import { AnimatePresence, motion } from 'framer-motion' import { useEffect, useState } from 'react' import { Image, Video } from '@/components' import { BeijingUnlockInteraction, InputBg, PianoUnlockInteraction, PostcardUnlockInteraction, SelectBg, } from '../components' import { getStaticImage } from '@/lib/utils' import { LOBBY_COLUMNS, SCENE_TITLES, UNLOCK_TITLES } from './lobby.config' import ContentDialog from './ContentDialog' import UnlockHintDialog from './UnlockHintDialog' import type { DialogState } from './useDialogReducer' interface SharePayload { sceneId?: number [key: string]: unknown } interface DialogLayerProps { state: DialogState onEnterUnlock: () => void onShare: (sceneId: number, payload?: SharePayload) => void onFinishBadgeVideo: () => void onClose: () => void } interface DialogLocalState { selectedLyric?: string guizhouInput: string pianoFinished: boolean selectedQuote?: string postcardFinished: boolean beijingFinished: boolean postcardState: { hasPlane: boolean hasText: boolean postcardImagePath: string } beijingSelection: { paradeId?: string paradeName?: string paradeImagePath?: string sloganId?: string sloganImagePath?: string previewImageDataUrl?: string } } const starName = 'nieer' const DEFAULT_POSTCARD_IMAGE_PATH = 'nieer/reflection/lobby/content/场景5待交互' const ANTHEM_LYRICS = [ { value: '1', label: '起来!不愿做奴隶的人们!' }, { value: '2', label: '把我们的血肉,筑成我们新的长城!' }, { value: '3', label: '中华民族到了最危险的时候' }, { value: '4', label: '每个人被迫着发出最后的吼声' }, { value: '5', label: '起来!起来!起来!' }, { value: '6', label: '我们万众一心' }, { value: '7', label: '冒着敌人的炮火,前进!' }, { value: '8', label: '前进!前进!进!' }, ] const SMEDLEY_QUOTES = [ { value: '1', label: '建设一个强大的和自由的中国' }, { value: '2', label: '为我的遗体唱一首歌,中国的国歌……"起来"' }, { value: '3', label: '我的心灵在这个世界上除了中国的任何地方都未能找到安宁' }, ] const getCanShare = (sceneId: number, localState: DialogLocalState): boolean => { switch (sceneId) { case 1: return !!localState.selectedLyric case 2: return localState.guizhouInput.trim().length > 0 case 3: return localState.pianoFinished case 4: return !!localState.selectedQuote case 5: return localState.postcardFinished case 6: return ( localState.beijingFinished && typeof localState.beijingSelection.previewImageDataUrl === 'string' ) default: return true } } const buildSharePayload = ( sceneId: number, localState: DialogLocalState ): SharePayload | undefined => { switch (sceneId) { case 1: { const selected = ANTHEM_LYRICS.find((item) => item.value === localState.selectedLyric) return { sceneId: 1, lyricValue: localState.selectedLyric ?? '', lyricLabel: selected?.label ?? '', } } case 2: return { sceneId: 2, reflectionText: localState.guizhouInput.trim(), } case 3: return { sceneId: 3, pianoCompleted: localState.pianoFinished, pianoImagePath: 'nieer/reflection/lobby/box/音符', } case 4: { const selected = SMEDLEY_QUOTES.find((item) => item.value === localState.selectedQuote) return { sceneId: 4, quoteValue: localState.selectedQuote ?? '', quoteLabel: selected?.label ?? '', } } case 5: return { sceneId: 5, ...localState.postcardState, } case 6: return { sceneId: 6, ...localState.beijingSelection, } default: return undefined } } interface UnlockContentHandlers { onSelectLyric: (value: string) => void onChangeGuizhouInput: (value: string) => void onFinishPiano: () => void onSelectQuote: (value: string) => void onFinishPostcard: () => void onChangePostcardState: (payload: DialogLocalState['postcardState']) => void onFinishBeijing: () => void onChangeBeijingSelection: (payload: DialogLocalState['beijingSelection']) => void } const renderUnlockContent = ( sceneId: number, localState: DialogLocalState, handlers: UnlockContentHandlers ) => { switch (sceneId) { case 1: return (
场景1交互
) case 2: return (
场景2交互
) case 3: return (
) case 4: return (
场景4交互
) case 5: return ( ) case 6: return ( ) default: return null } } const createUnlockHandlers = ( setSelectedLyric: (value: string) => void, setGuizhouInput: (value: string) => void, setPianoFinished: (value: boolean) => void, setSelectedQuote: (value: string) => void, setPostcardFinished: (value: boolean) => void, setPostcardState: (payload: DialogLocalState['postcardState']) => void, setBeijingFinished: (value: boolean) => void, setBeijingSelection: (payload: DialogLocalState['beijingSelection']) => void ): UnlockContentHandlers => ({ onSelectLyric: setSelectedLyric, onChangeGuizhouInput: (value) => setGuizhouInput(value.slice(0, 10)), onFinishPiano: () => setPianoFinished(true), onSelectQuote: setSelectedQuote, onFinishPostcard: () => setPostcardFinished(true), onChangePostcardState: setPostcardState, onFinishBeijing: () => setBeijingFinished(true), onChangeBeijingSelection: setBeijingSelection, }) const DialogLayer = ({ state, onEnterUnlock, onShare, onFinishBadgeVideo, onClose, }: DialogLayerProps) => { const [selectedLyric, setSelectedLyric] = useState() const [guizhouInput, setGuizhouInput] = useState('') const [pianoFinished, setPianoFinished] = useState(false) const [selectedQuote, setSelectedQuote] = useState() const [postcardFinished, setPostcardFinished] = useState(false) const [beijingFinished, setBeijingFinished] = useState(false) const [postcardState, setPostcardState] = useState({ hasPlane: false, hasText: false, postcardImagePath: DEFAULT_POSTCARD_IMAGE_PATH, }) const [beijingSelection, setBeijingSelection] = useState({}) const dialogNonce = state.mode === 'idle' ? 0 : state.nonce useEffect(() => { setSelectedLyric(undefined) setGuizhouInput('') setPianoFinished(false) setSelectedQuote(undefined) setPostcardFinished(false) setBeijingFinished(false) setPostcardState({ hasPlane: false, hasText: false, postcardImagePath: DEFAULT_POSTCARD_IMAGE_PATH, }) setBeijingSelection({}) }, [dialogNonce]) if (state.mode === 'idle') return const scene = LOBBY_COLUMNS.find((item) => item.id === state.sceneId) if (!scene) return null const localState: DialogLocalState = { selectedLyric, guizhouInput, pianoFinished, selectedQuote, postcardFinished, beijingFinished, postcardState, beijingSelection, } const canShare = getCanShare(state.sceneId, localState) const unlockHandlers = createUnlockHandlers( setSelectedLyric, setGuizhouInput, setPianoFinished, setSelectedQuote, setPostcardFinished, setPostcardState, setBeijingFinished, setBeijingSelection ) const handleShareClick = () => { if (state.mode !== 'unlock') return onShare(state.sceneId, buildSharePayload(state.sceneId, localState)) } return ( {state.mode === 'result' && (
结果页 {state.videoSrc && (
)} 关闭
)} {state.mode === 'unlock' && ( {renderUnlockContent(state.sceneId, localState, unlockHandlers)} )} {state.mode === 'content' && ( )}
) } export default DialogLayer