import type { Page } from "./urlState"; // Tiny decoupled navigator so deep components (a feed card's download toast, the Download // Center) can switch pages without threading setPage through the whole tree. NavigationProvider // registers its setPage on mount; navigateTo is a no-op until then. let _navigate: ((p: Page) => void) | null = null; export function setNavigator(fn: (p: Page) => void): void { _navigate = fn; } /** The "View" on a "Download added" toast is clicked INSIDE the player (its toast host). That is * safe because `setPage` closes every open overlay before it pushes (see * `lib/history.closeOverlaysThenNavigate`) — without it the player's Back-to-close cleanup popped the * entry the navigation had just pushed (deep-review round 4). */ export function navigateTo(p: Page): void { _navigate?.(p); } /** Should this click be handled IN-APP, or left to the browser? * * An anchor that ALSO navigates in-app has to keep the browser's own gestures working — Ctrl/Cmd-click * and Shift-click open a tab/window, and middle-click arrives as `auxclick` and never reaches React's * `onClick` at all (the `button !== 0` arm is belt-and-braces for synthetic events). Otherwise the * thing looks like a link and behaves like a button, which is what the channel name in the player did. * One predicate, so a second such link cannot forget an arm. */ export function isPlainLeftClick(e: { metaKey: boolean; ctrlKey: boolean; shiftKey: boolean; altKey: boolean; button: number; }): boolean { return !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey && e.button === 0; }