From cfa49a2cdac7af7c9acca7b50a23eceec862df09 Mon Sep 17 00:00:00 2001 From: Sobhan Date: Mon, 27 Jul 2026 19:09:05 +0530 Subject: [PATCH 1/2] fix(library): preserve leading articles in title sorting for natural alphabetical order --- .../nuvio/app/features/library/LibraryDisplaySettings.kt | 4 ---- .../app/features/library/LibraryDisplaySettingsTest.kt | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) 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..38c15d4c3 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 @@ -227,12 +227,8 @@ 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 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 }, ) } From 6d54ff1698c2c1611b3e1de155db87ed7eea76ea Mon Sep 17 00:00:00 2001 From: Sobhan Date: Mon, 27 Jul 2026 19:09:48 +0530 Subject: [PATCH 2/2] feat(library): add Rating and Release Date sorting options --- .../library/LibraryDisplaySettings.kt | 32 +++++++++++++++++++ .../features/library/LibrarySavedContent.kt | 4 +++ 2 files changed, 36 insertions(+) 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 38c15d4c3..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( @@ -235,6 +259,14 @@ private fun libraryTitleTieBreakKey(item: LibraryItem): String = .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? =