diff --git a/src/App.tsx b/src/App.tsx index b24afee..549155e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { FC, useEffect, useState } from 'react'; +import React, { FC, useEffect, useState, Suspense } from 'react'; import './App.scss'; import { domRelatedOptForTheme, @@ -12,8 +12,8 @@ import { BeiAn } from './components/BeiAn'; import { Title } from './components/Title'; import { PersonalInfo } from './components/PersonalInfo'; import { Info } from './components/Info'; -import { ThemeChanger } from './components/ThemeChanger'; -import { ConfigDialog } from './components/ConfigDialog'; +const ThemeChanger = React.lazy(() => import('./components/ThemeChanger')); +const ConfigDialog = React.lazy(() => import('./components/ConfigDialog')); // 读取缓存关卡得分 const initLevel = Number(localStorage.getItem(LAST_LEVEL_STORAGE_KEY) || '1'); @@ -63,37 +63,39 @@ const App: FC<{ theme: Theme }> = ({ theme: initTheme }) => { /> )} - <PersonalInfo /> <Game key={theme.title} theme={theme} initLevel={initLevel} initScore={initScore} /> + <PersonalInfo /> <div className={'flex-spacer'} /> <p style={{ textAlign: 'center', fontSize: 10, opacity: 0.5 }}> <span id="busuanzi_container_site_pv"> - {' '} 累计访问: <span id="busuanzi_value_site_pv" />次 </span> <br /> <BeiAn /> </p> - <Info /> - {!theme.pure && ( - <> - <ThemeChanger - changeTheme={changeTheme} - onDiyClick={() => setDiyDialogShow(true)} - /> - <ConfigDialog - show={diyDialogShow} - closeMethod={() => setDiyDialogShow(false)} - previewMethod={previewTheme} - /> - </> - )} + <Suspense fallback={<span>Loading</span>}> + {!theme.pure && ( + <> + <Info /> + <ThemeChanger + changeTheme={changeTheme} + onDiyClick={() => setDiyDialogShow(true)} + /> + {diyDialogShow && ( + <ConfigDialog + closeMethod={() => setDiyDialogShow(false)} + previewMethod={previewTheme} + /> + )} + </> + )} + </Suspense> </> ); }; diff --git a/src/components/ConfigDialog.module.scss b/src/components/ConfigDialog.module.scss index b0881ae..6e614c7 100644 --- a/src/components/ConfigDialog.module.scss +++ b/src/components/ConfigDialog.module.scss @@ -1,3 +1,15 @@ +@keyframes show { + 0% { + transform: translateX(-50%) translateY(-100%); + opacity: 0; + } + + 100% { + transform: translateX(-50%) translateY(0); + opacity: 1; + } +} + .dialog { text-align: left; overflow-y: auto; @@ -17,8 +29,7 @@ width: calc(100% - 32px); max-width: 500px; bottom: 0; - transform: translateX(-50%) translateY(-100%); - opacity: 0; + animation: ease-in-out show 0.3s both; transition: 0.3s; padding: 16px; display: flex; @@ -32,11 +43,6 @@ } } - &Show { - transform: translateX(-50%) translateY(0); - opacity: 1; - } - .error { color: crimson; } diff --git a/src/components/ConfigDialog.tsx b/src/components/ConfigDialog.tsx index 8c116d8..8ddb1d2 100644 --- a/src/components/ConfigDialog.tsx +++ b/src/components/ConfigDialog.tsx @@ -8,22 +8,11 @@ import { captureElement, LAST_UPLOAD_TIME_STORAGE_KEY } from '../utils'; import { copy } from 'clipboard'; const STORAGEKEY = 'customTheme'; -let storageTheme: Theme<any>; -try { - const configString = localStorage.getItem(STORAGEKEY); - if (configString) { - const parseRes = JSON.parse(configString); - if (typeof parseRes === 'object') storageTheme = parseRes; - } -} catch (e) { - // -} -export const ConfigDialog: FC<{ - show: boolean; +const ConfigDialog: FC<{ closeMethod: () => void; previewMethod: (theme: Theme<string>) => void; -}> = ({ show, closeMethod, previewMethod }) => { +}> = ({ closeMethod, previewMethod }) => { const [sounds, setSounds] = useState<Sound[]>([]); const [icons, setIcons] = useState<Icon[]>([]); const inputRefMap = useRef< @@ -57,38 +46,44 @@ export const ConfigDialog: FC<{ // 初始化 useEffect(() => { - if (storageTheme) { - const { - title, - desc = '', - bgm = '', - sounds, - icons, - background = '', - backgroundBlur = false, - } = storageTheme; - setSounds( - sounds.filter( - (s) => !['triple', 'button-click'].includes(s.name) - ) - ); - setIcons( - icons.map((icon) => { - if (icon.clickSound === 'button-click') - icon.clickSound = ''; - if (icon.tripleSound === 'triple') icon.tripleSound = ''; - return icon; - }) - ); - setCustomThemeInfo({ - title, - // @ts-ignore - desc, - bgm, - background, - backgroundBlur, - }); + let storageTheme: Theme<any> | undefined = undefined; + try { + const configString = localStorage.getItem(STORAGEKEY); + if (configString) { + const parseRes = JSON.parse(configString); + if (typeof parseRes === 'object') storageTheme = parseRes; + } + } catch (e) { + // } + if (!storageTheme) return; + const { + title, + desc = '', + bgm = '', + sounds, + icons, + background = '', + backgroundBlur = false, + } = storageTheme; + setSounds( + sounds.filter((s) => !['triple', 'button-click'].includes(s.name)) + ); + setIcons( + icons.map((icon) => { + if (icon.clickSound === 'button-click') icon.clickSound = ''; + if (icon.tripleSound === 'triple') icon.tripleSound = ''; + return icon; + }) + ); + setCustomThemeInfo({ + title, + // @ts-ignore + desc, + bgm, + background, + backgroundBlur, + }); }, []); // 音效保存 @@ -340,7 +335,6 @@ export const ConfigDialog: FC<{ className={classNames( style.dialog, style.dialogWrapper, - show && style.dialogShow, 'flex-container flex-container' )} > @@ -646,3 +640,5 @@ export const ConfigDialog: FC<{ </div> ); }; + +export default ConfigDialog; diff --git a/src/components/ThemeChanger.tsx b/src/components/ThemeChanger.tsx index 59a9f30..d4856fb 100644 --- a/src/components/ThemeChanger.tsx +++ b/src/components/ThemeChanger.tsx @@ -16,7 +16,7 @@ const BuiltinThemes = [ pddTheme, ]; -export const ThemeChanger: FC<{ +const ThemeChanger: FC<{ changeTheme: (theme: Theme<any>) => void; onDiyClick: () => void; }> = ({ changeTheme, onDiyClick }) => { @@ -75,3 +75,5 @@ export const ThemeChanger: FC<{ </div> ); }; + +export default ThemeChanger;