feat(plex): active-filter chip row above the grid (R13 S2)
Plex now shows the same at-a-glance "what's narrowing this" row the feed has, instead of the narrowing being visible only inside the collapsed sidebar. New usePlexActiveFilters is the Plex analogue of useActiveFilters — it turns the Plex state (expanded filters + watch-state + sort) into the source-agnostic ActiveFilter[] the SHARED ActiveFilterChips renders. One removable chip per dimension (genres/ratings/people emit one each), plus Clear-all resetting filters + watch-state + sort. Labels reuse the existing plex.* i18n keys; no new strings. Lives in components (not lib) since it reads the Plex provider — lib stays provider-free like useActiveFilters. Gate green: tsc/eslint-0/prettier/knip. Self-E2E'd: a sort=year chip renders, removing it resets sort to title and hides the row.
This commit is contained in:
@@ -9,7 +9,7 @@ import {
|
||||
type ReactNode,
|
||||
} from "react";
|
||||
import { qk } from "../lib/queryKeys";
|
||||
import { healPlexSort } from "../lib/plexSort";
|
||||
import { healPlexSort, PLEX_SORT_FALLBACK } from "../lib/plexSort";
|
||||
import { createPortal } from "react-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
@@ -59,6 +59,8 @@ import PlexPlaylistAdd, { type PlexAddTarget } from "./PlexPlaylistAdd";
|
||||
import PlexCollectionEditor from "./PlexCollectionEditor";
|
||||
import { LoadingState, StateMessage } from "./QueryState";
|
||||
import { PageToolbar } from "./PageShell";
|
||||
import ActiveFilterChips from "./ActiveFilterChips";
|
||||
import { usePlexActiveFilters } from "./usePlexActiveFilters";
|
||||
import { usePlex, usePlexActions } from "./PlexProvider";
|
||||
|
||||
// Lazy: the rich player (pulls in hls.js) loads only when something is first played.
|
||||
@@ -89,8 +91,16 @@ export default function PlexBrowse() {
|
||||
// search term (q) comes from the shared header box; the rail hands off a playlist to open via the
|
||||
// shared `playlistOpen` slot, which we consume into a history subview then clear.
|
||||
const { q, scope, show, sort, filters, playlistOpen: openPlaylist } = usePlex();
|
||||
const { setScope, setFilters, setPlaylistOpen } = usePlexActions();
|
||||
const { setScope, setShow, setSort, setFilters, setPlaylistOpen } = usePlexActions();
|
||||
const dq = useDebounced(q.trim(), 350);
|
||||
// Plex's active-filter chip row (above the grid), the shared feed idiom: one removable chip per
|
||||
// narrowing, plus a Clear-all that resets filters + watch-state + sort to their defaults.
|
||||
const plexChips = usePlexActiveFilters();
|
||||
const clearAllFilters = () => {
|
||||
setFilters(EMPTY_PLEX_FILTERS);
|
||||
setShow("all");
|
||||
setSort(PLEX_SORT_FALLBACK);
|
||||
};
|
||||
// The provider holds sort scope-agnostically; heal it against THIS scope's options so a movie-only
|
||||
// key (e.g. duration) left over from before a switch to shows doesn't ask for an unavailable sort.
|
||||
const sortState = healPlexSort(sort, scope);
|
||||
@@ -333,6 +343,8 @@ export default function PlexBrowse() {
|
||||
</div>
|
||||
</PageToolbar>
|
||||
|
||||
<ActiveFilterChips filters={plexChips} onClearAll={clearAllFilters} />
|
||||
|
||||
{personCards.length > 0 && (
|
||||
<div className="mb-4 flex flex-wrap gap-3">
|
||||
{personCards.map((p) => (
|
||||
|
||||
Reference in New Issue
Block a user