refactor(plex): scope module state in PlexProvider
Lift the Plex module's shared local state (scope / watch-state / sort / expanded filters / search term / open-playlist hand-off) out of App into a split-context PlexProvider with stable useCallback setters. PlexSidebar, PlexBrowse, and the header search box read it via usePlex()/usePlexActions() instead of props drilled through App; PlexBrowse is now prop-free. App loses six useStates + the filters JSON memo/serialise helpers. (Platform S6b.2)
This commit is contained in:
+1
-48
@@ -3,11 +3,9 @@ import { useTranslation } from "react-i18next";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
api,
|
||||
EMPTY_PLEX_FILTERS,
|
||||
getActiveAccount,
|
||||
setActiveAccount,
|
||||
setUnauthorizedHandler,
|
||||
type PlexFilters,
|
||||
} from "./lib/api";
|
||||
import { setLanguage, isSupported, type LangCode } from "./i18n";
|
||||
import {
|
||||
@@ -156,30 +154,6 @@ export default function App() {
|
||||
: channelsViewRaw === "blocked"
|
||||
? "blocked"
|
||||
: "subscribed";
|
||||
// Plex module filters (its own left-sidebar filter section) — per-account persisted.
|
||||
// The former per-library picker is now a cross-library SCOPE: movie | show | both (unified library).
|
||||
// (Reuses the old LS.plexLibrary key; an old stored library-id value falls back to "both".)
|
||||
const [plexScopeRaw, setPlexScope] = useAccountPersistedState(LS.plexLibrary, "both");
|
||||
const plexScope = ["movie", "show", "both"].includes(plexScopeRaw) ? plexScopeRaw : "both";
|
||||
const [plexShowFilter, setPlexShowFilter] = useAccountPersistedState(LS.plexShow, "all");
|
||||
const [plexSort, setPlexSort] = useAccountPersistedState(LS.plexSort, "title");
|
||||
const [plexPlaylistOpen, setPlexPlaylistOpen] = useState<number | null>(null); // sidebar → open a playlist
|
||||
// The expanded Plex filters live as one JSON blob (the string-only account store serializes it).
|
||||
const [plexFiltersRaw, setPlexFiltersRaw] = useAccountPersistedState(LS.plexFilters, "{}");
|
||||
const plexFilters = useMemo<PlexFilters>(() => {
|
||||
try {
|
||||
return { ...EMPTY_PLEX_FILTERS, ...JSON.parse(plexFiltersRaw) };
|
||||
} catch {
|
||||
return EMPTY_PLEX_FILTERS;
|
||||
}
|
||||
}, [plexFiltersRaw]);
|
||||
const setPlexFilters = (f: PlexFilters) => setPlexFiltersRaw(JSON.stringify(f));
|
||||
// The Plex library search term is its OWN ephemeral state — deliberately NOT the persisted feed
|
||||
// `filters.q`. Sharing that box meant a Plex search leaked into the feed and, being persisted,
|
||||
// greeted you with a stale query (colliding with a persisted collection filter → confusing
|
||||
// "0 matches") after a reload. Kept in App so it survives page switches within a session, but
|
||||
// resets on reload.
|
||||
const [plexQ, setPlexQ] = useAccountPersistedState(LS.plexQ, ""); // survives F5, unlike the feed search
|
||||
// Bumped to tell the channel manager to drop a stale column filter when we send the user
|
||||
// there to see a specific set (the header's "without full history" link).
|
||||
const [channelsFilterReset, setChannelsFilterReset] = useState(0);
|
||||
@@ -581,15 +555,6 @@ export default function App() {
|
||||
{page === "plex" && meQuery.data!.plex_enabled && (
|
||||
<Suspense fallback={null}>
|
||||
<PlexSidebar
|
||||
scope={plexScope}
|
||||
setScope={setPlexScope}
|
||||
show={plexShowFilter}
|
||||
setShow={setPlexShowFilter}
|
||||
sort={plexSort}
|
||||
setSort={setPlexSort}
|
||||
filters={plexFilters}
|
||||
setFilters={setPlexFilters}
|
||||
onOpenPlaylist={setPlexPlaylistOpen}
|
||||
layout={panelLayouts.plex}
|
||||
setLayout={(l) => setPanelLayout("plex", l)}
|
||||
collapsed={filterCollapsed}
|
||||
@@ -644,8 +609,6 @@ export default function App() {
|
||||
header={
|
||||
<Header
|
||||
me={meQuery.data!}
|
||||
plexQ={plexQ}
|
||||
setPlexQ={setPlexQ}
|
||||
channelsSearch={channelsSearch}
|
||||
setChannelsSearch={setChannelsSearch}
|
||||
onYtSearch={enterYtSearch}
|
||||
@@ -714,17 +677,7 @@ export default function App() {
|
||||
onOpenWizard={() => setWizardOpen(true)}
|
||||
/>
|
||||
) : page === "plex" && meQuery.data!.plex_enabled ? (
|
||||
<PlexBrowse
|
||||
q={plexQ}
|
||||
scope={plexScope}
|
||||
setScope={setPlexScope}
|
||||
show={plexShowFilter}
|
||||
sort={plexSort}
|
||||
filters={plexFilters}
|
||||
setFilters={setPlexFilters}
|
||||
openPlaylist={plexPlaylistOpen}
|
||||
onPlaylistOpened={() => setPlexPlaylistOpen(null)}
|
||||
/>
|
||||
<PlexBrowse />
|
||||
) : (
|
||||
<Feed
|
||||
filters={filters}
|
||||
|
||||
Reference in New Issue
Block a user