ui: clean up dead code
Clean up the last remaining legacy SortMode remnants. Also reformat all ViewHolder IDs to be properly unique and sequential.
This commit is contained in:
parent
c9dd3b97a2
commit
08169b6167
16 changed files with 160 additions and 340 deletions
|
@ -23,7 +23,6 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.home.LibSortMode
|
||||
import org.oxycblt.auxio.music.ActionHeader
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
|
@ -88,7 +87,7 @@ class DetailViewModel : ViewModel() {
|
|||
)
|
||||
)
|
||||
|
||||
data.addAll(LibSortMode.ASCENDING.sortGenre(curGenre.value!!))
|
||||
data.addAll(SortMode.ASCENDING.sortGenre(curGenre.value!!))
|
||||
|
||||
mGenreData.value = data
|
||||
}
|
||||
|
@ -108,7 +107,7 @@ class DetailViewModel : ViewModel() {
|
|||
)
|
||||
)
|
||||
|
||||
data.addAll(LibSortMode.YEAR.sortAlbums(artist.albums))
|
||||
data.addAll(SortMode.YEAR.sortAlbums(artist.albums))
|
||||
|
||||
data.add(
|
||||
ActionHeader(
|
||||
|
@ -121,7 +120,7 @@ class DetailViewModel : ViewModel() {
|
|||
)
|
||||
)
|
||||
|
||||
data.addAll(LibSortMode.YEAR.sortArtist(artist))
|
||||
data.addAll(SortMode.YEAR.sortArtist(artist))
|
||||
|
||||
mArtistData.value = data.toList()
|
||||
}
|
||||
|
@ -144,7 +143,7 @@ class DetailViewModel : ViewModel() {
|
|||
)
|
||||
)
|
||||
|
||||
data.addAll(LibSortMode.ASCENDING.sortAlbum(curAlbum.value!!))
|
||||
data.addAll(SortMode.ASCENDING.sortAlbum(curAlbum.value!!))
|
||||
|
||||
mAlbumData.value = data
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ class AlbumDetailAdapter(
|
|||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (getItem(position)) {
|
||||
is Album -> ALBUM_HEADER_ITEM_TYPE
|
||||
is Album -> ALBUM_DETAIL_ITEM_TYPE
|
||||
is ActionHeader -> ActionHeaderViewHolder.ITEM_TYPE
|
||||
is Song -> ALBUM_SONG_ITEM_TYPE
|
||||
|
||||
|
@ -63,7 +63,7 @@ class AlbumDetailAdapter(
|
|||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ALBUM_HEADER_ITEM_TYPE -> AlbumHeaderViewHolder(
|
||||
ALBUM_DETAIL_ITEM_TYPE -> AlbumDetailViewHolder(
|
||||
ItemDetailBinding.inflate(parent.context.inflater)
|
||||
)
|
||||
|
||||
|
@ -81,7 +81,7 @@ class AlbumDetailAdapter(
|
|||
val item = getItem(position)
|
||||
|
||||
when (item) {
|
||||
is Album -> (holder as AlbumHeaderViewHolder).bind(item)
|
||||
is Album -> (holder as AlbumDetailViewHolder).bind(item)
|
||||
is Song -> (holder as AlbumSongViewHolder).bind(item)
|
||||
is ActionHeader -> (holder as ActionHeaderViewHolder).bind(item)
|
||||
|
||||
|
@ -132,7 +132,7 @@ class AlbumDetailAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
inner class AlbumHeaderViewHolder(
|
||||
inner class AlbumDetailViewHolder(
|
||||
private val binding: ItemDetailBinding
|
||||
) : BaseViewHolder<Album>(binding) {
|
||||
|
||||
|
@ -188,7 +188,7 @@ class AlbumDetailAdapter(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val ALBUM_HEADER_ITEM_TYPE = 0xA007
|
||||
const val ALBUM_SONG_ITEM_TYPE = 0xA008
|
||||
const val ALBUM_DETAIL_ITEM_TYPE = 0xA006
|
||||
const val ALBUM_SONG_ITEM_TYPE = 0xA007
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class ArtistDetailAdapter(
|
|||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (getItem(position)) {
|
||||
is Artist -> ARTIST_HEADER_ITEM_TYPE
|
||||
is Artist -> ARTIST_DETAIL_ITEM_TYPE
|
||||
is Album -> ARTIST_ALBUM_ITEM_TYPE
|
||||
is Song -> ARTIST_SONG_ITEM_TYPE
|
||||
is Header -> HeaderViewHolder.ITEM_TYPE
|
||||
|
@ -71,7 +71,7 @@ class ArtistDetailAdapter(
|
|||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ARTIST_HEADER_ITEM_TYPE -> ArtistHeaderViewHolder(
|
||||
ARTIST_DETAIL_ITEM_TYPE -> ArtistDetailViewHolder(
|
||||
ItemDetailBinding.inflate(parent.context.inflater)
|
||||
)
|
||||
|
||||
|
@ -95,7 +95,7 @@ class ArtistDetailAdapter(
|
|||
val item = getItem(position)
|
||||
|
||||
when (item) {
|
||||
is Artist -> (holder as ArtistHeaderViewHolder).bind(item)
|
||||
is Artist -> (holder as ArtistDetailViewHolder).bind(item)
|
||||
is Album -> (holder as ArtistAlbumViewHolder).bind(item)
|
||||
is Song -> (holder as ArtistSongViewHolder).bind(item)
|
||||
is Header -> (holder as HeaderViewHolder).bind(item)
|
||||
|
@ -181,7 +181,7 @@ class ArtistDetailAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
inner class ArtistHeaderViewHolder(
|
||||
inner class ArtistDetailViewHolder(
|
||||
private val binding: ItemDetailBinding
|
||||
) : BaseViewHolder<Artist>(binding) {
|
||||
|
||||
|
@ -241,8 +241,8 @@ class ArtistDetailAdapter(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val ARTIST_HEADER_ITEM_TYPE = 0xA009
|
||||
const val ARTIST_ALBUM_ITEM_TYPE = 0xA00A
|
||||
const val ARTIST_SONG_ITEM_TYPE = 0xA00C
|
||||
const val ARTIST_DETAIL_ITEM_TYPE = 0xA008
|
||||
const val ARTIST_ALBUM_ITEM_TYPE = 0xA009
|
||||
const val ARTIST_SONG_ITEM_TYPE = 0xA00A
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ class GenreDetailAdapter(
|
|||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (getItem(position)) {
|
||||
is Genre -> GENRE_HEADER_ITEM_TYPE
|
||||
is Genre -> GENRE_DETAIL_ITEM_TYPE
|
||||
is ActionHeader -> ActionHeaderViewHolder.ITEM_TYPE
|
||||
is Song -> GENRE_SONG_ITEM_TYPE
|
||||
|
||||
|
@ -61,7 +61,7 @@ class GenreDetailAdapter(
|
|||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
GENRE_HEADER_ITEM_TYPE -> GenreHeaderViewHolder(
|
||||
GENRE_DETAIL_ITEM_TYPE -> GenreDetailViewHolder(
|
||||
ItemDetailBinding.inflate(parent.context.inflater)
|
||||
)
|
||||
|
||||
|
@ -79,7 +79,7 @@ class GenreDetailAdapter(
|
|||
val item = getItem(position)
|
||||
|
||||
when (item) {
|
||||
is Genre -> (holder as GenreHeaderViewHolder).bind(item)
|
||||
is Genre -> (holder as GenreDetailViewHolder).bind(item)
|
||||
is ActionHeader -> (holder as ActionHeaderViewHolder).bind(item)
|
||||
is Song -> (holder as GenreSongViewHolder).bind(item)
|
||||
else -> {}
|
||||
|
@ -128,7 +128,7 @@ class GenreDetailAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
inner class GenreHeaderViewHolder(
|
||||
inner class GenreDetailViewHolder(
|
||||
private val binding: ItemDetailBinding
|
||||
) : BaseViewHolder<Genre>(binding) {
|
||||
override fun onBind(data: Genre) {
|
||||
|
@ -173,7 +173,7 @@ class GenreDetailAdapter(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val GENRE_HEADER_ITEM_TYPE = 0xA00D
|
||||
const val GENRE_SONG_ITEM_TYPE = 0xA00E
|
||||
const val GENRE_DETAIL_ITEM_TYPE = 0xA00B
|
||||
const val GENRE_SONG_ITEM_TYPE = 0xA00C
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.oxycblt.auxio.music.Artist
|
|||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
import org.oxycblt.auxio.util.applyEdge
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logE
|
||||
|
@ -93,7 +94,7 @@ class HomeFragment : Fragment() {
|
|||
item.isChecked = true
|
||||
|
||||
homeModel.updateCurrentSort(
|
||||
requireNotNull(LibSortMode.fromId(item.itemId))
|
||||
requireNotNull(SortMode.fromId(item.itemId))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -220,7 +221,7 @@ class HomeFragment : Fragment() {
|
|||
|
||||
private fun updateSortMenu(
|
||||
item: MenuItem,
|
||||
toHighlight: LibSortMode,
|
||||
toHighlight: SortMode,
|
||||
isVisible: (Int) -> Boolean = { true }
|
||||
) {
|
||||
for (option in item.subMenu) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.oxycblt.auxio.music.Genre
|
|||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
|
||||
/**
|
||||
* The ViewModel for managing [HomeFragment]'s data and sorting modes.
|
||||
|
@ -55,16 +56,16 @@ class HomeViewModel : ViewModel() {
|
|||
private val mCurTab = MutableLiveData(mTabs.value!![0])
|
||||
val curTab: LiveData<DisplayMode> = mCurTab
|
||||
|
||||
var genreSortMode = LibSortMode.ASCENDING
|
||||
var genreSortMode = SortMode.ASCENDING
|
||||
private set
|
||||
|
||||
var artistSortMode = LibSortMode.ASCENDING
|
||||
var artistSortMode = SortMode.ASCENDING
|
||||
private set
|
||||
|
||||
var albumSortMode = LibSortMode.ASCENDING
|
||||
var albumSortMode = SortMode.ASCENDING
|
||||
private set
|
||||
|
||||
var songSortMode = LibSortMode.ASCENDING
|
||||
var songSortMode = SortMode.ASCENDING
|
||||
private set
|
||||
|
||||
private val musicStore = MusicStore.getInstance()
|
||||
|
@ -86,9 +87,9 @@ class HomeViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Update the currently displayed item's [LibSortMode].
|
||||
* Update the currently displayed item's [SortMode].
|
||||
*/
|
||||
fun updateCurrentSort(sort: LibSortMode) {
|
||||
fun updateCurrentSort(sort: SortMode) {
|
||||
when (mCurTab.value) {
|
||||
DisplayMode.SHOW_SONGS -> {
|
||||
songSortMode = sort
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Auxio Project
|
||||
* LibSortMode.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.home
|
||||
|
||||
import androidx.annotation.IdRes
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.ui.sliceArticle
|
||||
|
||||
/**
|
||||
* The enum for the current sort state.
|
||||
* This enum is semantic depending on the context it is used. Documentation describing each
|
||||
* sorting functions behavior can be found in the function definition.
|
||||
* @param itemId Menu ID associated with this enum
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
enum class LibSortMode(@IdRes val itemId: Int) {
|
||||
ASCENDING(R.id.option_sort_asc),
|
||||
DESCENDING(R.id.option_sort_dsc),
|
||||
ARTIST(R.id.option_sort_artist),
|
||||
ALBUM(R.id.option_sort_album),
|
||||
YEAR(R.id.option_sort_year);
|
||||
|
||||
/**
|
||||
* Sort a list of songs.
|
||||
*
|
||||
* **Behavior:**
|
||||
* - [ASCENDING] & [DESCENDING]: See [sortModels]
|
||||
* - [ARTIST]: Grouped by album and then sorted [ASCENDING] based off the artist name.
|
||||
* - [ALBUM]: Grouped by album and sorted [ASCENDING]
|
||||
* - [YEAR]: Grouped by album and sorted by year
|
||||
*
|
||||
* The grouping mode for songs in an album will be by track, [ASCENDING].
|
||||
* @see sortAlbums
|
||||
*/
|
||||
fun sortSongs(songs: Collection<Song>): List<Song> {
|
||||
return when (this) {
|
||||
ASCENDING, DESCENDING -> sortModels(songs)
|
||||
|
||||
else -> sortAlbums(songs.groupBy { it.album }.keys).flatMap { album ->
|
||||
ASCENDING.sortAlbum(album)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort a list of albums.
|
||||
*
|
||||
* **Behavior:**
|
||||
* - [ASCENDING] & [DESCENDING]: See [sortModels]
|
||||
* - [ARTIST]: Grouped by artist and sorted [ASCENDING]
|
||||
* - [ALBUM]: [ASCENDING]
|
||||
* - [YEAR]: Sorted by year
|
||||
*
|
||||
* The grouping mode for albums in an artist will be [YEAR].
|
||||
*/
|
||||
fun sortAlbums(albums: Collection<Album>): List<Album> {
|
||||
return when (this) {
|
||||
ASCENDING, DESCENDING -> sortModels(albums)
|
||||
|
||||
ARTIST -> ASCENDING.sortModels(albums.groupBy { it.artist }.keys)
|
||||
.flatMap { YEAR.sortAlbums(it.albums) }
|
||||
|
||||
ALBUM -> ASCENDING.sortModels(albums)
|
||||
|
||||
YEAR -> albums.sortedByDescending { it.year }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort a list of generic [BaseModel] instances.
|
||||
*
|
||||
* **Behavior:**
|
||||
* - [ASCENDING]: Sorted by name, ascending
|
||||
* - [DESCENDING]: Sorted by name, descending
|
||||
* - Same list is returned otherwise.
|
||||
*
|
||||
* Names will be treated as case-insensitive. Articles like "the" and "a" will be skipped
|
||||
* to line up with MediaStore behavior.
|
||||
*/
|
||||
fun <T : BaseModel> sortModels(models: Collection<T>): List<T> {
|
||||
return when (this) {
|
||||
ASCENDING -> models.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { model ->
|
||||
model.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
DESCENDING -> models.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { model ->
|
||||
model.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
else -> models.toList()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the songs in an album.
|
||||
*
|
||||
* **Behavior:**
|
||||
* - [ASCENDING]: By track, ascending
|
||||
* - [DESCENDING]: By track, descending
|
||||
* - Same song list is returned otherwise.
|
||||
*/
|
||||
fun sortAlbum(album: Album): List<Song> {
|
||||
return when (this) {
|
||||
ASCENDING -> album.songs.sortedBy { it.track }
|
||||
DESCENDING -> album.songs.sortedByDescending { it.track }
|
||||
else -> album.songs
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the songs in an artist.
|
||||
* @see sortSongs
|
||||
*/
|
||||
fun sortArtist(artist: Artist): List<Song> {
|
||||
return sortSongs(artist.songs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the songs in a genre.
|
||||
* @see sortSongs
|
||||
*/
|
||||
fun sortGenre(genre: Genre): List<Song> {
|
||||
return sortSongs(genre.songs)
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Convert a menu [id] to an instance of [LibSortMode].
|
||||
*/
|
||||
fun fromId(@IdRes id: Int): LibSortMode? {
|
||||
return when (id) {
|
||||
ASCENDING.itemId -> ASCENDING
|
||||
DESCENDING.itemId -> DESCENDING
|
||||
ARTIST.itemId -> ARTIST
|
||||
ALBUM.itemId -> ALBUM
|
||||
YEAR.itemId -> YEAR
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -331,9 +331,8 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
|||
* Add an [Album] to the user queue
|
||||
*/
|
||||
fun addToUserQueue(album: Album) {
|
||||
val songs = SortMode.NUMERIC_DOWN.getSortedSongList(album.songs)
|
||||
|
||||
playbackManager.addToUserQueue(songs)
|
||||
// TODO: Make this reflect the sort mode
|
||||
playbackManager.addToUserQueue(SortMode.ASCENDING.sortAlbum(album))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -169,7 +169,6 @@ class QueueAdapter(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val QUEUE_SONG_ITEM_TYPE = 0xA005
|
||||
const val USER_QUEUE_HEADER_ITEM_TYPE = 0xA006
|
||||
const val QUEUE_SONG_ITEM_TYPE = 0xA00D
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.oxycblt.auxio.music.MusicStore
|
|||
import org.oxycblt.auxio.music.Parent
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logE
|
||||
|
||||
|
@ -731,21 +732,21 @@ class PlaybackStateManager private constructor() {
|
|||
* Create an ordered queue based on an [Album].
|
||||
*/
|
||||
private fun orderSongsInAlbum(album: Album): MutableList<Song> {
|
||||
return settingsManager.albumSortMode.getSortedSongList(album.songs).toMutableList()
|
||||
return SortMode.ASCENDING.sortAlbum(album).toMutableList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ordered queue based on an [Artist].
|
||||
*/
|
||||
private fun orderSongsInArtist(artist: Artist): MutableList<Song> {
|
||||
return settingsManager.artistSortMode.getSortedArtistSongList(artist.songs).toMutableList()
|
||||
return SortMode.YEAR.sortArtist(artist).toMutableList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ordered queue based on a [Genre].
|
||||
*/
|
||||
private fun orderSongsInGenre(genre: Genre): MutableList<Song> {
|
||||
return settingsManager.genreSortMode.getSortedSongList(genre.songs).toMutableList()
|
||||
return SortMode.ASCENDING.sortGenre(genre).toMutableList()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.oxycblt.auxio.accent.ACCENTS
|
|||
import org.oxycblt.auxio.accent.Accent
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.ui.DisplayMode
|
||||
import org.oxycblt.auxio.ui.SortMode
|
||||
|
||||
/**
|
||||
* Wrapper around the [SharedPreferences] class that writes & reads values without a context.
|
||||
|
@ -114,33 +113,6 @@ class SettingsManager private constructor(context: Context) :
|
|||
val pauseOnLoop: Boolean
|
||||
get() = sharedPrefs.getBoolean(KEY_LOOP_PAUSE, false)
|
||||
|
||||
var albumSortMode: SortMode
|
||||
get() = sharedPrefs.getData(KEY_ALBUM_SORT_MODE, SortMode::fromInt) ?: SortMode.NUMERIC_DOWN
|
||||
set(value) {
|
||||
sharedPrefs.edit {
|
||||
putInt(KEY_ALBUM_SORT_MODE, value.toInt())
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
var artistSortMode: SortMode
|
||||
get() = sharedPrefs.getData(KEY_ARTIST_SORT_MODE, SortMode::fromInt) ?: SortMode.NUMERIC_DOWN
|
||||
set(value) {
|
||||
sharedPrefs.edit {
|
||||
putInt(KEY_ARTIST_SORT_MODE, value.toInt())
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
var genreSortMode: SortMode
|
||||
get() = sharedPrefs.getData(KEY_GENRE_SORT_MODE, SortMode::fromInt) ?: SortMode.ALPHA_DOWN
|
||||
set(value) {
|
||||
sharedPrefs.edit {
|
||||
putInt(KEY_GENRE_SORT_MODE, value.toInt())
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
/** The current filter mode of the search tab */
|
||||
var searchFilterMode: DisplayMode?
|
||||
get() = sharedPrefs.getData(KEY_SEARCH_FILTER_MODE, DisplayMode::fromSearchInt)
|
||||
|
|
|
@ -29,7 +29,7 @@ enum class DisplayMode {
|
|||
SHOW_SONGS;
|
||||
|
||||
companion object {
|
||||
private const val CONST_SHOW_ALL = 0xA107
|
||||
private const val CONST_NULL = 0xA107
|
||||
private const val CONST_SHOW_GENRES = 0xA108
|
||||
private const val CONST_SHOW_ARTISTS = 0xA109
|
||||
private const val CONST_SHOW_ALBUMS = 0xA10A
|
||||
|
@ -41,7 +41,7 @@ enum class DisplayMode {
|
|||
SHOW_ALBUMS -> CONST_SHOW_ALBUMS
|
||||
SHOW_ARTISTS -> CONST_SHOW_ARTISTS
|
||||
SHOW_GENRES -> CONST_SHOW_GENRES
|
||||
null -> CONST_SHOW_ALL
|
||||
null -> CONST_NULL
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,125 +18,146 @@
|
|||
|
||||
package org.oxycblt.auxio.ui
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.IdRes
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Song
|
||||
|
||||
/**
|
||||
* The legacy enum for sorting. This is set to be removed soon.
|
||||
* @property iconRes The icon for this [SortMode]
|
||||
* The enum for the current sort state.
|
||||
* This enum is semantic depending on the context it is used. Documentation describing each
|
||||
* sorting functions behavior can be found in the function definition.
|
||||
* @param itemId Menu ID associated with this enum
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
enum class SortMode(@DrawableRes val iconRes: Int) {
|
||||
// Icons for each mode are assigned to the enums themselves
|
||||
NONE(R.drawable.ic_sort),
|
||||
ALPHA_UP(R.drawable.ic_sort),
|
||||
ALPHA_DOWN(R.drawable.ic_sort),
|
||||
NUMERIC_UP(R.drawable.ic_sort),
|
||||
NUMERIC_DOWN(R.drawable.ic_sort);
|
||||
enum class SortMode(@IdRes val itemId: Int) {
|
||||
ASCENDING(R.id.option_sort_asc),
|
||||
DESCENDING(R.id.option_sort_dsc),
|
||||
ARTIST(R.id.option_sort_artist),
|
||||
ALBUM(R.id.option_sort_album),
|
||||
YEAR(R.id.option_sort_year);
|
||||
|
||||
/**
|
||||
* Get a sorted list of songs for a SortMode. Supports alpha + numeric sorting.
|
||||
* @param songs An unsorted list of songs.
|
||||
* @return The sorted list of songs.
|
||||
* Sort a list of songs.
|
||||
*
|
||||
* **Behavior:**
|
||||
* - [ASCENDING] & [DESCENDING]: See [sortModels]
|
||||
* - [ARTIST]: Grouped by album and then sorted [ASCENDING] based off the artist name.
|
||||
* - [ALBUM]: Grouped by album and sorted [ASCENDING]
|
||||
* - [YEAR]: Grouped by album and sorted by year
|
||||
*
|
||||
* The grouping mode for songs in an album will be by track, [ASCENDING].
|
||||
* @see sortAlbums
|
||||
*/
|
||||
fun getSortedSongList(songs: List<Song>): List<Song> {
|
||||
fun sortSongs(songs: Collection<Song>): List<Song> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> songs.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
ASCENDING, DESCENDING -> sortModels(songs)
|
||||
|
||||
else -> sortAlbums(songs.groupBy { it.album }.keys).flatMap { album ->
|
||||
ASCENDING.sortAlbum(album)
|
||||
}
|
||||
)
|
||||
|
||||
ALPHA_DOWN -> songs.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
NUMERIC_UP -> songs.sortedWith(compareByDescending { it.track })
|
||||
NUMERIC_DOWN -> songs.sortedWith(compareBy { it.track })
|
||||
|
||||
else -> songs
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a sorted list of songs with regards to an artist.
|
||||
* @param songs An unsorted list of songs
|
||||
* @return The sorted list of songs
|
||||
* Sort a list of albums.
|
||||
*
|
||||
* **Behavior:**
|
||||
* - [ASCENDING] & [DESCENDING]: See [sortModels]
|
||||
* - [ARTIST]: Grouped by artist and sorted [ASCENDING]
|
||||
* - [ALBUM]: [ASCENDING]
|
||||
* - [YEAR]: Sorted by year
|
||||
*
|
||||
* The grouping mode for albums in an artist will be [YEAR].
|
||||
*/
|
||||
fun getSortedArtistSongList(songs: List<Song>): List<Song> {
|
||||
fun sortAlbums(albums: Collection<Album>): List<Album> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> songs.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
ASCENDING, DESCENDING -> sortModels(albums)
|
||||
|
||||
ALPHA_DOWN -> songs.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
ARTIST -> ASCENDING.sortModels(albums.groupBy { it.artist }.keys)
|
||||
.flatMap { YEAR.sortAlbums(it.albums) }
|
||||
|
||||
NUMERIC_UP -> {
|
||||
val list = mutableListOf<Song>()
|
||||
ALBUM -> ASCENDING.sortModels(albums)
|
||||
|
||||
songs.groupBy { it.album }.entries.sortedBy { it.key.year }.forEach { entry ->
|
||||
list.addAll(entry.value.sortedWith(compareBy { it.track }))
|
||||
}
|
||||
|
||||
list
|
||||
}
|
||||
|
||||
NUMERIC_DOWN -> {
|
||||
val list = mutableListOf<Song>()
|
||||
|
||||
songs.groupBy { it.album }.entries.sortedWith(compareByDescending { it.key.year }).forEach { entry ->
|
||||
list.addAll(entry.value.sortedWith(compareBy { it.track }))
|
||||
}
|
||||
|
||||
list
|
||||
}
|
||||
|
||||
else -> songs
|
||||
YEAR -> albums.sortedByDescending { it.year }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the constant for this mode. Used to write a compressed variant to SettingsManager
|
||||
* @return The int constant for this mode.
|
||||
* Sort a list of generic [BaseModel] instances.
|
||||
*
|
||||
* **Behavior:**
|
||||
* - [ASCENDING]: Sorted by name, ascending
|
||||
* - [DESCENDING]: Sorted by name, descending
|
||||
* - Same list is returned otherwise.
|
||||
*
|
||||
* Names will be treated as case-insensitive. Articles like "the" and "a" will be skipped
|
||||
* to line up with MediaStore behavior.
|
||||
*/
|
||||
fun toInt(): Int {
|
||||
fun <T : BaseModel> sortModels(models: Collection<T>): List<T> {
|
||||
return when (this) {
|
||||
NONE -> CONST_NONE
|
||||
ALPHA_UP -> CONST_ALPHA_UP
|
||||
ALPHA_DOWN -> CONST_ALPHA_DOWN
|
||||
NUMERIC_UP -> CONST_NUMERIC_UP
|
||||
NUMERIC_DOWN -> CONST_NUMERIC_DOWN
|
||||
ASCENDING -> models.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { model ->
|
||||
model.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
DESCENDING -> models.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { model ->
|
||||
model.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
else -> models.toList()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the songs in an album.
|
||||
*
|
||||
* **Behavior:**
|
||||
* - [ASCENDING]: By track, ascending
|
||||
* - [DESCENDING]: By track, descending
|
||||
* - Same song list is returned otherwise.
|
||||
*/
|
||||
fun sortAlbum(album: Album): List<Song> {
|
||||
return when (this) {
|
||||
ASCENDING -> album.songs.sortedBy { it.track }
|
||||
DESCENDING -> album.songs.sortedByDescending { it.track }
|
||||
else -> album.songs
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the songs in an artist.
|
||||
* @see sortSongs
|
||||
*/
|
||||
fun sortArtist(artist: Artist): List<Song> {
|
||||
return sortSongs(artist.songs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the songs in a genre.
|
||||
* @see sortSongs
|
||||
*/
|
||||
fun sortGenre(genre: Genre): List<Song> {
|
||||
return sortSongs(genre.songs)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CONST_NONE = 0xA10C
|
||||
const val CONST_ALPHA_UP = 0xA10D
|
||||
const val CONST_ALPHA_DOWN = 0xA10E
|
||||
const val CONST_NUMERIC_UP = 0xA10F
|
||||
const val CONST_NUMERIC_DOWN = 0xA110
|
||||
|
||||
/**
|
||||
* Get an enum for an int constant
|
||||
* @return The [SortMode] if the constant is valid, null otherwise.
|
||||
* Convert a menu [id] to an instance of [SortMode].
|
||||
*/
|
||||
fun fromInt(value: Int): SortMode? {
|
||||
return when (value) {
|
||||
CONST_NONE -> NONE
|
||||
CONST_ALPHA_UP -> ALPHA_UP
|
||||
CONST_ALPHA_DOWN -> ALPHA_DOWN
|
||||
CONST_NUMERIC_UP -> NUMERIC_UP
|
||||
CONST_NUMERIC_DOWN -> NUMERIC_DOWN
|
||||
|
||||
fun fromId(@IdRes id: Int): SortMode? {
|
||||
return when (id) {
|
||||
ASCENDING.itemId -> ASCENDING
|
||||
DESCENDING.itemId -> DESCENDING
|
||||
ARTIST.itemId -> ARTIST
|
||||
ALBUM.itemId -> ALBUM
|
||||
YEAR.itemId -> YEAR
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -266,7 +266,7 @@ class ActionHeaderViewHolder private constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_TYPE = 0xA999 // TODO: Give this an ID
|
||||
const val ITEM_TYPE = 0xA005
|
||||
|
||||
/**
|
||||
* Create an instance of [ActionHeaderViewHolder]
|
||||
|
|
|
@ -45,18 +45,17 @@ To prevent any strange bugs, all integer representations must be unique. A table
|
|||
0xA002 | ArtistViewHolder
|
||||
0xA003 | GenreViewHolder
|
||||
0xA004 | HeaderViewHolder
|
||||
0xA005 | ActionHeaderViewHolder
|
||||
|
||||
0xA005 | QueueSongViewHolder
|
||||
0xA006 | UserQueueHeaderViewHolder
|
||||
0xA005 | AlbumDetailViewHolder
|
||||
0xA006 | AlbumSongViewHolder
|
||||
0xA007 | ArtistDetailViewHolder
|
||||
0xA008 | ArtistAlbumViewHolder
|
||||
0xA009 | ArtistSongViewHolder
|
||||
0xA010 | GenreDetailViewHolder
|
||||
0xA011 | GenreSongViewHolder
|
||||
|
||||
0xA007 | AlbumHeaderViewHolder
|
||||
0xA008 | AlbumSongViewHolder
|
||||
0xA009 | ArtistHeaderViewHolder
|
||||
0xA00A | ArtistAlbumViewHolder
|
||||
0xA00B | ArtistSongHeaderViewHolder
|
||||
0xA00C | ArtistSongViewHolder
|
||||
0xA00D | GenreHeaderViewHolder
|
||||
0xA00E | GenreSongViewHolder
|
||||
0xA00A | QueueSongViewHolder
|
||||
|
||||
0xA0A0 | Auxio notification code
|
||||
0xA0C0 | Auxio request code
|
||||
|
@ -77,12 +76,6 @@ To prevent any strange bugs, all integer representations must be unique. A table
|
|||
0xA109 | DisplayMode.SHOW_ARTISTS
|
||||
0xA10A | DisplayMode.SHOW_ALBUMS
|
||||
0xA10B | DisplayMode.SHOW_SONGS
|
||||
|
||||
0xA10C | SortMode.NONE
|
||||
0xA10D | SortMode.ALPHA_UP
|
||||
0xA10E | SortMode.ALPHA_DOWN
|
||||
0xA10F | SortMode.NUMERIC_UP
|
||||
0xA110 | SortMode.NUMERIC_DOWN
|
||||
```
|
||||
|
||||
#### Package structure overview
|
||||
|
|
Loading…
Reference in a new issue