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._ID, // 0
|
||||||
Albums.ALBUM, // 1
|
Albums.ALBUM, // 1
|
||||||
Albums.ARTIST, // 2
|
Albums.ARTIST, // 2
|
||||||
Albums.FIRST_YEAR, // 4
|
Albums.LAST_YEAR, // 4
|
||||||
),
|
),
|
||||||
null, null,
|
null, null,
|
||||||
Albums.DEFAULT_SORT_ORDER
|
Albums.DEFAULT_SORT_ORDER
|
||||||
|
@ -114,7 +114,7 @@ class MusicLoader(private val context: Context) {
|
||||||
val idIndex = cursor.getColumnIndexOrThrow(Albums._ID)
|
val idIndex = cursor.getColumnIndexOrThrow(Albums._ID)
|
||||||
val nameIndex = cursor.getColumnIndexOrThrow(Albums.ALBUM)
|
val nameIndex = cursor.getColumnIndexOrThrow(Albums.ALBUM)
|
||||||
val artistNameIndex = cursor.getColumnIndexOrThrow(Albums.ARTIST)
|
val artistNameIndex = cursor.getColumnIndexOrThrow(Albums.ARTIST)
|
||||||
val yearIndex = cursor.getColumnIndexOrThrow(Albums.FIRST_YEAR)
|
val yearIndex = cursor.getColumnIndexOrThrow(Albums.LAST_YEAR)
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
val id = cursor.getLong(idIndex)
|
val id = cursor.getLong(idIndex)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.oxycblt.auxio.music.Song
|
||||||
* off the given sorting mode.
|
* off the given sorting mode.
|
||||||
* @property iconRes The icon for this [SortMode]
|
* @property iconRes The icon for this [SortMode]
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
|
* TODO: Make SortMode use title case [skip the/a(n)]
|
||||||
*/
|
*/
|
||||||
enum class SortMode(@DrawableRes val iconRes: Int) {
|
enum class SortMode(@DrawableRes val iconRes: Int) {
|
||||||
// Icons for each mode are assigned to the enums themselves
|
// 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> {
|
fun getSortedGenreList(genres: List<Genre>): List<Genre> {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
ALPHA_UP -> genres.sortedWith(
|
ALPHA_UP -> genres.sortedWith(
|
||||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.resolvedName }
|
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||||
|
it.resolvedName.sliceArticle()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
ALPHA_DOWN -> genres.sortedWith(
|
ALPHA_DOWN -> genres.sortedWith(
|
||||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.resolvedName }
|
compareBy(String.CASE_INSENSITIVE_ORDER) {
|
||||||
|
it.resolvedName.sliceArticle()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> genres
|
else -> genres
|
||||||
|
@ -51,11 +56,15 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
||||||
fun getSortedArtistList(artists: List<Artist>): List<Artist> {
|
fun getSortedArtistList(artists: List<Artist>): List<Artist> {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
ALPHA_UP -> artists.sortedWith(
|
ALPHA_UP -> artists.sortedWith(
|
||||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||||
|
it.name.sliceArticle()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
ALPHA_DOWN -> artists.sortedWith(
|
ALPHA_DOWN -> artists.sortedWith(
|
||||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
|
compareBy(String.CASE_INSENSITIVE_ORDER) {
|
||||||
|
it.name.sliceArticle()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> artists
|
else -> artists
|
||||||
|
@ -70,11 +79,15 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
||||||
fun getSortedAlbumList(albums: List<Album>): List<Album> {
|
fun getSortedAlbumList(albums: List<Album>): List<Album> {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
ALPHA_UP -> albums.sortedWith(
|
ALPHA_UP -> albums.sortedWith(
|
||||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||||
|
it.name.sliceArticle()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
ALPHA_DOWN -> albums.sortedWith(
|
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 }
|
NUMERIC_UP -> albums.sortedBy { it.year }
|
||||||
|
@ -92,11 +105,15 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
||||||
fun getSortedSongList(songs: List<Song>): List<Song> {
|
fun getSortedSongList(songs: List<Song>): List<Song> {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
ALPHA_UP -> songs.sortedWith(
|
ALPHA_UP -> songs.sortedWith(
|
||||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||||
|
it.name.sliceArticle()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
ALPHA_DOWN -> songs.sortedWith(
|
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 })
|
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> {
|
fun getSortedArtistSongList(songs: List<Song>): List<Song> {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
ALPHA_UP -> songs.sortedWith(
|
ALPHA_UP -> songs.sortedWith(
|
||||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
compareByDescending(String.CASE_INSENSITIVE_ORDER) {
|
||||||
|
it.name.sliceArticle()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
ALPHA_DOWN -> songs.sortedWith(
|
ALPHA_DOWN -> songs.sortedWith(
|
||||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
|
compareBy(String.CASE_INSENSITIVE_ORDER) {
|
||||||
|
it.name.sliceArticle()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
NUMERIC_UP -> {
|
NUMERIC_UP -> {
|
||||||
|
@ -130,6 +151,7 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
||||||
|
|
||||||
list
|
list
|
||||||
}
|
}
|
||||||
|
|
||||||
NUMERIC_DOWN -> {
|
NUMERIC_DOWN -> {
|
||||||
val list = mutableListOf<Song>()
|
val list = mutableListOf<Song>()
|
||||||
|
|
||||||
|
@ -205,3 +227,24 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
|
||||||
fun ImageButton.bindSortIcon(mode: SortMode) {
|
fun ImageButton.bindSortIcon(mode: SortMode) {
|
||||||
setImageResource(mode.iconRes)
|
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.
|
* 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
|
* This code is fundamentally an adaptation of Reddit's IndicatorFastScroll, albeit specialized
|
||||||
* towards Auxio. The original library is here: https://github.com/reddit/IndicatorFastScroll/
|
* towards Auxio. The original library is here: https://github.com/reddit/IndicatorFastScroll/
|
||||||
|
* TODO: Make this update with data.
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class FastScrollView @JvmOverloads constructor(
|
class FastScrollView @JvmOverloads constructor(
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.oxycblt.auxio.databinding.FragmentSongsBinding
|
||||||
import org.oxycblt.auxio.logD
|
import org.oxycblt.auxio.logD
|
||||||
import org.oxycblt.auxio.music.MusicStore
|
import org.oxycblt.auxio.music.MusicStore
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
|
import org.oxycblt.auxio.recycler.sliceArticle
|
||||||
import org.oxycblt.auxio.ui.getSpans
|
import org.oxycblt.auxio.ui.getSpans
|
||||||
import org.oxycblt.auxio.ui.newMenu
|
import org.oxycblt.auxio.ui.newMenu
|
||||||
|
|
||||||
|
@ -56,7 +57,8 @@ class SongsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.songFastScroll.setup(binding.songRecycler) { pos ->
|
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
|
if (char.isDigit()) '#' else char
|
||||||
}
|
}
|
||||||
|
@ -65,26 +67,4 @@ class SongsFragment : Fragment() {
|
||||||
|
|
||||||
return binding.root
|
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