recycler: use article sort everywhere
Use the native MediaStore sort of using the characters after an article [if present] everywhere when sorting is done. Yes, this is still dumb and non-local, but if I want to add fast-scrolling to the library view I will have to keep consistency across each sort.
This commit is contained in:
parent
e7d3dd0a98
commit
2f29950725
4 changed files with 59 additions and 35 deletions
|
@ -101,7 +101,7 @@ class MusicLoader(private val context: Context) {
|
|||
Albums._ID, // 0
|
||||
Albums.ALBUM, // 1
|
||||
Albums.ARTIST, // 2
|
||||
Albums.FIRST_YEAR, // 4
|
||||
Albums.LAST_YEAR, // 4
|
||||
),
|
||||
null, null,
|
||||
Albums.DEFAULT_SORT_ORDER
|
||||
|
@ -114,7 +114,7 @@ class MusicLoader(private val context: Context) {
|
|||
val idIndex = cursor.getColumnIndexOrThrow(Albums._ID)
|
||||
val nameIndex = cursor.getColumnIndexOrThrow(Albums.ALBUM)
|
||||
val artistNameIndex = cursor.getColumnIndexOrThrow(Albums.ARTIST)
|
||||
val yearIndex = cursor.getColumnIndexOrThrow(Albums.FIRST_YEAR)
|
||||
val yearIndex = cursor.getColumnIndexOrThrow(Albums.LAST_YEAR)
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
val id = cursor.getLong(idIndex)
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.oxycblt.auxio.music.Song
|
|||
* off the given sorting mode.
|
||||
* @property iconRes The icon for this [SortMode]
|
||||
* @author OxygenCobalt
|
||||
* TODO: Make SortMode use title case [skip the/a(n)]
|
||||
*/
|
||||
enum class SortMode(@DrawableRes val iconRes: Int) {
|
||||
// Icons for each mode are assigned to the enums themselves
|
||||
|
@ -32,11 +33,15 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
|||
fun getSortedGenreList(genres: List<Genre>): List<Genre> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> genres.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.resolvedName }
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.resolvedName.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
ALPHA_DOWN -> genres.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.resolvedName }
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.resolvedName.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
else -> genres
|
||||
|
@ -51,11 +56,15 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
|||
fun getSortedArtistList(artists: List<Artist>): List<Artist> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> artists.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
ALPHA_DOWN -> artists.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
else -> artists
|
||||
|
@ -70,11 +79,15 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
|||
fun getSortedAlbumList(albums: List<Album>): List<Album> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> albums.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
ALPHA_DOWN -> albums.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
NUMERIC_UP -> albums.sortedBy { it.year }
|
||||
|
@ -92,11 +105,15 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
|||
fun getSortedSongList(songs: List<Song>): List<Song> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> songs.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
ALPHA_DOWN -> songs.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
NUMERIC_UP -> songs.sortedWith(compareByDescending { it.track })
|
||||
|
@ -114,11 +131,15 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
|||
fun getSortedArtistSongList(songs: List<Song>): List<Song> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> songs.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
ALPHA_DOWN -> songs.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) {
|
||||
it.name.sliceArticle()
|
||||
}
|
||||
)
|
||||
|
||||
NUMERIC_UP -> {
|
||||
|
@ -130,6 +151,7 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
|||
|
||||
list
|
||||
}
|
||||
|
||||
NUMERIC_DOWN -> {
|
||||
val list = mutableListOf<Song>()
|
||||
|
||||
|
@ -205,3 +227,24 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
|||
fun ImageButton.bindSortIcon(mode: SortMode) {
|
||||
setImageResource(mode.iconRes)
|
||||
}
|
||||
|
||||
/**
|
||||
* Slice a string so that any preceding articles like The/A(n) are truncated.
|
||||
* This is hilariously anglo-centric, but its mostly for MediaStore compat and hopefully
|
||||
* shouldn't run with other languages.
|
||||
*/
|
||||
fun String.sliceArticle(): String {
|
||||
if (length > 5 && startsWith("the ", true)) {
|
||||
return slice(4..lastIndex)
|
||||
}
|
||||
|
||||
if (length > 4 && startsWith("an ", true)) {
|
||||
return slice(3..lastIndex)
|
||||
}
|
||||
|
||||
if (length > 3 && startsWith("a ", true)) {
|
||||
return slice(2..lastIndex)
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import kotlin.math.roundToInt
|
|||
* fast-scrollers, this one displays indicators and a thumb instead of simply a scroll bar.
|
||||
* This code is fundamentally an adaptation of Reddit's IndicatorFastScroll, albeit specialized
|
||||
* towards Auxio. The original library is here: https://github.com/reddit/IndicatorFastScroll/
|
||||
* TODO: Make this update with data.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class FastScrollView @JvmOverloads constructor(
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.oxycblt.auxio.databinding.FragmentSongsBinding
|
|||
import org.oxycblt.auxio.logD
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.recycler.sliceArticle
|
||||
import org.oxycblt.auxio.ui.getSpans
|
||||
import org.oxycblt.auxio.ui.newMenu
|
||||
|
||||
|
@ -56,7 +57,8 @@ class SongsFragment : Fragment() {
|
|||
}
|
||||
|
||||
binding.songFastScroll.setup(binding.songRecycler) { pos ->
|
||||
val char = musicStore.songs[pos].name.first
|
||||
// Get the first character [respecting articles]
|
||||
val char = musicStore.songs[pos].name.sliceArticle().first().uppercaseChar()
|
||||
|
||||
if (char.isDigit()) '#' else char
|
||||
}
|
||||
|
@ -65,26 +67,4 @@ class SongsFragment : Fragment() {
|
|||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumb shortcut for getting the first letter in a string, while regarding certain
|
||||
* semantics when it comes to articles.
|
||||
*/
|
||||
private val String.first: Char get() {
|
||||
// If the name actually starts with "The"/"A"/"An", get the character *after* that word.
|
||||
// Yes, this is stupidly english centric but it wont run with other languages.
|
||||
if (length > 5 && startsWith("the ", true)) {
|
||||
return get(4).uppercaseChar()
|
||||
}
|
||||
|
||||
if (length > 3 && startsWith("a ", true)) {
|
||||
return get(2).uppercaseChar()
|
||||
}
|
||||
|
||||
if (length > 4 && startsWith("an ", true)) {
|
||||
return get(3).uppercaseChar()
|
||||
}
|
||||
|
||||
return get(0).uppercaseChar()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue