diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx index 7618accc..de2f13aa 100644 --- a/frontend/src/components/Header.tsx +++ b/frontend/src/components/Header.tsx @@ -5,6 +5,7 @@ import type { Me } from "../lib/api"; import SearchBar from "./SearchBar"; import PlexSearchBox from "./PlexSearchBox"; import PlexScopeToggle from "./PlexScopeToggle"; +import PlexViewToggle from "./PlexViewToggle"; import FeedScopeToggle from "./FeedScopeToggle"; import SyncStatus from "./SyncStatus"; import { useNavigation } from "./NavigationProvider"; @@ -103,8 +104,10 @@ const Header = forwardRef< so the primary "what am I browsing" control is always in reach (mirrors Plex's scope toggle). */} {page === "feed" && } {/* Library scope (movie/show/both) sits right of the search box on Plex — relocated here from - the filter sidebar (S3) so the primary "what am I browsing" control is always in reach. */} + the filter sidebar (S3) so the primary "what am I browsing" control is always in reach. The + Discover ⟷ Browse toggle sits right beside it (driven via the PlexViewBridge). */} {page === "plex" && me.plex_enabled && } + {page === "plex" && me.plex_enabled && } {/* Per-user sync status — it used to cost the nav rail a whole block. It sits with the other pills rather than pinned to the far right: on a wide window that just strands it. Only on the two modules it says anything about: the feed those subscriptions fill, and the manager diff --git a/frontend/src/components/PlexBrowse.tsx b/frontend/src/components/PlexBrowse.tsx index 72e38d6b..878b9225 100644 --- a/frontend/src/components/PlexBrowse.tsx +++ b/frontend/src/components/PlexBrowse.tsx @@ -25,7 +25,6 @@ import { useHistorySubview } from "../lib/history"; 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"; @@ -34,6 +33,7 @@ import ItemCount from "./ItemCount"; import { StateMessage } from "./QueryState"; import { usePlexActiveFilters, usePlexClearFilters } from "./usePlexActiveFilters"; import { usePlex, usePlexActions } from "./PlexProvider"; +import { usePublishPlexView } from "./PlexViewBridge"; import { EpisodeCard, PlexPosterCard } from "./plexCards"; import { PlexInfoView, PlexPersonView, PlexSeasonView, PlexShowView } from "./plexViews"; @@ -82,6 +82,20 @@ export default function PlexBrowse() { // or an added filter is a browse intent → flip to the grid (below); an explicit toggle returns. const sub = useHistorySubview({ kind: "discover" }, PLEX_SUB_URL); + // Publish the top-level view (discover vs grid) + opener to the header's Discover/Browse toggle via + // the bridge; clear it on unmount so the toggle disappears when you leave the plex page. Keyed on the + // view KIND (open is behaviourally stable — it takes the next view as an arg, closing over nothing). + const publishView = usePublishPlexView(); + useLayoutEffect(() => { + publishView({ + isDiscover: sub.view.kind === "discover", + toggleable: sub.view.kind === "discover" || sub.view.kind === "grid", + open: sub.open, + }); + return () => publishView(null); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [sub.view.kind]); + // Sidebar asked to open a playlist → push it as a subview (browser Back returns to the grid), then // clear the signal so it doesn't re-open. useEffect(() => { @@ -366,42 +380,23 @@ export default function PlexBrowse() { ); } - // Discover ⟷ Browse switch, shown on both surfaces so either can return to the other. - const viewToggle = ( - sub.open(v === "discover" ? { kind: "discover" } : { kind: "grid" })} - /> - ); - - // Sort + the Discover/Browse toggle are tightly bound to the grid below, so on the grid view they - // live pinned to the right of the applied-filter chip row (directly above the cards), not on their - // own toolbar line — the same idiom as the Feed's `sortView`. + // Sort is tightly bound to the grid below, so on the grid view it lives pinned to the right of the + // applied-filter chip row (directly above the cards), not on its own toolbar line — the same idiom as + // the Feed's `sortView`. The Discover/Browse toggle moved up to the header (next to the scope pill). const sortView = ( - <> - setSort(next ?? PLEX_SORT_FALLBACK)} - label={t("plex.filter.sort")} - ascLabel={t("plex.filter.dir.asc")} - descLabel={t("plex.filter.dir.desc")} - /> -