music: prepare sort tags
Prepare support for sort tags by reworking how sortName is structured. Instead of rawName and sortName, music must now implement rawName and rawSortName. rawSortName will be checked first, followed by will falling back to rawName.withoutArticle. This allows hard-coded tags to be neatly implemented while avoiding an immediate copy.
This commit is contained in:
parent
9921a39784
commit
e8f94564b7
4 changed files with 32 additions and 20 deletions
|
@ -58,7 +58,7 @@ class AlbumListFragment : HomeListFragment<Album>() {
|
|||
// Change how we display the popup depending on the mode.
|
||||
return when (homeModel.getSortForDisplay(DisplayMode.SHOW_ALBUMS).mode) {
|
||||
// By Name -> Use Name
|
||||
is Sort.Mode.ByName -> album.sortName.first().uppercase()
|
||||
is Sort.Mode.ByName -> album.sortName?.run { first().uppercase() }
|
||||
|
||||
// By Artist -> Use Artist Name
|
||||
is Sort.Mode.ByArtist -> album.artist.sortName?.run { first().uppercase() }
|
||||
|
|
|
@ -62,13 +62,13 @@ class SongListFragment : HomeListFragment<Song>() {
|
|||
// based off the names of the parent objects and not the child objects.
|
||||
return when (homeModel.getSortForDisplay(DisplayMode.SHOW_SONGS).mode) {
|
||||
// Name -> Use name
|
||||
is Sort.Mode.ByName -> song.sortName.first().uppercase()
|
||||
is Sort.Mode.ByName -> song.sortName?.run { first().uppercase() }
|
||||
|
||||
// Artist -> Use Artist Name
|
||||
is Sort.Mode.ByArtist -> song.album.artist.sortName?.run { first().uppercase() }
|
||||
|
||||
// Album -> Use Album Name
|
||||
is Sort.Mode.ByAlbum -> song.album.sortName.first().uppercase()
|
||||
is Sort.Mode.ByAlbum -> song.album.sortName?.run { first().uppercase() }
|
||||
|
||||
// Year -> Use Full Year
|
||||
is Sort.Mode.ByYear -> song.album.year?.toString()
|
||||
|
|
|
@ -33,8 +33,18 @@ sealed class Music : Item() {
|
|||
/** The raw name of this item. Null if unknown. */
|
||||
abstract val rawName: String?
|
||||
|
||||
/** The name of this item used for sorting. Null if unknown. */
|
||||
abstract val sortName: String?
|
||||
/** The raw sorting name of this item. Null if not present. */
|
||||
abstract val rawSortName: String?
|
||||
|
||||
/**
|
||||
* The name of this item used for sorting. This will first use the sort tag for the item,
|
||||
* followed by the name without a preceding article (The/A/An). In the case that the item has no
|
||||
* name, this returns null.
|
||||
*
|
||||
* This should not be used outside of sorting and fast-scrolling.
|
||||
*/
|
||||
val sortName: String?
|
||||
get() = rawSortName ?: rawName?.withoutArticle
|
||||
|
||||
/**
|
||||
* Resolve a name from it's raw form to a form suitable to be shown in a ui. Ex. "unknown" would
|
||||
|
@ -99,8 +109,8 @@ data class Song(
|
|||
return result
|
||||
}
|
||||
|
||||
override val sortName: String
|
||||
get() = rawName.withoutArticle
|
||||
override val rawSortName: String?
|
||||
get() = null
|
||||
|
||||
override fun resolveName(context: Context) = rawName
|
||||
|
||||
|
@ -196,8 +206,8 @@ data class Album(
|
|||
return result
|
||||
}
|
||||
|
||||
override val sortName: String
|
||||
get() = rawName.withoutArticle
|
||||
override val rawSortName: String?
|
||||
get() = null
|
||||
|
||||
override fun resolveName(context: Context) = rawName
|
||||
|
||||
|
@ -238,8 +248,8 @@ data class Artist(
|
|||
override val id: Long
|
||||
get() = (rawName ?: MediaStore.UNKNOWN_STRING).hashCode().toLong()
|
||||
|
||||
override val sortName: String?
|
||||
get() = rawName?.withoutArticle
|
||||
override val rawSortName: String?
|
||||
get() = null
|
||||
|
||||
override fun resolveName(context: Context) = rawName ?: context.getString(R.string.def_artist)
|
||||
|
||||
|
@ -258,8 +268,8 @@ data class Genre(override val rawName: String?, override val songs: List<Song>)
|
|||
override val id: Long
|
||||
get() = (rawName ?: MediaStore.UNKNOWN_STRING).hashCode().toLong()
|
||||
|
||||
override val sortName: String?
|
||||
get() = rawName
|
||||
override val rawSortName: String?
|
||||
get() = null
|
||||
|
||||
override fun resolveName(context: Context) = rawName ?: context.getString(R.string.def_genre)
|
||||
}
|
||||
|
|
|
@ -183,7 +183,8 @@ class Task(context: Context, private val audio: MediaStoreBackend.Audio) {
|
|||
}
|
||||
}
|
||||
is VorbisComment -> {
|
||||
val id = tag.key.sanitize()
|
||||
// Vorbis comment keys can be in any case, make them uppercase for simplicity.
|
||||
val id = tag.key.sanitize().uppercase()
|
||||
val value = tag.value.sanitize()
|
||||
if (value.isNotEmpty()) {
|
||||
vorbisTags[id] = value
|
||||
|
@ -223,9 +224,10 @@ class Task(context: Context, private val audio: MediaStoreBackend.Audio) {
|
|||
// 3. ID3v2.4 Release Date, as it is the second most common date type
|
||||
// 4. ID3v2.3 Original Date, as it is like #1
|
||||
// 5. ID3v2.3 Release Year, as it is the most common date type
|
||||
audio.year
|
||||
?: tags["TDOR"]?.iso8601year ?: tags["TDRC"]?.iso8601year ?: tags["TDRL"]?.iso8601year
|
||||
?: tags["TORY"]?.year ?: tags["TYER"]?.year
|
||||
(tags["TDOR"]?.iso8601year
|
||||
?: tags["TDRC"]?.iso8601year ?: tags["TDRL"]?.iso8601year ?: tags["TORY"]?.year
|
||||
?: tags["TYER"]?.year)
|
||||
?.let { audio.year = it }
|
||||
|
||||
// Album
|
||||
tags["TALB"]?.let { audio.album = it }
|
||||
|
@ -256,8 +258,8 @@ class Task(context: Context, private val audio: MediaStoreBackend.Audio) {
|
|||
// 2. Date, as it is the most common date type
|
||||
// 3. Year, as old vorbis tags tended to use this (I know this because it's the only
|
||||
// tag that android supports, so it must be 15 years old or more!)
|
||||
audio.year =
|
||||
tags["ORIGINALDATE"]?.iso8601year ?: tags["DATE"]?.iso8601year ?: tags["YEAR"]?.year
|
||||
(tags["ORIGINALDATE"]?.iso8601year ?: tags["DATE"]?.iso8601year ?: tags["YEAR"]?.year)
|
||||
?.let { audio.year = it }
|
||||
|
||||
// Album
|
||||
tags["ALBUM"]?.let { audio.album = it }
|
||||
|
@ -268,7 +270,7 @@ class Task(context: Context, private val audio: MediaStoreBackend.Audio) {
|
|||
// Album artist. This actually comes into two flavors:
|
||||
// 1. ALBUMARTIST, which is the most common
|
||||
// 2. ALBUM ARTIST, which is present on older vorbis tags
|
||||
audio.albumArtist = tags["ALBUMARTIST"] ?: tags["ALBUM ARTIST"]
|
||||
(tags["ALBUMARTIST"] ?: tags["ALBUM ARTIST"])?.let { audio.albumArtist = it }
|
||||
|
||||
// Genre, no ID3 rules here
|
||||
tags["GENRE"]?.let { audio.genre = it }
|
||||
|
|
Loading…
Reference in a new issue