music: add support for compilation sub-types
Add support for compilation + live, compilation + remix, and compilation + dj-mix release types. This was not included due to the changes it required to the parser. Turns out these changes are largely trivial if I do more clever inlining.
This commit is contained in:
parent
780e0dce06
commit
33b0aabc44
4 changed files with 69 additions and 27 deletions
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#### What's Improved
|
#### What's Improved
|
||||||
- Sorting now takes accented characters into account
|
- Sorting now takes accented characters into account
|
||||||
|
- Added support for compilation sub-release-types like (DJ) Mix
|
||||||
|
|
||||||
#### What's Fixed
|
#### What's Fixed
|
||||||
- Fixed issue where the scroll popup would not display correctly in landscape mode [#230]
|
- Fixed issue where the scroll popup would not display correctly in landscape mode [#230]
|
||||||
|
|
|
@ -245,22 +245,23 @@ class DetailViewModel(application: Application) :
|
||||||
val byReleaseGroup =
|
val byReleaseGroup =
|
||||||
albums.groupBy {
|
albums.groupBy {
|
||||||
when (it.releaseType.refinement) {
|
when (it.releaseType.refinement) {
|
||||||
ReleaseType.Refinement.LIVE -> R.string.lbl_live_group
|
ReleaseType.Refinement.LIVE -> ReleaseTypeGrouping.LIVE
|
||||||
ReleaseType.Refinement.REMIX -> R.string.lbl_remix_group
|
ReleaseType.Refinement.REMIX -> ReleaseTypeGrouping.REMIXES
|
||||||
null ->
|
null ->
|
||||||
when (it.releaseType) {
|
when (it.releaseType) {
|
||||||
is ReleaseType.Album -> R.string.lbl_albums
|
is ReleaseType.Album -> ReleaseTypeGrouping.ALBUMS
|
||||||
is ReleaseType.EP -> R.string.lbl_eps
|
is ReleaseType.EP -> ReleaseTypeGrouping.EPS
|
||||||
is ReleaseType.Single -> R.string.lbl_singles
|
is ReleaseType.Single -> ReleaseTypeGrouping.SINGLES
|
||||||
is ReleaseType.Compilation -> R.string.lbl_compilations
|
is ReleaseType.Compilation -> ReleaseTypeGrouping.COMPILATIONS
|
||||||
is ReleaseType.Soundtrack -> R.string.lbl_soundtracks
|
is ReleaseType.Soundtrack -> ReleaseTypeGrouping.SOUNDTRACKS
|
||||||
is ReleaseType.Mixtape -> R.string.lbl_mixtapes
|
is ReleaseType.Mix -> ReleaseTypeGrouping.MIXES
|
||||||
|
is ReleaseType.Mixtape -> ReleaseTypeGrouping.MIXTAPES
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (entry in byReleaseGroup.entries.sortedBy { it.key }) {
|
for (entry in byReleaseGroup.entries.sortedBy { it.key }) {
|
||||||
data.add(Header(entry.key))
|
data.add(Header(entry.key.string))
|
||||||
data.addAll(entry.value)
|
data.addAll(entry.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,6 +325,18 @@ class DetailViewModel(application: Application) :
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
musicStore.removeCallback(this)
|
musicStore.removeCallback(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum class ReleaseTypeGrouping(@StringRes val string: Int) {
|
||||||
|
ALBUMS(R.string.lbl_albums),
|
||||||
|
EPS(R.string.lbl_eps),
|
||||||
|
SINGLES(R.string.lbl_singles),
|
||||||
|
COMPILATIONS(R.string.lbl_compilations),
|
||||||
|
SOUNDTRACKS(R.string.lbl_compilations),
|
||||||
|
MIXES(R.string.lbl_mixes),
|
||||||
|
MIXTAPES(R.string.lbl_mixtapes),
|
||||||
|
LIVE(R.string.lbl_live_group),
|
||||||
|
REMIXES(R.string.lbl_remix_group),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class SortHeader(@StringRes val string: Int) : Item
|
data class SortHeader(@StringRes val string: Int) : Item
|
||||||
|
|
|
@ -771,12 +771,13 @@ sealed class ReleaseType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Compilation : ReleaseType() {
|
data class Compilation(override val refinement: Refinement?) : ReleaseType() {
|
||||||
override val refinement: Refinement?
|
|
||||||
get() = null
|
|
||||||
|
|
||||||
override val stringRes: Int
|
override val stringRes: Int
|
||||||
get() = R.string.lbl_compilation
|
get() = when (refinement) {
|
||||||
|
null -> R.string.lbl_compilation
|
||||||
|
Refinement.LIVE -> R.string.lbl_compilation_live
|
||||||
|
Refinement.REMIX -> R.string.lbl_compilation_remix
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Soundtrack : ReleaseType() {
|
object Soundtrack : ReleaseType() {
|
||||||
|
@ -787,6 +788,14 @@ sealed class ReleaseType {
|
||||||
get() = R.string.lbl_soundtrack
|
get() = R.string.lbl_soundtrack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Mix : ReleaseType() {
|
||||||
|
override val refinement: Refinement?
|
||||||
|
get() = null
|
||||||
|
|
||||||
|
override val stringRes: Int
|
||||||
|
get() = R.string.lbl_mix
|
||||||
|
}
|
||||||
|
|
||||||
object Mixtape : ReleaseType() {
|
object Mixtape : ReleaseType() {
|
||||||
override val refinement: Refinement?
|
override val refinement: Refinement?
|
||||||
get() = null
|
get() = null
|
||||||
|
@ -806,6 +815,9 @@ sealed class ReleaseType {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
// Note: The parsing code is extremely clever in order to reduce duplication. It's
|
||||||
|
// better just to read the specification behind release types than follow this code.
|
||||||
|
|
||||||
fun parse(types: List<String>): ReleaseType {
|
fun parse(types: List<String>): ReleaseType {
|
||||||
val primary = types[0]
|
val primary = types[0]
|
||||||
|
|
||||||
|
@ -823,22 +835,31 @@ sealed class ReleaseType {
|
||||||
|
|
||||||
private inline fun List<String>.parseSecondaryTypes(
|
private inline fun List<String>.parseSecondaryTypes(
|
||||||
secondaryIdx: Int,
|
secondaryIdx: Int,
|
||||||
target: (Refinement?) -> ReleaseType
|
convertRefinement: (Refinement?) -> ReleaseType
|
||||||
): ReleaseType {
|
): ReleaseType {
|
||||||
val secondary = (getOrNull(secondaryIdx) ?: return target(null))
|
val secondary = getOrNull(secondaryIdx)
|
||||||
|
|
||||||
return when {
|
return if (secondary.equals("compilation", true)) {
|
||||||
// Compilation is the only weird secondary release type, as it could
|
// Secondary type is a compilation, actually parse the third type
|
||||||
// theoretically have additional modifiers including soundtrack, remix,
|
// and put that into a compilation if needed.
|
||||||
// live, dj-mix, etc. However, since there is no real demand for me to
|
parseSecondaryTypeImpl(getOrNull(secondaryIdx + 1)) { Compilation(it) }
|
||||||
// respond to those, I don't implement them simply for simplicity.
|
} else {
|
||||||
secondary.equals("compilation", true) -> Compilation
|
// Secondary type is a plain value, use the original values given.
|
||||||
secondary.equals("soundtrack", true) -> Soundtrack
|
parseSecondaryTypeImpl(secondary, convertRefinement)
|
||||||
secondary.equals("mixtape/street", true) -> Mixtape
|
|
||||||
secondary.equals("live", true) -> target(Refinement.LIVE)
|
|
||||||
secondary.equals("remix", true) -> target(Refinement.REMIX)
|
|
||||||
else -> target(null)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun parseSecondaryTypeImpl(
|
||||||
|
type: String?,
|
||||||
|
convertRefinement: (Refinement?) -> ReleaseType
|
||||||
|
) = when {
|
||||||
|
// Parse all the types that have no children
|
||||||
|
type.equals("soundtrack", true) -> Soundtrack
|
||||||
|
type.equals("mixtape/street", true) -> Mixtape
|
||||||
|
type.equals("dj-mix", true) -> Mix
|
||||||
|
type.equals("live", true) -> convertRefinement(Refinement.LIVE)
|
||||||
|
type.equals("remix", true) -> convertRefinement(Refinement.REMIX)
|
||||||
|
else -> convertRefinement(null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,12 +51,19 @@
|
||||||
<string name="lbl_compilations">Compilations</string>
|
<string name="lbl_compilations">Compilations</string>
|
||||||
<!-- As in a compilation of music -->
|
<!-- As in a compilation of music -->
|
||||||
<string name="lbl_compilation">Compilation</string>
|
<string name="lbl_compilation">Compilation</string>
|
||||||
|
<!-- As in a compilation of live music -->
|
||||||
|
<string name="lbl_compilation_live">Live compilation</string>
|
||||||
|
<string name="lbl_compilation_remix">Remix compilations</string>
|
||||||
<string name="lbl_soundtracks">Soundtracks</string>
|
<string name="lbl_soundtracks">Soundtracks</string>
|
||||||
<string name="lbl_soundtrack">Soundtrack</string>
|
<string name="lbl_soundtrack">Soundtrack</string>
|
||||||
<!-- As in the collection of music -->
|
<!-- As in the collection of music -->
|
||||||
<string name="lbl_mixtapes">Mixtapes</string>
|
<string name="lbl_mixtapes">Mixtapes</string>
|
||||||
<!-- As in the collection of music -->
|
<!-- As in the collection of music -->
|
||||||
<string name="lbl_mixtape">Mixtape</string>
|
<string name="lbl_mixtape">Mixtape</string>
|
||||||
|
<!-- As in a compilation of several performances that blend into a single continuous flow of music -->
|
||||||
|
<string name="lbl_mixes">Mixes</string>
|
||||||
|
<!-- As in a compilation of several performances that blend into a single continuous flow of music -->
|
||||||
|
<string name="lbl_mix">Mix</string>
|
||||||
|
|
||||||
<!-- As in music that was performed live -->
|
<!-- As in music that was performed live -->
|
||||||
<string name="lbl_live_group">Live</string>
|
<string name="lbl_live_group">Live</string>
|
||||||
|
|
Loading…
Reference in a new issue