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 -6
View File
@@ -1,6 +1,7 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useNavigationActions } from "./NavigationProvider";
import { ArrowLeft, Ban, Check, ExternalLink, Loader2, Plus, RefreshCw, SlidersHorizontal } from "lucide-react";
import Avatar from "./Avatar";
import Feed from "./Feed";
@@ -57,8 +58,6 @@ export default function ChannelPage({
me,
view,
setView,
onBack,
onOpenChannel,
onShowInFeed,
}: {
channelId: string;
@@ -68,14 +67,13 @@ export default function ChannelPage({
// toolbar carries the same switcher and a change here is the same account-wide choice.
view: FeedView;
setView: (v: FeedView) => void;
onBack: () => void;
// Narrow the real feed to this channel and go there. Offered only for a channel you're
// subscribed to: the feed defaults to scope "my", so filtering it to a channel you don't
// follow would just land you on an empty page.
onShowInFeed: () => void;
onOpenChannel: (id: string, name?: string) => void;
}) {
const { t, i18n } = useTranslation();
const { closeChannel } = useNavigationActions();
const qc = useQueryClient();
const confirm = useConfirm();
const [tab, setTab] = useState<"videos" | "about">("videos");
@@ -245,7 +243,7 @@ export default function ChannelPage({
)}
<button
data-testid="channel-back"
onClick={onBack}
onClick={closeChannel}
className="absolute top-5 left-7 sm:left-9 z-10 inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm bg-black/45 text-white hover:bg-black/65 backdrop-blur-sm"
>
<ArrowLeft className="w-4 h-4" />
@@ -382,7 +380,6 @@ export default function ChannelPage({
ytSearch={null}
onYtSearch={() => {}}
onExitYtSearch={() => {}}
onOpenChannel={onOpenChannel}
channelScoped
/>
{!ch?.subscribed && nextToken && (