feat(plex): move Watch-state out of the rail into a toolbar pill
The "Show" (watch-state) filter leaves the left rail and becomes a FilterSelect pill next to the item count, mirroring the feed's Watch-state control — a top-level "what am I looking at" choice, always in reach, not buried in the rail. It still emits a removable chip when non-default (same as the feed).
This commit is contained in:
@@ -26,6 +26,7 @@ import { PLEX_SUB_URL, type Sub } from "./plexSubUrl";
|
||||
import { toggleWatchState } from "../lib/plexWatch";
|
||||
import SortControl from "./SortControl";
|
||||
import SegmentedToggle from "./SegmentedToggle";
|
||||
import FilterSelect from "./FilterSelect";
|
||||
import PlexDiscover from "./PlexDiscover";
|
||||
import { PageToolbar } from "./PageShell";
|
||||
import ActiveFilterChips from "./ActiveFilterChips";
|
||||
@@ -48,6 +49,10 @@ const PlexPlaylistView = lazy(() => import("./PlexPlaylistView"));
|
||||
|
||||
const PAGE = 40;
|
||||
|
||||
// Watch-state options for the toolbar pill (moved out of the filter rail — it's a top-level "what am
|
||||
// I looking at" control now, like the feed's Watch-state pill, not a rail widget).
|
||||
const SHOW_OPTS = ["all", "unwatched", "in_progress", "watched"] as const;
|
||||
|
||||
export default function PlexBrowse() {
|
||||
const { t } = useTranslation();
|
||||
const qc = useQueryClient();
|
||||
@@ -55,7 +60,7 @@ 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, field, playlistOpen: openPlaylist, jumpTo } = usePlex();
|
||||
const { setScope, setSort, setFilters, setPlaylistOpen, setJumpTo } = usePlexActions();
|
||||
const { setScope, setShow, setSort, setFilters, setPlaylistOpen, setJumpTo } = usePlexActions();
|
||||
const dq = useDebounced(q.trim(), 350);
|
||||
// Active language for the HU overlay: "hu" serves Hungarian metadata, else EN. In the query keys so
|
||||
// a switch refetches the grid/facets/detail; useTranslation re-renders this component on switch.
|
||||
@@ -408,7 +413,18 @@ export default function PlexBrowse() {
|
||||
while only the poster grid scrolls. */}
|
||||
<PageToolbar>
|
||||
<div className="px-4 pt-2 pb-1 max-w-[1600px] mx-auto">
|
||||
<ItemCount count={browseQ.isLoading ? undefined : total} />
|
||||
<div className="flex items-center gap-1.5">
|
||||
<ItemCount count={browseQ.isLoading ? undefined : total} />
|
||||
{/* Watch state — a top-level toolbar pill next to the count (moved out of the rail),
|
||||
the same idiom as the feed's Watch-state FilterSelect. */}
|
||||
<FilterSelect
|
||||
label={t("plex.filter.show")}
|
||||
testId="plex-show"
|
||||
options={SHOW_OPTS.map((s) => ({ value: s, label: t(`plex.filter.showOpt.${s}`) }))}
|
||||
selected={[show]}
|
||||
onChange={(next) => setShow(next[0] ?? "all")}
|
||||
/>
|
||||
</div>
|
||||
{/* The controls row sits directly above the grid: the applied-filter chips flow from the
|
||||
left (overflowing to a "+N"/count pill so they never crowd the controls), while Sort +
|
||||
the Discover/Browse toggle stay pinned to the right — the same layout as the Feed. */}
|
||||
|
||||
@@ -27,7 +27,6 @@ type Props = {
|
||||
onToggleCollapse: () => void;
|
||||
};
|
||||
|
||||
const SHOW_OPTS = ["all", "unwatched", "in_progress", "watched"] as const;
|
||||
const RATING_STEPS = [5, 6, 7, 8, 9];
|
||||
const ADDED_OPTS = ["24h", "1w", "1m", "6m", "1y"] as const;
|
||||
const DURATION_BUCKETS: { key: string; min: number | null; max: number | null }[] = [
|
||||
@@ -66,7 +65,7 @@ export default function PlexSidebar({ layout, setLayout, collapsed, onToggleColl
|
||||
// the header search box); this rail is the primary editor of them. Opening a playlist is a
|
||||
// hand-off to PlexBrowse via the shared `playlistOpen` slot.
|
||||
const { scope, show, filters } = usePlex();
|
||||
const { setShow, setFilters, setPlaylistOpen: onOpenPlaylist } = usePlexActions();
|
||||
const { setFilters, setPlaylistOpen: onOpenPlaylist } = usePlexActions();
|
||||
const playlistsQ = useQuery({ queryKey: qk.plexPlaylists(), queryFn: () => api.plexPlaylists() });
|
||||
const [newPlaylist, setNewPlaylist] = useState("");
|
||||
// This rail's media source (the Plex library) — names the abstraction the feed and Plex rails
|
||||
@@ -151,18 +150,6 @@ export default function PlexSidebar({ layout, setLayout, collapsed, onToggleColl
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "watch",
|
||||
title: t("plex.filter.show"),
|
||||
body: (
|
||||
<FilterChipGroup
|
||||
ariaLabel={t("plex.filter.show")}
|
||||
options={SHOW_OPTS.map((s) => ({ value: s, label: t(`plex.filter.showOpt.${s}`) }))}
|
||||
value={show}
|
||||
onChange={setShow}
|
||||
/>
|
||||
),
|
||||
},
|
||||
...(peopleActive
|
||||
? [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user