import { createContext, useContext } from "react"; import { EMPTY_PLEX_FILTERS, type PlexFilters } from "../lib/api"; import type { SortState } from "../lib/columnSort"; import type { PlexSearchField } from "../lib/plexSearch"; import { PLEX_SORT_FALLBACK } from "../lib/plexSort"; // The Plex module's contexts + hooks, split out of PlexProvider so that file exports only components // (Fast Refresh). // A "jump straight to this title" hand-off: PlexBrowse opens a movie's info page (like the card's ⓘ), // a show's drill-down (like clicking a show card), or — for E24's Home hero, whose whole promise is a // single Play button — the PLAYER for a movie/episode rating_key. `play` exists because the player // lives inside this module with its lazy hls.js and its provider tree; mounting a second one on the // landing page to avoid one hand-off would be the expensive way round. export type PlexJumpTarget = { id: string; type: "movie" | "show" | "play"; /** The jump ARRIVED WITH a page change — another module set this and sent the user here in one * gesture (the Home surface plays a Plex title). The opened sub-view then REPLACES the page entry * that hand-off just pushed, instead of stacking on top of it, so Back returns to where the user * actually came from rather than to a module root they never visited. Omitted for a jump made * from INSIDE the Plex module (the header typeahead), where the entry being replaced would be a * sub-view the user really was looking at. */ replace?: boolean; }; export type PlexState = { scope: string; // movie | show | both (unified cross-library scope) show: string; sort: SortState; // {key,dir}; healed against the scope's options at the point of use filters: PlexFilters; q: string; field: PlexSearchField; // search scope-pill; healed against `scope` at the point of use playlistOpen: number | null; jumpTo: PlexJumpTarget | null; // typeahead → grid hand-off ("open this title") }; export interface PlexActions { setScope: (v: string) => void; setShow: (v: string) => void; setSort: (v: SortState) => void; setFilters: (f: PlexFilters) => void; setQ: (q: string) => void; setField: (f: PlexSearchField) => void; setPlaylistOpen: (id: number | null) => void; setJumpTo: (t: PlexJumpTarget | null) => void; } export const PlexStateContext = createContext({ scope: "both", show: "all", sort: PLEX_SORT_FALLBACK, filters: EMPTY_PLEX_FILTERS, q: "", field: "all", playlistOpen: null, jumpTo: null, }); export const PlexActionsContext = createContext({ setScope: () => {}, setShow: () => {}, setSort: () => {}, setFilters: () => {}, setQ: () => {}, setField: () => {}, setPlaylistOpen: () => {}, setJumpTo: () => {}, }); export function usePlex(): PlexState { return useContext(PlexStateContext); } export function usePlexActions(): PlexActions { return useContext(PlexActionsContext); }