import type { NextPage } from 'next'; import { useRouter } from 'next/router'; import { useAtom } from "jotai"; import { useEffect, useState } from 'react'; import { AnimatePresence } from "framer-motion"; import { Box } from "@chakra-ui/react"; import { AvailableLanguages, ImageData, IsPortrait, Language, LanguagePack } from "@states/global"; import { AssetLoader } from "@utils/loader"; import { findNearestMultiple, LanguagePack as _LanguagePack, localGet, localSet, Nullable, useLocale, waitAsync } from "@utils/common"; import { Footer } from "@components/footer"; import { Header } from '@components/header'; import { IntroLogo } from "@components/logo/IntroLogo"; import { Body } from '@components/body'; import { LogoLarge_EN } from "@components/logo/EN/EN-big"; import { LogoLarge_CN } from "@components/logo/CN/CN-big.v2"; import { LogoLarge_JP } from "@components/logo/JP/JP-big"; import { LogoLarge_KR } from "@components/logo/KR/KR-big"; import { MotionBox, MotionFlex } from '@components/motion'; interface PageProps { lang: string, langPack: string, fullIntro: Nullable, } function getIntroAnimSpeed(lang: string) { switch (lang) { default: case 'en': return 1.35; case 'cn': return 1.545; case 'jp': return 2.3; case 'kr': return 1.8; } } function getPostIntroAnimSpeed(lang: string) { switch (lang) { default: return null; case 'kr': return 1.5; } } const Home: NextPage = ({ lang, fullIntro, langPack }) => { const [progressPercentage , setProgressPercentage] = useState(0); const [finishedLoading, setFinishedLoading] = useState(false); const [logoVisible, setLogoVisible] = useState(false); const [introVisible, setIntroVisible] = useState(false); const [introFinished, setIntroFinished] = useState(false); const [dontAnimate, setDontAnimate] = useState>(true); const initalLangPack: Partial<_LanguagePack> = { [lang]: JSON.parse(langPack) }; const [currentLang, setCurrentLang] = useAtom(Language); const [, setLangPack] = useAtom(LanguagePack); const [, setImageData] = useAtom(ImageData); const locale = useLocale(useAtom(Language)[0], initalLangPack); const loadDependencies = [ ...[ ...new Array(8) .fill(0) .map((_, i) => `0${i + 1}_HD`), ...[ "bg", "world_bg", "department_bg", ] ].map((i) => ({ url: `assets/img/${i}.jpg`, overrideOptions: { mimeType: 'image/jpeg' } })), ...AvailableLanguages .filter(l => l !== lang) .map(l => ({ url: `assets/lang/${l}.json`, overrideOptions: { responseType: 'json', mimeType: 'application/json' } })), ]; const [progressData, setProgressData] = useState({ total: loadDependencies.length, loaded: 0, success: 0, _lastPercentage: 0, }); const router = useRouter(); if (!fullIntro && 'fullIntro' in router.query) fullIntro = router.query.fullIntro?.toString() ?? null; useEffect(() => { setLangPack(initalLangPack); if (currentLang !== lang) setCurrentLang(lang); if (localGet('fullIntro') === 'true' && fullIntro === null) void router.push({ pathname: '/', query: { fullIntro: 'true', } }); console.log(lang); let animateLogo = true; if (fullIntro === 'true' || (fullIntro === null && localGet('fullIntro') === 'true')) document.body.style.setProperty('--anim-playback-rate', getIntroAnimSpeed(lang ?? '').toString()); else { let time = localGet('endfield-time'); if (!time) localSet('endfield-time', new Date().toISOString() + "@first"); else { if (time.includes('@first')) localSet('endfield-time', time.replace('@first', '')); else { const timeThen = new Date().getTime(); const timeDiff = Date.now() - timeThen; if (timeDiff < 1000 * 60 * 60 * 24) animateLogo = false; else localSet('endfield-time', new Date(timeThen + 1000 * 60 * 60 * 24).toISOString()); } } } setDontAnimate(animateLogo ? null : true); (async () => { const loader = new AssetLoader( loadDependencies, { responseType: 'arraybuffer', onProgressUpdate: (v, requests) => { const percentage = Math.floor(v * 100); setProgressData(prev => { if (percentage >= findNearestMultiple(100 / requests.length, prev._lastPercentage)) { let success = 0, loaded = 0; for (const request of requests) { if (request.success) { success++; continue; } if (request.progress === 1) loaded++; } return { total: requests.length, loaded: loaded + success, success, _lastPercentage: percentage }; } return prev; }); setProgressPercentage(percentage); } } ); loader.await().then(resolved => { setProgressPercentage(100); const imageData = new Map(); const langPack: Partial<_LanguagePack> = {}; for (const data of resolved) { if (data.url.includes('lang/')) langPack[ data.url .split('/') .at(-1)! .split('.')[0] as keyof _LanguagePack ] = data.resolved as Record; if (data.url.includes('img/')) imageData.set( data.url, data.resolved ? URL.createObjectURL(new Blob([data.resolved as Blob])) : 'null' ); } setLangPack(langPack); setImageData(imageData); waitAsync(500).then(() => setProgressPercentage(() => 101)); }); await waitAsync(500).then(() => setIntroVisible(() => true)); await waitAsync(3000).then(() => setIntroVisible(() => false)); await waitAsync(500).then(() => { setLogoVisible(() => true); setIntroFinished(() => true); }); await waitAsync(animateLogo ? 6500 : 1200) .then(() => { setLogoVisible(() => false); const postIntroAnimSpeed = getPostIntroAnimSpeed(lang ?? ''); if (postIntroAnimSpeed) document.body.style.setProperty('--anim-playback-rate', postIntroAnimSpeed.toString()); }); await waitAsync(500) .then(() => setFinishedLoading(() => true)); })(); }, []); return
{ (progressPercentage < 101) && {progressPercentage >= 100 ? locale("init-prgs-bar.ready") : (({ loaded, success }) => <> {progressPercentage}% {locale("init-prgs-bar.loading")} {loaded} / {loadDependencies.length} { loaded !== success &&  ({loaded - success} {locale("init-prgs-bar.failed")}) } )(progressData) } 100 ? 100 : progressPercentage) + '%' }} transition={{ duration: .3, easings: [0.88,-0.07, 0.22, 1.01], }} > {/**/} } { introVisible && } {(() => { if (!((logoVisible || progressPercentage < 101) && introFinished)) return null; const config = { dontAnimateChild: dontAnimate, key: `logo-endfield-${currentLang}` }; switch (currentLang) { case 'en': return ; case 'cn': return ; case 'jp': return ; case 'kr': return ; } })()} {finishedLoading && progressPercentage === 101 && <>
}
; }; export async function getServerSideProps(context: { query: Record }) { let lang = 'en'; if (AvailableLanguages.includes(context.query.lang ?? '')) lang = context.query.lang as string; const langPack = await import(`../lang/${lang}.json`); return { props:{ lang, langPack: JSON.stringify(langPack), fullIntro: context.query.fullIntro ?? null, } }; } export default Home;