import { lazy, Suspense, useMemo, useState } from "react";
import { classById, FACTIONS, raceById } from "../app/characterCatalog";
import { selectedCharacter, useShellStore } from "../app/shellStore";
import { DualDisplayFrame } from "../components/DualDisplayFrame";
import { useMenuController, type MenuAction } from "../input/useMenuController";
import { CharacterPreview } from "./CharacterPreview";
import { LazyLocalCompanionPanel } from "./LazyLocalCompanionPanel";
import { ControllerButton } from "./ControllerButton";
import { ContentManagerScreen } from "./ContentManagerScreen";
import { BrandMark, ControllerLegend, FrontSurface } from "./FrontSurface";
import { OnlineGroupPanel } from "./OnlineGroupPanel";
import { sessionCanUseShelvedGmTools, SHELVED_MODES_ENABLED } from "../app/releaseFeatures";
import { DungeonReportsScreen } from "./DungeonReportsScreen";
import { MainMenuCharacterEditor, type MainMenuEditor } from "./MainMenuCharacterEditor";
const BossCardCollectionScreen = lazy(() => import("./BossCardCollection"));
const BossTestingScreen = lazy(() => import("./BossTestingScreen").then((module) => ({ default: module.BossTestingScreen })));
const GAME_MODES = [
{
id: "dungeons",
number: "01",
name: "Dungeons",
description: "Choose an expedition and lead your party into the depths.",
available: true,
},
...(SHELVED_MODES_ENABLED ? [{
id: "manastorms" as const,
number: "02",
name: "Manastorms",
description: "Chain random boss encounters as the storm grows stronger and more rewarding.",
available: true,
}, {
id: "arenas" as const,
number: "03",
name: "Arenas",
description: "Rated 2v2 and 3v3 combat against players or rating-matched opponents.",
available: true,
}] : []),
{
id: "trials",
number: "04",
name: "Trials",
description: "A new mode is taking shape.",
available: false,
},
{
id: "downloads",
number: "05",
name: "Downloads",
description: "Install, update, or remove adventures that remain playable offline.",
available: true,
},
{
id: "options",
number: "06",
name: "Options",
description: "Main-menu settings are coming soon.",
available: false,
},
{
id: "player-profile",
number: "07",
name: "Player Profile",
description: "Profile details are coming soon.",
available: false,
},
] as const;
export function MainMenuScreen() {
const [contentManagerOpen, setContentManagerOpen] = useState(false);
const [reportsOpen, setReportsOpen] = useState(false);
const [cardsOpen, setCardsOpen] = useState(false);
const [bossTestingOpen, setBossTestingOpen] = useState(false);
const [editor, setEditor] = useState(null);
if (editor) return setEditor(null)} />;
if (bossTestingOpen) return Opening Boss Testing…
}> setBossTestingOpen(false)} />;
if (cardsOpen) return Opening collection log…}> setCardsOpen(false)} />;
if (contentManagerOpen) return setContentManagerOpen(false)} />;
if (reportsOpen) return setReportsOpen(false)} />;
return setContentManagerOpen(true)} onOpenReports={() => setReportsOpen(true)} onOpenCards={() => setCardsOpen(true)} onOpenBossTesting={() => setBossTestingOpen(true)} onOpenEditor={setEditor} />;
}
function MainMenuDestinations({ onOpenDownloads, onOpenReports, onOpenCards, onOpenBossTesting, onOpenEditor }: {
readonly onOpenDownloads: () => void;
readonly onOpenReports: () => void;
readonly onOpenCards: () => void;
readonly onOpenBossTesting: () => void;
readonly onOpenEditor: (editor: MainMenuEditor) => void;
}) {
const activeCharacter = useShellStore((state) => state.activeCharacter);
const rosterCharacter = useShellStore(selectedCharacter);
const openDungeons = useShellStore((state) => state.openDungeons);
const openManastorms = useShellStore((state) => state.openManastorms);
const openArenas = useShellStore((state) => state.openArenas);
const openClassHall = useShellStore((state) => state.openClassHall);
const returnToCharacters = useShellStore((state) => state.returnToCharacters);
const notice = useShellStore((state) => state.notice);
const session = useShellStore((state) => state.session);
const openGmAdmin = useShellStore((state) => state.openGmAdmin);
const character = activeCharacter ?? rosterCharacter;
const isRom = character?.categoryId === "rom";
const isGm = sessionCanUseShelvedGmTools(session);
const actions = useMemo(() => [
{
id: "mode-dungeons",
run: openDungeons,
neighbors: { right: "mode-manastorms", down: "back-to-roster" },
},
...(SHELVED_MODES_ENABLED ? [{
id: "mode-manastorms",
run: openManastorms,
neighbors: { left: "mode-dungeons", down: "back-to-roster" },
}, {
id: "mode-arenas",
run: openArenas,
neighbors: { left: "mode-manastorms", down: "back-to-roster" },
}] : []),
{
id: "mode-downloads",
run: onOpenDownloads,
neighbors: { left: SHELVED_MODES_ENABLED ? "mode-manastorms" : "mode-dungeons", down: "back-to-roster" },
},
{
id: "back-to-roster",
run: returnToCharacters,
neighbors: { up: "mode-dungeons", left: "mode-dungeons" },
},
...(character ? [
{ id: "mode-class-hall", run: openClassHall },
{ id: "mode-talents", run: () => onOpenEditor("talents") },
{ id: "mode-keybinds", run: () => onOpenEditor("keybinds") },
{ id: "mode-bindings", run: () => onOpenEditor("bindings") },
] : []),
...(isGm ? [{ id: "mode-gm-tools", run: openGmAdmin }] : []),
{ id: "mode-reports", run: onOpenReports },
{ id: "mode-cards", run: onOpenCards },
{ id: "mode-boss-testing", run: onOpenBossTesting },
], [character, isGm, onOpenBossTesting, onOpenCards, onOpenDownloads, onOpenEditor, onOpenReports, openArenas, openClassHall, openDungeons, openGmAdmin, openManastorms, returnToCharacters]);
const controller = useMenuController(actions, {
initialId: "mode-dungeons",
onBack: returnToCharacters,
});
const race = character ? raceById(character.raceId) : null;
const characterClass = character ? classById(character.classId) : null;
return (
{notice && {notice}
}
}
bottom={}
/>
);
}