import { createContext, lazy, Suspense, useCallback, useContext, useEffect, useMemo, useState, type ReactNode, } from "react"; import { qk } from "../lib/queryKeys"; import { useQuery } from "@tanstack/react-query"; import { api } from "../lib/api"; import { shouldAutoOpenOnboarding } from "../lib/onboarding"; const OnboardingWizard = lazy(() => import("./OnboardingWizard")); // Owns the onboarding wizard's open state (and the wizard render itself), lifted out of App so any // module can trigger "connect YouTube" via a hook instead of an onOpenWizard prop threaded through // the tree. Mirrors the other split-context providers; composed in main.tsx around . // // The wizard auto-opens on first login for accounts that still need to connect YouTube (derived from // granted scopes + storage flags, so it's stable across the OAuth round-trip) and is reopenable from // Settings / the notify "reconnect" action. It reads `me` as a passive qk.me() observer (App owns the // fetching query), so it re-runs the auto-open check when the account resolves or its grants change. interface WizardActions { openWizard: () => void; closeWizard: () => void; } // Only the actions are shared — the open flag stays local to the provider (it renders the wizard // itself), so no consumer needs to subscribe to it. const ActionsContext = createContext({ openWizard: () => {}, closeWizard: () => {}, }); export function useWizard(): WizardActions { return useContext(ActionsContext); } export function WizardProvider({ children }: { children: ReactNode }) { const [open, setOpen] = useState(false); // Passive observer of the account App fetches (enabled:false → reads cache, re-renders on update). const { data: me } = useQuery({ queryKey: qk.me(), queryFn: api.me, enabled: false }); const openWizard = useCallback(() => setOpen(true), []); const closeWizard = useCallback(() => setOpen(false), []); // First-login onboarding: prompt the user to connect YouTube (and resume the flow after each // consent redirect). Re-checked when the account or its grants change. useEffect(() => { if (me && shouldAutoOpenOnboarding(me)) setOpen(true); }, [me?.id, me?.can_read, me?.can_write]); const actions = useMemo( () => ({ openWizard, closeWizard }), [openWizard, closeWizard], ); return ( {children} {/* The wizard is a full-screen overlay; the demo account can't connect YouTube, so it never opens there. Lazy — its chunk loads only when first opened. */} {open && me && !me.is_demo && } ); }