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
|
||||
- Sorting now takes accented characters into account
|
||||
- Added support for compilation sub-release-types like (DJ) Mix
|
||||
|
||||
#### What's Fixed
|
||||
- Fixed issue where the scroll popup would not display correctly in landscape mode [#230]
|
||||
|
|
|
@ -245,22 +245,23 @@ class DetailViewModel(application: Application) :
|
|||
val byReleaseGroup =
|
||||
albums.groupBy {
|
||||
when (it.releaseType.refinement) {
|
||||
ReleaseType.Refinement.LIVE -> R.string.lbl_live_group
|
||||
ReleaseType.Refinement.REMIX -> R.string.lbl_remix_group
|
||||
ReleaseType.Refinement.LIVE -> ReleaseTypeGrouping.LIVE
|
||||
ReleaseType.Refinement.REMIX -> ReleaseTypeGrouping.REMIXES
|
||||
null ->
|
||||
when (it.releaseType) {
|
||||
is ReleaseType.Album -> R.string.lbl_albums
|
||||
is ReleaseType.EP -> R.string.lbl_eps
|
||||
is ReleaseType.Single -> R.string.lbl_singles
|
||||
is ReleaseType.Compilation -> R.string.lbl_compilations
|
||||
is ReleaseType.Soundtrack -> R.string.lbl_soundtracks
|
||||
is ReleaseType.Mixtape -> R.string.lbl_mixtapes
|
||||
is ReleaseType.Album -> ReleaseTypeGrouping.ALBUMS
|
||||
is ReleaseType.EP -> ReleaseTypeGrouping.EPS
|
||||
is ReleaseType.Single -> ReleaseTypeGrouping.SINGLES
|
||||
is ReleaseType.Compilation -> ReleaseTypeGrouping.COMPILATIONS
|
||||
is ReleaseType.Soundtrack -> ReleaseTypeGrouping.SOUNDTRACKS
|
||||
is ReleaseType.Mix -> ReleaseTypeGrouping.MIXES
|
||||
is ReleaseType.Mixtape -> ReleaseTypeGrouping.MIXTAPES
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (entry in byReleaseGroup.entries.sortedBy { it.key }) {
|
||||
data.add(Header(entry.key))
|
||||
data.add(Header(entry.key.string))
|
||||
data.addAll(entry.value)
|
||||
}
|
||||
|
||||
|
@ -324,6 +325,18 @@ class DetailViewModel(application: Application) :
|
|||
override fun onCleared() {
|
||||
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
|
||||
|
|
|
@ -771,12 +771,13 @@ sealed class ReleaseType {
|
|||
}
|
||||
}
|
||||
|
||||
object Compilation : ReleaseType() {
|
||||
override val refinement: Refinement?
|
||||
get() = null
|
||||
|
||||
data class Compilation(override val refinement: Refinement?) : ReleaseType() {
|
||||
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() {
|
||||
|
@ -787,6 +788,14 @@ sealed class ReleaseType {
|
|||
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() {
|
||||
override val refinement: Refinement?
|
||||
get() = null
|
||||
|
@ -806,6 +815,9 @@ sealed class ReleaseType {
|
|||
}
|
||||
|
||||
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 {
|
||||
val primary = types[0]
|
||||
|
||||
|
@ -823,22 +835,31 @@ sealed class ReleaseType {
|
|||
|
||||
private inline fun List<String>.parseSecondaryTypes(
|
||||
secondaryIdx: Int,
|
||||
target: (Refinement?) -> ReleaseType
|
||||
convertRefinement: (Refinement?) -> ReleaseType
|
||||
): ReleaseType {
|
||||
val secondary = (getOrNull(secondaryIdx) ?: return target(null))
|
||||
val secondary = getOrNull(secondaryIdx)
|
||||
|
||||
return when {
|
||||
// Compilation is the only weird secondary release type, as it could
|
||||
// theoretically have additional modifiers including soundtrack, remix,
|
||||
// live, dj-mix, etc. However, since there is no real demand for me to
|
||||
// respond to those, I don't implement them simply for simplicity.
|
||||
secondary.equals("compilation", true) -> Compilation
|
||||
secondary.equals("soundtrack", true) -> Soundtrack
|
||||
secondary.equals("mixtape/street", true) -> Mixtape
|
||||
secondary.equals("live", true) -> target(Refinement.LIVE)
|
||||
secondary.equals("remix", true) -> target(Refinement.REMIX)
|
||||
else -> target(null)
|
||||
}
|
||||
return if (secondary.equals("compilation", true)) {
|
||||
// Secondary type is a compilation, actually parse the third type
|
||||
// and put that into a compilation if needed.
|
||||
parseSecondaryTypeImpl(getOrNull(secondaryIdx + 1)) { Compilation(it) }
|
||||
} else {
|
||||
// Secondary type is a plain value, use the original values given.
|
||||
parseSecondaryTypeImpl(secondary, convertRefinement)
|
||||
}
|
||||
}
|
||||
|
||||
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>
|
||||
<!-- As in a compilation of music -->
|
||||
<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_soundtrack">Soundtrack</string>
|
||||
<!-- As in the collection of music -->
|
||||
<string name="lbl_mixtapes">Mixtapes</string>
|
||||
<!-- As in the collection of music -->
|
||||
<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 -->
|
||||
<string name="lbl_live_group">Live</string>
|
||||
|
|
Loading…
Reference in a new issue