refactor(wizard): move onboarding wizard state into WizardProvider

Lift the onboarding wizard's open state, first-login auto-open effect, and the
wizard render itself out of App into WizardProvider. Feed, Channels, and
SettingsPanel trigger it via useWizard() instead of an onOpenWizard prop; App
and ChannelPage drop the prop plumbing. First step of S6b.3 — removing the
per-module props that block a uniform registry render. (Platform S6b.3)
This commit is contained in:
2026-07-19 00:55:34 +02:00
parent 8434aac78d
commit dd921e3209
7 changed files with 87 additions and 37 deletions
+6 -4
View File
@@ -32,6 +32,7 @@ import { FEED_VIEWS, type FeedView } from "../lib/feedView";
import { clearedFilters, useActiveFilters } from "../lib/useActiveFilters";
import ActiveFilterChips from "./ActiveFilterChips";
import { PageToolbar } from "./PageShell";
import { useWizard } from "./WizardProvider";
import ViewSwitcher from "./ViewSwitcher";
import VirtualFeed from "./VirtualFeed";
// Lazy: the in-app YouTube player (IFrame API) loads only when a video is first opened.
@@ -85,7 +86,6 @@ export default function Feed({
setView,
canRead,
isDemo = false,
onOpenWizard,
ytSearch,
onYtSearch,
onExitYtSearch,
@@ -93,13 +93,13 @@ export default function Feed({
}: {
filters: FeedFilters;
setFilters: (f: FeedFilters) => void;
// The view mode is an account pref, not a filter: App owns it and it persists on pick, so it
// isn't part of FeedFilters (no share-link param, no saved view, no active-filter chip).
// The view mode is an account pref, not a filter: it persists on pick, so it isn't part of
// FeedFilters (no share-link param, no saved view, no active-filter chip). Provided by the caller
// (FeedViewProvider on the feed page; ChannelPage threads its own).
view: FeedView;
setView: (v: FeedView) => void;
canRead: boolean;
isDemo?: boolean;
onOpenWizard: () => void;
// Live YouTube search: the active search term (null = normal feed). Entering a search and
// leaving it both step browser history (the search is a feed sub-view with its own history
// entry), so the empty-state CTA enters via onYtSearch and "back to feed" pops via
@@ -112,6 +112,8 @@ export default function Feed({
channelScoped?: boolean;
}) {
const { t } = useTranslation();
// "Connect YouTube" onboarding lives in WizardProvider (the empty-state CTA when not connected).
const { openWizard: onOpenWizard } = useWizard();
// Same list the panel's badge counts — see lib/useActiveFilters.
const activeFilters = useActiveFilters(filters, setFilters);
const sortKeys = channelScoped