Implementation

Search Filters#

Before implementing search, it helps to understand how provider search filters work.

Overview#

In the capability-first SDK, filters belong to SearchProviderApi via the filters: FilterList property. The host UI renders these filters and passes the selected state back into search(...).

class TestSearchApi : SearchProviderApi {
    override val filters: FilterList = FilterList(
        // ...
    )
 
    override suspend fun search(
        title: String,
        page: Int,
        filters: FilterList,
    ): PaginatedResponse<FilmSearchItem> {
        // Read selected filter state from `filters` and apply it to your request.
        TODO("Not yet implemented")
    }
}

To create your own search filters, you’ll need to understand the different filter types.

Filter#

Filter is a sealed class representing a named filter with a mutable state. This structure was inspired by Tachiyomi.

Examples:

// Select filter for choosing a genre
val genreFilter = Filter.Select(
    name = "Genre",
    options = listOf("Action", "Comedy", "Drama"),
    state = 0, // Default: first option
)
 
// CheckBox filter for HD content
val hdFilter = Filter.CheckBox(
    name = "HD Only",
    state = true,
)
 
// TriState filter for availability
val availabilityFilter = Filter.TriState(
    name = "Availability",
    state = Filter.TriState.STATE_UNSELECTED,
)
 
// Sort filter for sorting by popularity or release date
val sortFilter = Filter.Sort(
    name = "Sort By",
    options = listOf("Popularity", "Release Date"),
    state = Filter.Sort.Selection(index = 0, ascending = true),
)

Types#

TypeDescriptionStateExample
SelectMultiple selectable options.Selected index (Int).Genre selection.
CheckBoxOn/off toggle.Boolean.“HD only”.
TriStateUnselected/selected/indeterminate.0, 1, 2.Availability filter.
SortSorting option + direction.Selection(index, ascending) or null.Sort by popularity.

FilterGroup#

FilterGroup groups multiple filters under a single heading in the UI.

val contentFilterGroup = FilterGroup(
    name = "Content Filters",
    Filter.Select("Genre", listOf("Action", "Comedy", "Drama")),
    Filter.CheckBox("HD Only", state = true),
    Filter.Sort("Sort By", listOf("Popularity", "Release Date")),
)

FilterList#

FilterList is a container of FilterGroups. This is what you expose from SearchProviderApi.filters.

Example output#

class TestSearchApi : SearchProviderApi {
    override val filters: FilterList = FilterList(
        FilterGroup(
            name = "Content Filters",
            Filter.Select("Genre", listOf("Action", "Comedy", "Drama")),
            Filter.CheckBox("HD Only"),
            Filter.Sort("Sort By", listOf("Popularity", "Release Date")),
        ),
        FilterGroup(
            name = "Availability",
            Filter.TriState("Available Now"),
            Filter.CheckBox("Free Content"),
        ),
    )
 
    override suspend fun search(
        title: String,
        page: Int,
        filters: FilterList,
    ): PaginatedResponse<FilmSearchItem> {
        TODO("Apply filters to your request")
    }
}

You can inspect a real-world example of grouped filters in the Flixclusive app’s TMDB provider implementation.