Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 13 additions & 20 deletions src/components/DevPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,25 +80,18 @@ export function DevPalette() {
},
}
: null
// Dev-only "mature island" preview — flips the sparse-by-default
// Flowers/Tree/Butterflies views into showAll so we can see what a
// saturated island looks like without scripting captures. Toggle off
// restores the sparse state (only what the student has actually
// earned through captures remains visible).
const matureIsland: Command | null = import.meta.env.DEV
? {
id: 'mature-island',
label: matureIslandOn ? 'Hide mature island' : 'Show mature island',
hint: 'dev preview',
run: () => {
setOpen(false)
window.dispatchEvent(
new CustomEvent('ss:mature-island-toggle', { detail: { on: !matureIslandOn } }),
)
setMatureIslandOn((v) => !v)
},
}
: null
const matureIsland: Command = {
id: 'mature-island',
label: matureIslandOn ? 'Hide mature island' : 'Show mature island',
hint: 'island preview',
run: () => {
setOpen(false)
window.dispatchEvent(
new CustomEvent('ss:mature-island-toggle', { detail: { on: !matureIslandOn } }),
)
setMatureIslandOn((v) => !v)
},
}
return [
{ id: 'ui', label: 'Switch to UI mode', hint: '/', run: go('/') },
{
Expand All @@ -118,7 +111,7 @@ export function DevPalette() {
},
...(cameraTuner ? [cameraTuner] : []),
...(hatchTuner ? [hatchTuner] : []),
...(matureIsland ? [matureIsland] : []),
matureIsland,
{
id: 'restart-onboarding',
label: 'Restart onboarding',
Expand Down
8 changes: 1 addition & 7 deletions src/components/student-space/EngineHost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ export function EngineHost({
<MoodSheet />
{showOnboardingFlow ? <OnboardingFlow /> : null}
{import.meta.env.DEV && game ? <CameraTuneBridge game={game} /> : null}
{import.meta.env.DEV && game ? <MatureIslandBridge game={game} /> : null}
{game ? <MatureIslandBridge game={game} /> : null}
{children}
</EngineOverlayProvider>
</EngineContext.Provider>
Expand All @@ -292,12 +292,6 @@ export function EngineHost({
* static framing without a remount. The HUD itself is hidden until the
* palette dispatches CAMERA_TUNER_OPEN_EVENT.
*/
/**
* DEV-only bridge: listens for the dev palette's `ss:mature-island-toggle`
* event and flips the sparse-by-default Flowers / Tree / Butterflies views
* into showAll (or back to hidden — only what the student has earned by
* capturing stays visible).
*/
function MatureIslandBridge({ game }: { game: Game }) {
useEffect(() => {
const view = (
Expand Down
33 changes: 28 additions & 5 deletions test/components/DevPalette.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ beforeEach(() => {

afterEach(() => {
document.body.classList.remove('is-dev-overlay-hidden')
document.body.classList.remove('is-world-controls-visible')
navigate.mockClear()
vi.unstubAllEnvs()
Object.defineProperty(window.location, 'assign', {
configurable: true,
writable: true,
Expand Down Expand Up @@ -117,14 +119,35 @@ describe('DevPalette', () => {
render(<DevPalette />)
await user.keyboard('{Meta>}k{/Meta}')

await user.click(screen.getByRole('option', { name: /show world controls/i }))
expect(document.body).toHaveClass('is-world-controls-visible')
expect(localStorage.getItem('sm:world-controls-visible')).toBe('1')

await user.keyboard('{Meta>}k{/Meta}')
await user.click(screen.getByRole('option', { name: /hide world controls/i }))
expect(document.body).toHaveClass('is-dev-overlay-hidden')
expect(localStorage.getItem('sm:dev-overlay-hidden')).toBe('1')
expect(document.body).not.toHaveClass('is-world-controls-visible')
expect(localStorage.getItem('sm:world-controls-visible')).toBeNull()
})

it('keeps mature island preview available in production builds', async () => {
vi.stubEnv('DEV', false)
const user = userEvent.setup()
const matureIslandListener = vi.fn()
window.addEventListener('ss:mature-island-toggle', matureIslandListener)
render(<DevPalette />)

await user.keyboard('{Meta>}k{/Meta}')
await user.click(screen.getByRole('option', { name: /show world controls/i }))
expect(document.body).not.toHaveClass('is-dev-overlay-hidden')
expect(localStorage.getItem('sm:dev-overlay-hidden')).toBeNull()
expect(screen.getByRole('option', { name: /show mature island/i })).toBeInTheDocument()
expect(screen.queryByRole('option', { name: /show camera tuner/i })).not.toBeInTheDocument()
expect(screen.queryByRole('option', { name: /show hatch tuner/i })).not.toBeInTheDocument()

await user.click(screen.getByRole('option', { name: /show mature island/i }))
expect(matureIslandListener).toHaveBeenCalledTimes(1)
expect(matureIslandListener.mock.calls[0]?.[0]).toMatchObject({
detail: { on: true },
})

window.removeEventListener('ss:mature-island-toggle', matureIslandListener)
})

it('restarts onboarding from Cmd-K without clearing the full student-space state', async () => {
Expand Down
Loading