From 33b0aabc446551959f7922009cca02674788af0e Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Wed, 14 Sep 2022 10:16:02 -0600 Subject: [PATCH] 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. --- CHANGELOG.md | 1 + .../oxycblt/auxio/detail/DetailViewModel.kt | 31 +++++++--- .../java/org/oxycblt/auxio/music/Music.kt | 57 +++++++++++++------ app/src/main/res/values/strings.xml | 7 +++ 4 files changed, 69 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ceccf41b..f6ffec5cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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] diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt index 272e9d5be..7dbdc7e02 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt @@ -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 diff --git a/app/src/main/java/org/oxycblt/auxio/music/Music.kt b/app/src/main/java/org/oxycblt/auxio/music/Music.kt index df165045c..6db26418a 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/Music.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Music.kt @@ -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): ReleaseType { val primary = types[0] @@ -823,22 +835,31 @@ sealed class ReleaseType { private inline fun List.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) + } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8e33d337e..ecf10f570 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -51,12 +51,19 @@ Compilations Compilation + + Live compilation + Remix compilations Soundtracks Soundtrack Mixtapes Mixtape + + Mixes + + Mix Live