Add filtering & sorting for discover grid pages (#1614)

## Description
This PR adds sort & filter options for the discover grid pages.

Sort options:
- Popularity
- Release date
- "Community rating" (TMDB user vote)
- Name

Filter options:
- Genre
- Studio/Network
- "Community rating" (TMDB user vote)
- Parental rating
- Production status (TV only)

Also, two more tabs are added to the discover page for browsing movies
and TV. These are essentially the same as clicking "View more" on the
respective rows on the Discover tab.

### Limitations

This PR hardcodes the region used for studio listing and filtering to
"United States". I'll work on a follow up PR to enable users to specify
this.

The sort & filters are not persisted. I think they should be on the two
new tabs, but not elsewhere, but this will be a follow up PR.

### Related issues
Related to #702 
Implements some of #1511
Rewrites the filter logic in #1610 

### Testing
Emulator, but needs further testing

## Screenshots
<img width="1280" height="720" alt="discover_filters Large"
src="https://github.com/user-attachments/assets/cdefb95c-c4b7-4e06-9bac-b535d372ba03"
/>


## AI or LLM usage
None
This commit is contained in:
Damontecres 2026-06-23 17:24:37 -04:00 • committed by GitHub
parent 552c3b5500
commit d705a3ea01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 1200 additions and 157 deletions

View file

@ -4,6 +4,7 @@ import androidx.annotation.StringRes
import com.github.damontecres.wholphin.R
import com.github.damontecres.wholphin.api.seerr.model.MovieResult
import com.github.damontecres.wholphin.api.seerr.model.TvResult
import com.github.damontecres.wholphin.data.filter.DiscoverFilter
import com.github.damontecres.wholphin.data.model.DiscoverItem
import com.github.damontecres.wholphin.data.model.SeerrItemType
import com.github.damontecres.wholphin.services.SeerrApi
@ -82,35 +83,27 @@ interface DiscoverRequestHandler<T> {
}
class DiscoverTvRequestHandler(
private val genre: Int? = null,
val filter: DiscoverFilter = DiscoverFilter(),
) : DiscoverRequestHandler<TvResult> {
override suspend fun execute(
api: SeerrApi,
pageNumber: Int,
): QueryResult<TvResult> =
api.api.searchApi
.discoverTvGet(
page = pageNumber,
genre = genre?.toString(),
).let {
QueryResult(it.results.orEmpty(), it.totalResults ?: 0)
}
filter.discoverTv(api.api.searchApi, pageNumber).let {
QueryResult(it.results.orEmpty(), it.totalResults ?: 0)
}
}
class DiscoverMovieRequestHandler(
private val genre: Int? = null,
val filter: DiscoverFilter = DiscoverFilter(),
) : DiscoverRequestHandler<MovieResult> {
override suspend fun execute(
api: SeerrApi,
pageNumber: Int,
): QueryResult<MovieResult> =
api.api.searchApi
.discoverMoviesGet(
page = pageNumber,
genre = genre?.toString(),
).let {
QueryResult(it.results.orEmpty(), it.totalResults ?: 0)
}
filter.discoverMovies(api.api.searchApi, pageNumber).let {
QueryResult(it.results.orEmpty(), it.totalResults ?: 0)
}
}
val TrendingRequestHandler =