Play the platform music on the shared Learn page too
Reversing yesterday's call at Karti's direction. The provider moves from Shell up above the router in App, so a share-code visitor gets the same character as a member rather than a silent page. The reason that is safe is the same reason "autoplay" was never really autoplay: the browser refuses audio until the page has had a real gesture, so nothing plays the instant a link opens — it starts once someone is actually using the page. The anonymous page renders OUTSIDE Shell and therefore has no app header, so the mute control is added to its own chrome. Music with no way to stop it is the worst version of this feature, and a visitor who cannot find the switch does not conclude the site has taste. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+14
-3
@@ -10,6 +10,7 @@ import { ThemeProvider } from '@/lib/theme';
|
||||
import { IdentityProvider, useIdentityQuery } from '@/lib/identity';
|
||||
import { LayoutProvider } from '@/lib/layout';
|
||||
import { PiggyContextProvider } from '@/lib/piggy-context';
|
||||
import { PlatformAudioProvider } from '@/lib/audio';
|
||||
import { Shell } from '@/components/Shell';
|
||||
import { SignIn } from '@/pages/SignIn';
|
||||
import { CreateProfile } from '@/pages/CreateProfile';
|
||||
@@ -85,9 +86,19 @@ export function App() {
|
||||
void patch('/api/me/preferences', prefs).catch(() => {});
|
||||
}}
|
||||
>
|
||||
<BrowserRouter>
|
||||
<AuthGate config={config} />
|
||||
</BrowserRouter>
|
||||
{/*
|
||||
Above the router, so the music survives navigation AND covers the
|
||||
anonymous Learn page — a share-code visitor gets the same platform
|
||||
character as a member. It never plays unbidden: the browser refuses
|
||||
audio until the page has had a real gesture, so it begins when
|
||||
someone actually starts using the page, and the header control mutes
|
||||
it for good on that device.
|
||||
*/}
|
||||
<PlatformAudioProvider>
|
||||
<BrowserRouter>
|
||||
<AuthGate config={config} />
|
||||
</BrowserRouter>
|
||||
</PlatformAudioProvider>
|
||||
{/* Inside ThemeProvider: the host reads the resolved light/dark value. */}
|
||||
<Toaster />
|
||||
</ThemeProvider>
|
||||
|
||||
@@ -29,7 +29,6 @@ import { NavLink } from 'react-router-dom';
|
||||
import { useIdentity } from '@/lib/identity';
|
||||
import { useLayout } from '@/lib/layout';
|
||||
import { visibleNav, type NavItem } from '@/lib/nav';
|
||||
import { PlatformAudioProvider } from '@/lib/audio';
|
||||
import { AppHeader } from './AppHeader';
|
||||
import { AppSidebar } from './AppSidebar';
|
||||
import { PiggyDock } from './PiggyDock';
|
||||
@@ -45,14 +44,6 @@ export function Shell() {
|
||||
const items = visibleNav(identity);
|
||||
|
||||
return (
|
||||
/*
|
||||
* Music is mounted HERE rather than in App.tsx, so it wraps only the
|
||||
* signed-in application. The anonymous Learn page renders outside Shell,
|
||||
* and a share-code visitor opening a link someone sent them should not get
|
||||
* unexpected audio — that is the one context where it reads as a fault
|
||||
* rather than as character.
|
||||
*/
|
||||
<PlatformAudioProvider>
|
||||
<SidebarProvider
|
||||
open={sidebarOpen}
|
||||
onOpenChange={setSidebarOpen}
|
||||
@@ -98,7 +89,6 @@ export function Shell() {
|
||||
|
||||
<MobileTabBar items={items.filter((item) => item.primary)} />
|
||||
</SidebarProvider>
|
||||
</PlatformAudioProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ import { usePageTitle } from '@/lib/title';
|
||||
import { usePiggyContext } from '@/lib/piggy-context';
|
||||
import { toPiggyPageRoute } from '@pig/core';
|
||||
import { Badge, Button, Card, EmptyState, Skeleton } from '@/components/ui';
|
||||
import { AudioControl } from '@/components/AudioControl';
|
||||
import { PiggyMark } from '@/components/PiggyMark';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { AddResourceDialog } from '@/components/learn/AddResourceDialog';
|
||||
@@ -418,9 +419,15 @@ function AnonFrame({ children }: { children: ReactNode }) {
|
||||
<PiggyMark className="size-7 shrink-0 text-fg" aria-hidden />
|
||||
<span className="min-w-0 truncate font-semibold tracking-tight">pig</span>
|
||||
</span>
|
||||
<Button variant="ghost" size="sm" className="shrink-0" asChild>
|
||||
<a href="/">Sign in</a>
|
||||
</Button>
|
||||
<span className="flex shrink-0 items-center gap-1">
|
||||
{/* The anonymous page renders outside Shell, so it does not get the
|
||||
app header — but it DOES get the music, and music with no way to
|
||||
stop it is the worst version of this feature. */}
|
||||
<AudioControl />
|
||||
<Button variant="ghost" size="sm" className="shrink-0" asChild>
|
||||
<a href="/">Sign in</a>
|
||||
</Button>
|
||||
</span>
|
||||
</header>
|
||||
<main className="mx-auto flex w-full min-w-0 max-w-5xl flex-1 flex-col gap-10 px-4 pb-14 pt-2 sm:px-6 sm:pb-20">
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user