refactor(nav): read navigation from context, drop the prop-drilling

VideoCard/PlayerModal read openChannel from useNavigationActions (the memo'd
VideoCard subscribes to the STABLE actions context, so a page/channel change
no longer re-renders it); NavSidebar/Header read page/setPage; ChannelPage
reads closeChannel; NotificationsPanel reads setPage. App sheds the matching
props, and Feed/VirtualFeed no longer thread onOpenChannel at all.
This commit is contained in:
2026-07-18 02:19:52 +02:00
parent 41bb1b2ab3
commit a1bdfece6d
9 changed files with 20 additions and 53 deletions
+3 -5
View File
@@ -2,11 +2,11 @@ import { type ReactNode } from "react";
import { useTranslation } from "react-i18next";
import { Youtube } from "lucide-react";
import type { FeedFilters, Me } from "../lib/api";
import type { Page } from "../lib/urlState";
import { moduleLabelKey, moduleOrder, stepModule } from "../lib/modules";
import ModuleName from "./ModuleName";
import SearchBar from "./SearchBar";
import SyncStatus from "./SyncStatus";
import { useNavigation, useNavigationActions } from "./NavigationProvider";
// The floating top header: a row of glass pills over the content — a ModuleName pill (label +
// accent dot + back/forward arrows), the module's SearchBar where it has one, and the per-user
@@ -21,8 +21,6 @@ export default function Header({
setChannelsSearch,
playlistsSearch,
setPlaylistsSearch,
page,
setPage,
onYtSearch,
onGoToFullHistory,
}: {
@@ -36,8 +34,6 @@ export default function Header({
setChannelsSearch: (q: string) => void;
playlistsSearch: string;
setPlaylistsSearch: (q: string) => void;
page: Page;
setPage: (p: Page) => void;
// Trigger a live YouTube search for the current term (feed only; hidden for the demo account,
// which can't spend the shared quota).
onYtSearch: (q: string) => void;
@@ -45,6 +41,8 @@ export default function Header({
onGoToFullHistory: () => void;
}) {
const { t } = useTranslation();
const { page } = useNavigation();
const { setPage } = useNavigationActions();
// The ◀/▶ arrows step cyclically through the user's available modules (derived from `me`, so
// it stays correct as modules are added/gated). Labels of every active module feed ModuleName's
// dynamic width so the pill is sized to the widest reachable title in the current language.