feat(plex): make the Collection filter multi-select with Any/All
A title can belong to several Plex collections, so the collection filter becomes multi-select combining with Any (OR, default) / All (AND) — the same shape as the genre/actor filters. Backend (query.py): `collection` (single) → `collections` CSV + `collection_mode` on LibraryFilters; meta_filter_conds ORs/ANDs `collection_keys.contains` per id. Frontend: PlexFilters `collection`/`collectionTitle` → `collections` + optional `collectionMode` + `collectionTitles` map; CollectionPicker is now a multi-select Combobox with the any/all match footer; one chip per collection (usePlexActive- Filters); the info-page "Browse collection" strip unions into the list; applyFilter now shallow-merges label maps so adding one keeps the others' titles. PlexProvider migrates a legacy persisted single `collection` into the new shape on read. Test: test_plex_collections_filter (single / any-union / all-intersection).
This commit is contained in:
@@ -123,9 +123,20 @@ export function PlexProvider({ children }: { children: ReactNode }) {
|
||||
const filters = useMemo<PlexFilters>(() => {
|
||||
try {
|
||||
// Drop the legacy `sortDir` — direction now lives in the sort SortState. Left here it would leak
|
||||
// into the facets query key and be re-persisted on every filter change.
|
||||
const { sortDir: _drop, ...rest } = JSON.parse(filtersRaw);
|
||||
return { ...EMPTY_PLEX_FILTERS, ...rest };
|
||||
// into the facets query key and be re-persisted on every filter change. Also migrate the legacy
|
||||
// single `collection`/`collectionTitle` into the multi-select `collections`/`collectionTitles`.
|
||||
const {
|
||||
sortDir: _drop,
|
||||
collection: legacyCollection,
|
||||
collectionTitle: legacyTitle,
|
||||
...rest
|
||||
} = JSON.parse(filtersRaw);
|
||||
const merged: PlexFilters = { ...EMPTY_PLEX_FILTERS, ...rest };
|
||||
if (legacyCollection && !merged.collections.length) {
|
||||
merged.collections = [legacyCollection];
|
||||
if (legacyTitle) merged.collectionTitles = { [legacyCollection]: legacyTitle };
|
||||
}
|
||||
return merged;
|
||||
} catch {
|
||||
return EMPTY_PLEX_FILTERS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user