added tmdb watch providers for streaming services, and sorting by most voted

This commit is contained in:
kmshaw1990 2026-05-14 02:04:18 -05:00
parent 9056716c06
commit 4381d19229
5 changed files with 83 additions and 0 deletions

View file

@ -247,6 +247,19 @@
<string name="collections_editor_tmdb_sort_popular">Popular</string>
<string name="collections_editor_tmdb_sort_top_rated">Top Rated</string>
<string name="collections_editor_tmdb_sort_recent">Recent</string>
<string name="collections_editor_tmdb_sort_vote_count">Most Voted</string>
<string name="collections_editor_tmdb_watch_region">Watch region</string>
<string name="collections_editor_tmdb_watch_region_helper">ISO 3166-1 country code where the title is available. Example: US, GB.</string>
<string name="collections_editor_tmdb_quick_watch_regions">Quick watch regions</string>
<string name="collections_editor_tmdb_watch_providers">Watch provider IDs</string>
<string name="collections_editor_tmdb_watch_providers_helper">Pipe-separated TMDB provider IDs. Example: 8|337 for Netflix and Disney+.</string>
<string name="collections_editor_tmdb_watch_providers_placeholder">8|337|350</string>
<string name="collections_editor_tmdb_quick_watch_providers">Quick watch providers</string>
<string name="collections_editor_tmdb_watch_provider_netflix">Netflix</string>
<string name="collections_editor_tmdb_watch_provider_prime">Prime Video</string>
<string name="collections_editor_tmdb_watch_provider_disney">Disney+</string>
<string name="collections_editor_tmdb_watch_provider_apple">Apple TV+</string>
<string name="collections_editor_tmdb_watch_provider_hulu">Hulu</string>
<string name="collections_editor_tmdb_subtitle_list">TMDB List</string>
<string name="collections_editor_tmdb_subtitle_movie_collection">TMDB Movie Collection</string>
<string name="collections_editor_tmdb_subtitle_production">Production</string>

View file

@ -1125,6 +1125,7 @@ private fun TmdbSourcePickerScreen(
val sorts = listOf(
TmdbCollectionSort.POPULAR_DESC,
TmdbCollectionSort.VOTE_AVERAGE_DESC,
TmdbCollectionSort.VOTE_COUNT_DESC,
if (state.tmdbMediaType == TmdbCollectionMediaType.TV && !state.tmdbMediaBoth) {
TmdbCollectionSort.FIRST_AIR_DATE_DESC
} else {
@ -1353,6 +1354,54 @@ private fun TmdbSourcePickerScreen(
}
},
)
TmdbQuickChips(
label = stringResource(Res.string.collections_editor_tmdb_quick_watch_regions),
chips = listOf(
stringResource(Res.string.collections_editor_tmdb_country_us) to "US",
stringResource(Res.string.collections_editor_tmdb_country_uk) to "GB",
"Canada" to "CA",
"Australia" to "AU",
"Germany" to "DE",
),
onSelect = { value ->
CollectionEditorRepository.updateTmdbFilters { it.copy(watchRegion = value) }
},
)
TmdbFilterField(
label = stringResource(Res.string.collections_editor_tmdb_watch_region),
helper = stringResource(Res.string.collections_editor_tmdb_watch_region_helper),
value = state.tmdbFilters.watchRegion.orEmpty(),
placeholder = "US",
onValueChange = { value ->
CollectionEditorRepository.updateTmdbFilters {
it.copy(watchRegion = value.ifBlank { null })
}
},
)
TmdbQuickChips(
label = stringResource(Res.string.collections_editor_tmdb_quick_watch_providers),
chips = listOf(
stringResource(Res.string.collections_editor_tmdb_watch_provider_netflix) to "8",
stringResource(Res.string.collections_editor_tmdb_watch_provider_prime) to "119",
stringResource(Res.string.collections_editor_tmdb_watch_provider_disney) to "337",
stringResource(Res.string.collections_editor_tmdb_watch_provider_apple) to "350",
stringResource(Res.string.collections_editor_tmdb_watch_provider_hulu) to "15",
),
onSelect = { value ->
CollectionEditorRepository.updateTmdbFilters { it.copy(withWatchProviders = value) }
},
)
TmdbFilterField(
label = stringResource(Res.string.collections_editor_tmdb_watch_providers),
helper = stringResource(Res.string.collections_editor_tmdb_watch_providers_helper),
value = state.tmdbFilters.withWatchProviders.orEmpty(),
placeholder = stringResource(Res.string.collections_editor_tmdb_watch_providers_placeholder),
onValueChange = { value ->
CollectionEditorRepository.updateTmdbFilters {
it.copy(withWatchProviders = value.ifBlank { null })
}
},
)
}
}
}
@ -2255,6 +2304,7 @@ private fun tmdbSortLabel(sort: TmdbCollectionSort): String =
TmdbCollectionSort.ORIGINAL -> stringResource(Res.string.collections_editor_tmdb_sort_original)
TmdbCollectionSort.POPULAR_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_popular)
TmdbCollectionSort.VOTE_AVERAGE_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_top_rated)
TmdbCollectionSort.VOTE_COUNT_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_vote_count)
TmdbCollectionSort.RELEASE_DATE_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_recent)
TmdbCollectionSort.FIRST_AIR_DATE_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_recent)
}

View file

@ -100,6 +100,7 @@ enum class TmdbCollectionSort(val value: String) {
ORIGINAL("original"),
POPULAR_DESC("popularity.desc"),
VOTE_AVERAGE_DESC("vote_average.desc"),
VOTE_COUNT_DESC("vote_count.desc"),
RELEASE_DATE_DESC("primary_release_date.desc"),
FIRST_AIR_DATE_DESC("first_air_date.desc"),
}
@ -149,6 +150,8 @@ data class TmdbCollectionFilters(
val withCompanies: String? = null,
val withNetworks: String? = null,
val year: Int? = null,
val watchRegion: String? = null,
val withWatchProviders: String? = null,
)
data class TmdbSourceImportMetadata(

View file

@ -325,6 +325,11 @@ object TmdbCollectionSourceResolver {
putIfNotBlank("with_original_language", filters.withOriginalLanguage)
putIfNotBlank("with_origin_country", filters.withOriginCountry)
putIfNotBlank("with_keywords", filters.withKeywords)
if (!filters.withWatchProviders.isNullOrBlank()) {
put("with_watch_providers", filters.withWatchProviders)
put("watch_region", filters.watchRegion?.takeIf { it.isNotBlank() } ?: "US")
put("with_watch_monetization_types", "flatrate")
}
putIfNotBlank("year", filters.year?.takeIf { mediaType == TmdbCollectionMediaType.MOVIE }?.toString())
putIfNotBlank("first_air_date_year", filters.year?.takeIf { mediaType == TmdbCollectionMediaType.TV }?.toString())
putIfNotBlank(
@ -358,6 +363,7 @@ object TmdbCollectionSourceResolver {
compareByDescending<MetaPreview> { it.imdbRating?.toDoubleOrNull() ?: -1.0 }
.thenByDescending { it.rawReleaseDate ?: it.releaseInfo.orEmpty() },
)
TmdbCollectionSort.VOTE_COUNT_DESC.value -> sortedByDescending { it.voteCount ?: 0 }
TmdbCollectionSort.RELEASE_DATE_DESC.value,
TmdbCollectionSort.FIRST_AIR_DATE_DESC.value -> sortedByDescending { it.rawReleaseDate ?: it.releaseInfo.orEmpty() }
TmdbCollectionSort.POPULAR_DESC.value,
@ -395,6 +401,7 @@ object TmdbCollectionSourceResolver {
TmdbCollectionMediaType.TV -> firstAirDate
},
popularity = popularity,
voteCount = voteCount,
imdbRating = voteAverage?.let { ((it * 10).roundToInt() / 10.0).toString() },
)
}
@ -412,6 +419,7 @@ object TmdbCollectionSourceResolver {
releaseInfo = releaseDate?.take(4),
rawReleaseDate = releaseDate,
popularity = popularity,
voteCount = voteCount,
imdbRating = voteAverage?.let { ((it * 10).roundToInt() / 10.0).toString() },
)
}
@ -440,6 +448,7 @@ object TmdbCollectionSourceResolver {
TmdbCollectionMediaType.TV -> firstAirDate
},
popularity = popularity,
voteCount = voteCount,
imdbRating = voteAverage?.let { ((it * 10).roundToInt() / 10.0).toString() },
)
}
@ -468,6 +477,7 @@ object TmdbCollectionSourceResolver {
TmdbCollectionMediaType.TV -> firstAirDate
},
popularity = popularity,
voteCount = voteCount,
imdbRating = voteAverage?.let { ((it * 10).roundToInt() / 10.0).toString() },
)
}
@ -508,6 +518,7 @@ object TmdbCollectionSourceResolver {
when (sortBy) {
TmdbCollectionSort.FIRST_AIR_DATE_DESC.value -> TmdbCollectionSort.RELEASE_DATE_DESC.value
TmdbCollectionSort.ORIGINAL.value -> TmdbCollectionSort.POPULAR_DESC.value
TmdbCollectionSort.VOTE_COUNT_DESC.value -> TmdbCollectionSort.VOTE_COUNT_DESC.value
null, "" -> TmdbCollectionSort.POPULAR_DESC.value
else -> sortBy
}
@ -516,6 +527,7 @@ object TmdbCollectionSourceResolver {
when (sortBy) {
TmdbCollectionSort.RELEASE_DATE_DESC.value -> TmdbCollectionSort.FIRST_AIR_DATE_DESC.value
TmdbCollectionSort.ORIGINAL.value -> TmdbCollectionSort.POPULAR_DESC.value
TmdbCollectionSort.VOTE_COUNT_DESC.value -> TmdbCollectionSort.VOTE_COUNT_DESC.value
null, "" -> TmdbCollectionSort.POPULAR_DESC.value
else -> sortBy
}
@ -640,6 +652,7 @@ private data class TmdbPersonCreditCast(
@SerialName("release_date") val releaseDate: String? = null,
@SerialName("first_air_date") val firstAirDate: String? = null,
@SerialName("vote_average") val voteAverage: Double? = null,
@SerialName("vote_count") val voteCount: Int? = null,
val popularity: Double? = null,
)
@ -658,6 +671,7 @@ private data class TmdbPersonCreditCrew(
@SerialName("first_air_date") val firstAirDate: String? = null,
val job: String? = null,
@SerialName("vote_average") val voteAverage: Double? = null,
@SerialName("vote_count") val voteCount: Int? = null,
val popularity: Double? = null,
)
@ -675,6 +689,7 @@ private data class TmdbListItem(
@SerialName("release_date") val releaseDate: String? = null,
@SerialName("first_air_date") val firstAirDate: String? = null,
@SerialName("vote_average") val voteAverage: Double? = null,
@SerialName("vote_count") val voteCount: Int? = null,
val popularity: Double? = null,
)
@ -687,5 +702,6 @@ private data class TmdbCollectionPart(
@SerialName("backdrop_path") val backdropPath: String? = null,
@SerialName("release_date") val releaseDate: String? = null,
@SerialName("vote_average") val voteAverage: Double? = null,
@SerialName("vote_count") val voteCount: Int? = null,
val popularity: Double? = null,
)

View file

@ -15,6 +15,7 @@ data class MetaPreview(
val releaseInfo: String? = null,
val rawReleaseDate: String? = null,
val popularity: Double? = null,
val voteCount: Int? = null,
val imdbRating: String? = null,
val genres: List<String> = emptyList(),
)