diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/library/LibraryDisplaySettings.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/library/LibraryDisplaySettings.kt index d7f2b7752..56b8504ce 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/library/LibraryDisplaySettings.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/library/LibraryDisplaySettings.kt @@ -20,6 +20,10 @@ enum class LibrarySortOption { ADDED_ASC, TITLE_ASC, TITLE_DESC, + RATING_DESC, + RATING_ASC, + RELEASE_DATE_DESC, + RELEASE_DATE_ASC, } data class LibraryDisplaySettingsUiState( @@ -131,6 +135,26 @@ internal fun sortLibraryItems( compareByDescending { libraryTitleSortKey(it) } .thenBy { it.id }, ) + LibrarySortOption.RATING_DESC -> items.sortedWith( + compareByDescending { it.imdbRating?.toFloatOrNull() ?: 0f } + .thenBy { libraryTitleTieBreakKey(it) } + .thenBy { it.id }, + ) + LibrarySortOption.RATING_ASC -> items.sortedWith( + compareBy { it.imdbRating?.toFloatOrNull() ?: Float.MAX_VALUE } + .thenBy { libraryTitleTieBreakKey(it) } + .thenBy { it.id }, + ) + LibrarySortOption.RELEASE_DATE_DESC -> items.sortedWith( + compareByDescending { releaseDateSortKey(it) } + .thenBy { libraryTitleTieBreakKey(it) } + .thenBy { it.id }, + ) + LibrarySortOption.RELEASE_DATE_ASC -> items.sortedWith( + compareBy { releaseDateSortKey(it) } + .thenBy { libraryTitleTieBreakKey(it) } + .thenBy { it.id }, + ) } internal fun sortLibrarySections( @@ -227,18 +251,22 @@ private val LibraryDisplaySettingsJson = Json { encodeDefaults = true } -private val LeadingLibraryTitleArticle = Regex("^(the|an|a)\\s+", RegexOption.IGNORE_CASE) - private fun libraryTitleSortKey(item: LibraryItem): String = libraryTitleTieBreakKey(item) - .trim() - .replace(LeadingLibraryTitleArticle, "") private fun libraryTitleTieBreakKey(item: LibraryItem): String = item.name .ifBlank { item.id } .lowercase() +private val IsoDateRegex = Regex("\\b\\d{4}(-\\d{2})?(-\\d{2})?\\b") + +private fun releaseDateSortKey(item: LibraryItem): String { + val info = item.releaseInfo.orEmpty().trim() + if (info.isBlank()) return "" + return IsoDateRegex.find(info)?.value ?: info.lowercase() +} + private fun libraryDisplayItemKey(item: LibraryItem): String = "${item.type.normalizedLibraryType()}:${item.id.trim()}" diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/library/LibrarySavedContent.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/library/LibrarySavedContent.kt index b5fc5c467..b70cd2d86 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/library/LibrarySavedContent.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/library/LibrarySavedContent.kt @@ -163,6 +163,10 @@ private fun librarySortOptionLabel(option: LibrarySortOption): String = LibrarySortOption.ADDED_ASC -> stringResource(Res.string.library_sort_added_asc) LibrarySortOption.TITLE_ASC -> stringResource(Res.string.library_sort_title_asc) LibrarySortOption.TITLE_DESC -> stringResource(Res.string.library_sort_title_desc) + LibrarySortOption.RATING_DESC -> "Rating (Highest)" + LibrarySortOption.RATING_ASC -> "Rating (Lowest)" + LibrarySortOption.RELEASE_DATE_DESC -> "Release Date (Newest)" + LibrarySortOption.RELEASE_DATE_ASC -> "Release Date (Oldest)" } private fun List.findEntry(preview: MetaPreview): LibraryVerticalEntry? = diff --git a/composeApp/src/commonTest/kotlin/com/nuvio/app/features/library/LibraryDisplaySettingsTest.kt b/composeApp/src/commonTest/kotlin/com/nuvio/app/features/library/LibraryDisplaySettingsTest.kt index bbfdf90bb..51e20a4ac 100644 --- a/composeApp/src/commonTest/kotlin/com/nuvio/app/features/library/LibraryDisplaySettingsTest.kt +++ b/composeApp/src/commonTest/kotlin/com/nuvio/app/features/library/LibraryDisplaySettingsTest.kt @@ -51,7 +51,7 @@ class LibraryDisplaySettingsTest { } @Test - fun `title sorting ignores leading English articles`() { + fun `title sorting preserves leading articles for literal alphabetical order`() { val input = listOf( item("batman", name = "The Batman"), item("arrival", name = "Arrival"), @@ -59,11 +59,11 @@ class LibraryDisplaySettingsTest { ) assertEquals( - listOf("arrival", "batman", "quiet"), + listOf("quiet", "arrival", "batman"), sortLibraryItems(input, LibrarySortOption.TITLE_ASC, LibrarySourceMode.LOCAL).map { it.id }, ) assertEquals( - listOf("quiet", "batman", "arrival"), + listOf("batman", "arrival", "quiet"), sortLibraryItems(input, LibrarySortOption.TITLE_DESC, LibrarySourceMode.LOCAL).map { it.id }, ) }