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:
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { createPortal } from "react-dom";
|
||||
import { useNavigationActions } from "./NavigationProvider";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { AlertTriangle, ArrowLeft, Check, CheckCheck, ChevronLeft, ChevronRight, ExternalLink, Repeat, Repeat1, Settings, Shuffle, SkipBack, SkipForward, Volume2, VolumeX, X } from "lucide-react";
|
||||
import Avatar from "./Avatar";
|
||||
@@ -55,7 +56,6 @@ export default function PlayerModal({
|
||||
startIndex,
|
||||
onClose,
|
||||
onState,
|
||||
onOpenChannel,
|
||||
}: {
|
||||
video: Video;
|
||||
// Where to start the opened video: a number of seconds (0 = Restart), or null/undefined
|
||||
@@ -70,9 +70,9 @@ export default function PlayerModal({
|
||||
onState: (id: string, status: string) => void;
|
||||
// Open the active video's channel page in-app (closes the player first). The small external
|
||||
// icon next to the name keeps the open-on-YouTube behaviour.
|
||||
onOpenChannel?: (channelId: string, channelName?: string) => void;
|
||||
}) {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { openChannel } = useNavigationActions();
|
||||
const qc = useQueryClient();
|
||||
const descFade = useScrollFade();
|
||||
// Browser/mouse Back closes the player instead of leaving the page.
|
||||
@@ -840,16 +840,15 @@ export default function PlayerModal({
|
||||
<div className="flex items-center gap-1.5 shrink-0 min-w-0">
|
||||
<button
|
||||
onClick={() => {
|
||||
if (!onOpenChannel) return onClose();
|
||||
const cid = active.channel_id;
|
||||
const cname = active.channel_title ?? undefined;
|
||||
// Closing the player pops its own history entry (useBackToClose → history.back()).
|
||||
// Open the channel only AFTER that pop's popstate — pushing the channel entry
|
||||
// before it would let the back remove it again (the bug: clicking the name only
|
||||
// closed the player). One-shot listener fires after App's popstate handler.
|
||||
// closed the player). One-shot listener fires after the popstate handler.
|
||||
const open = () => {
|
||||
window.removeEventListener("popstate", open);
|
||||
onOpenChannel(cid, cname);
|
||||
openChannel(cid, cname);
|
||||
};
|
||||
window.addEventListener("popstate", open);
|
||||
onClose();
|
||||
|
||||
Reference in New Issue
Block a user