From e4648945d1621b0ddda65444850d840faf281a59 Mon Sep 17 00:00:00 2001 From: Haoyu Xu Date: Tue, 28 Feb 2023 14:20:28 -0500 Subject: [PATCH] feat(directory): init operator page --- Version | 2 +- aklive2d.js | 2 +- directory/.env | 5 +- directory/Version | 2 +- directory/src/App.jsx | 1 + directory/src/component/popup.css | 16 +++- directory/src/context/useConfigContext.jsx | 13 ++- directory/src/context/useHeaderContext.jsx | 7 +- directory/src/context/useLanguageContext.jsx | 15 +++- directory/src/db/index.js | 1 + directory/src/i18n.json | 6 +- directory/src/routes/path/home.jsx | 27 ++---- directory/src/routes/path/operator.jsx | 38 ++++++++- directory/src/routes/root.css | 17 +++- directory/src/routes/root.jsx | 88 ++++++++++++-------- libs/directory.js | 2 + libs/version.js | 6 +- vite.config.js | 7 +- 18 files changed, 172 insertions(+), 83 deletions(-) diff --git a/Version b/Version index a8bf53a..050ffa7 100644 --- a/Version +++ b/Version @@ -1 +1 @@ -3.3.11 \ No newline at end of file +3.3.13 \ No newline at end of file diff --git a/aklive2d.js b/aklive2d.js index 247577f..af8cc40 100644 --- a/aklive2d.js +++ b/aklive2d.js @@ -37,7 +37,7 @@ async function main() { for (const [key, _] of Object.entries(__config.operators)) { OPERATOR_NAMES.push(key) } - increase(__projetRoot) + __config.version.showcase = increase(__projetRoot) break case 'preview': assert(OPERATOR_NAMES.length !== 0, 'Please set the operator name.') diff --git a/directory/.env b/directory/.env index e8878ab..f0a27de 100644 --- a/directory/.env +++ b/directory/.env @@ -1,3 +1,4 @@ VITE_APP_TITLE=AKLive2D -VITE_VERSION=0.5.7 -VITE_APP_VOICE_URL=jp/CN_037.ogg \ No newline at end of file +VITE_VERSION=0.5.9 +VITE_APP_VOICE_URL=jp/CN_037.ogg +VITE_SHOWCASE_VERSION=3.3.13 \ No newline at end of file diff --git a/directory/Version b/directory/Version index b35b9dd..89235c0 100644 --- a/directory/Version +++ b/directory/Version @@ -1 +1 @@ -0.5.8 \ No newline at end of file +0.5.9 \ No newline at end of file diff --git a/directory/src/App.jsx b/directory/src/App.jsx index 66523b0..0444c94 100644 --- a/directory/src/App.jsx +++ b/directory/src/App.jsx @@ -32,6 +32,7 @@ const router = createBrowserRouter( index={route.index} path={route.path} element={route.element} + loader={route.loader} /> ) })} diff --git a/directory/src/component/popup.css b/directory/src/component/popup.css index 05794a7..d58c447 100644 --- a/directory/src/component/popup.css +++ b/directory/src/component/popup.css @@ -25,7 +25,7 @@ flex-direction: column; align-items: stretch; flex-wrap: nowrap; - width: 480px; + max-width: 480px; height: fit-content; margin: 0 auto; background-color: var(--root-background-color); @@ -55,6 +55,20 @@ padding: 1rem 1rem 0 1rem; } +@media (max-width: 768px) { + .popup .title { + font-size: 2rem; + } + + .popup .content { + font-size: 1rem; + } + + .popup .return-button { + transform: scale(0.8); + } +} + .popup .overlay { position: absolute; left: 0; diff --git a/directory/src/context/useConfigContext.jsx b/directory/src/context/useConfigContext.jsx index 8e4c438..f94a880 100644 --- a/directory/src/context/useConfigContext.jsx +++ b/directory/src/context/useConfigContext.jsx @@ -1,18 +1,29 @@ import { createContext, useState, useEffect } from "react" +import db from "@/db" export const ConfigContext = createContext() export function ConfigProvider(props) { const [config, setConfig] = useState([]) + const [operators, setOperators] = useState([]) useEffect(() => { fetch("/_assets/directory.json").then(res => res.json()).then(data => { setConfig(data) + db.config.put({ key: "config", value: data }) + let operatorsList = [] + data.operators.forEach((item) => { + operatorsList = [...operatorsList, ...item] + }) + setOperators(operatorsList) + }) + fetch("/_assets/version.json").then(res => res.json()).then(data => { + db.config.put({ key: "version", value: data }) }) }, []) return ( - + {props.children} ) diff --git a/directory/src/context/useHeaderContext.jsx b/directory/src/context/useHeaderContext.jsx index 9223dd2..1fb7d1c 100644 --- a/directory/src/context/useHeaderContext.jsx +++ b/directory/src/context/useHeaderContext.jsx @@ -15,15 +15,12 @@ export function HeaderProvider(props) { language, i18n } = useContext(LanguageContext) - const [tabs, setTabs] = useState(null) + const [tabs, setTabs] = useState([]) const [currentTab, setCurrentTab] = useState([]) const [appbarExtraArea, setAppbarExtraArea] = useState([]) useEffect(() => { - let newTitle = key - if (i18n.key[newTitle]) { - newTitle = i18n.key[newTitle][language] - } + const newTitle = i18n(key) document.title = `${newTitle} - ${import.meta.env.VITE_APP_TITLE}`; setRealTitle(newTitle) }, [key, language]) diff --git a/directory/src/context/useLanguageContext.jsx b/directory/src/context/useLanguageContext.jsx index f75c04e..afe46b7 100644 --- a/directory/src/context/useLanguageContext.jsx +++ b/directory/src/context/useLanguageContext.jsx @@ -1,24 +1,31 @@ -import { createContext, useState, useEffect } from "react" -import i18n from '@/i18n' +import { createContext, useState, useEffect, useCallback } from "react" +import i18nValues from '@/i18n' export const LanguageContext = createContext() export function LanguageProvider(props) { const textDefaultLang = "en-US" - const [language, setLanguage] = useState(i18n.available.includes(navigator.language) ? navigator.language : "en-US") // language will be default to en-US if not available + const [language, setLanguage] = useState(i18nValues.available.includes(navigator.language) ? navigator.language : "en-US") // language will be default to en-US if not available const [alternateLang, setAlternateLang] = useState(null) // drawerAlternateLang will be default to zh-CN if language is en-* useEffect(() => { setAlternateLang(language.startsWith("en") ? "zh-CN" : language) }, [language]) + const i18n = useCallback((key, preferredLanguage = language) => { + if (i18nValues.key[key]) { + return i18nValues.key[key][preferredLanguage] + } + return key + }, [language]) + return ( {props.children} diff --git a/directory/src/db/index.js b/directory/src/db/index.js index fb22e62..915d0c7 100644 --- a/directory/src/db/index.js +++ b/directory/src/db/index.js @@ -4,6 +4,7 @@ const db = new Dexie('aklive2dDatabase'); db.version(2).stores({ image: '++key, blob', voice: '++key, blob', + config: '++key, value', }); export default db; \ No newline at end of file diff --git a/directory/src/i18n.json b/directory/src/i18n.json index 0add8bb..2511700 100644 --- a/directory/src/i18n.json +++ b/directory/src/i18n.json @@ -39,12 +39,12 @@ "zh-CN": "综合", "en-US": "All" }, - "elite2": { - "zh-CN": "干员晋升", + "operator": { + "zh-CN": "精英2", "en-US": "Elite 2" }, "skin": { - "zh-CN": "干员时装", + "zh-CN": "时装", "en-US": "Skin" }, "voice": { diff --git a/directory/src/routes/path/home.jsx b/directory/src/routes/path/home.jsx index 1c11982..0a221a8 100644 --- a/directory/src/routes/path/home.jsx +++ b/directory/src/routes/path/home.jsx @@ -5,7 +5,7 @@ import { useCallback } from 'react' import { - Link, + NavLink, } from "react-router-dom"; import './home.css' import { ConfigContext } from '@/context/useConfigContext'; @@ -24,7 +24,7 @@ export default function Home() { const { setTitle, setTabs, - currentTab, setCurrentTab, + currentTab, setAppbarExtraArea } = useContext(HeaderContext) const { config } = useContext(ConfigContext) @@ -39,19 +39,7 @@ export default function Home() { useEffect(() => { setTitle('dynamic_compile') - setTabs([ - { - key: 'all', - text: i18n.key.all - }, { - key: 'operator', - text: i18n.key.elite2 - }, { - key: 'skin', - text: i18n.key.skin - } - ]) - setCurrentTab('all') + setTabs(['all', 'operator', 'skin']) }, []) useEffect(() => { @@ -67,7 +55,7 @@ export default function Home() { ( toggleVoice()} /> @@ -122,9 +110,8 @@ export default function Home() {
{v.map(item => { return ( -
- + ) })}
{v[0].date}
diff --git a/directory/src/routes/path/operator.jsx b/directory/src/routes/path/operator.jsx index 94c6eb4..1c83808 100644 --- a/directory/src/routes/path/operator.jsx +++ b/directory/src/routes/path/operator.jsx @@ -3,18 +3,52 @@ import { useEffect, useContext } from 'react' +import { + useParams, +} from "react-router-dom"; import './operator.css' +import { ConfigContext } from '@/context/useConfigContext'; +import { LanguageContext } from '@/context/useLanguageContext'; import { HeaderContext } from '@/context/useHeaderContext'; import useUmami from '@parcellab/react-use-umami' export default function Operator(props) { const _trackEvt = useUmami('/operator/:key') - const { setTitle } = useContext(HeaderContext) + const { operators } = useContext(ConfigContext) + const { + language, + i18n + } = useContext(LanguageContext) + const { key } = useParams(); + const { + setTitle, + setTabs, + setAppbarExtraArea + } = useContext(HeaderContext) + const [config, setConfig] = useState(null) + const [spineData, setSpineData] = useState({}) useEffect(() => { - setTitle('chen') + setTabs([]) + setAppbarExtraArea([]) }, []) + useEffect(() => { + const config = operators.find((item) => item.link === key) + if (config) { + setConfig(config) + fetch(`/_assets/${config.filename.replace("#", "%23")}.json`).then(res => res.json()).then(data => { + setSpineData(data) + }) + } + }, [operators]) + + useEffect(() => { + if (config) { + setTitle(config.codename[language]) + } + }, [config, language]) + return (
diff --git a/directory/src/routes/root.css b/directory/src/routes/root.css index 2972b45..211fcea 100644 --- a/directory/src/routes/root.css +++ b/directory/src/routes/root.css @@ -191,7 +191,6 @@ border-top: 1px solid var(--border-color); padding: 1rem 0; display: flex; - align-content: center; justify-content: center; align-items: center; flex-wrap: nowrap; @@ -200,12 +199,22 @@ .footer .links { flex-direction: row; - gap: 1rem; + height: 2rem; } -.footer .links .separator { - height: 1rem; +.footer .links .item { + padding: 0 1rem; border-left: 2px solid var(--border-color); + height: inherit; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + flex-wrap: wrap; +} + +.footer .links .item:first-of-type { + border-left: none; } .footer .copyright { diff --git a/directory/src/routes/root.jsx b/directory/src/routes/root.jsx index a6a51f8..a92f314 100644 --- a/directory/src/routes/root.jsx +++ b/directory/src/routes/root.jsx @@ -8,6 +8,7 @@ import { Link, NavLink, useNavigate, + ScrollRestoration } from "react-router-dom"; import './root.css' import routes from '@/routes' @@ -25,7 +26,7 @@ export default function Root(props) { language, setLanguage, textDefaultLang, alternateLang, - i18n + i18n, i18nValues } = useContext(LanguageContext) const { title, @@ -41,21 +42,21 @@ export default function Root(props) { setHeaderTabs(tabs?.map((item) => { return (
{ - setCurrentTab(item.key) - item.onClick && item.onClick(e, item.key) + setCurrentTab(item) + item.onClick && item.onClick(e, item) }} > - {item.text[language]} + {i18n(item)}
) })) } - const toggleDrawer = () => { - setDrawerHidden(!drawerHidden) + const toggleDrawer = (value) => { + setDrawerHidden(value || !drawerHidden) } const renderDrawerDestinations = () => { @@ -67,13 +68,13 @@ export default function Root(props) { to={item.path} target="_blank" className="link" - onClick={() => toggleDrawer()} + onClick={() => toggleDrawer(false)} >
- {i18n.key[item.name][textDefaultLang]} + {i18n(item.name, textDefaultLang)}
- {i18n.key[item.name][alternateLang]} + {i18n(item.name, alternateLang)}
) @@ -83,13 +84,13 @@ export default function Root(props) { to={item.path} key={item.name} className="link" - onClick={() => toggleDrawer()} + onClick={() => toggleDrawer(false)} >
- {i18n.key[item.name][textDefaultLang]} + {i18n(item.name, textDefaultLang)}
- {i18n.key[item.name][alternateLang]} + {i18n(item.name, alternateLang)}
) @@ -105,6 +106,14 @@ export default function Root(props) { renderHeaderTabs(tabs) }, [tabs, currentTab, language]) + useEffect(() => { + if (tabs.length > 0) { + setCurrentTab(tabs[0]) + } else { + setCurrentTab(null) + } + }, [tabs]) + return ( <>
@@ -119,10 +128,10 @@ export default function Root(props) {
{appbarExtraArea} { + text={i18n(language)} + menu={i18nValues.available.map((item) => { return { - name: i18n.key[item][language], + name: i18n(item), value: item } })} @@ -161,23 +170,28 @@ export default function Root(props) {
- - {i18n.key.disclaimer_content[language]} - - - {i18n.key.privacy_policy[language]} - - Github - - - ak#halyul.dev - +
+ + {i18n('disclaimer_content')} + +
+
+ {i18n('privacy_policy')} +
+
+ GitHub +
+
+ + ak#halyul.dev + +
Spine Runtimes © 2013 - 2019 Esoteric Software LLC @@ -186,6 +200,12 @@ export default function Root(props) { Version: {import.meta.env.VITE_VERSION}
+ { + // default behavior + return location.pathname; + }} + /> ) } diff --git a/libs/directory.js b/libs/directory.js index 17126d8..b461f17 100644 --- a/libs/directory.js +++ b/libs/directory.js @@ -25,7 +25,9 @@ export default function () { }, {})) .sort((a, b) => Date.parse(b[0].date) - Date.parse(a[0].date)), } + const versionJson = __config.version writeSync(JSON.stringify(directoryJson, null), path.join(targetFolder, "directory.json")) + writeSync(JSON.stringify(versionJson, null), path.join(targetFolder, "version.json")) filesToCopy.forEach((key) => { copy(path.join(sourceFolder, key, 'assets.json'), path.join(targetFolder, `${__config.operators[key].filename}.json`)) }) diff --git a/libs/version.js b/libs/version.js index 5d4808e..90ea96c 100644 --- a/libs/version.js +++ b/libs/version.js @@ -9,5 +9,7 @@ export function increase(dir) { // release version will be lagged by 0.0.1 const version = read(dir) const [major, minor, patch] = version.split('.') - writeSync(`${major}.${minor}.${+patch + 1}`, path.join(dir, 'Version')) -} \ No newline at end of file + const newVersion = `${major}.${minor}.${+patch + 1}` + writeSync(newVersion, path.join(dir, 'Version')) + return newVersion +} diff --git a/vite.config.js b/vite.config.js index 5c97360..1ca21f0 100644 --- a/vite.config.js +++ b/vite.config.js @@ -63,7 +63,7 @@ class ViteRunner { this.#dev(viteConfig) break case 'build': - increase(configObj.versionDir) + this.#globalConfig.version.showcase = increase(configObj.versionDir) case 'build-all': this.#build(viteConfig) break @@ -133,7 +133,7 @@ class ViteRunner { get #directoryConfig() { if (process.env.npm_lifecycle_event === 'vite:directory:build') { - increase(path.join(__projetRoot, "directory")) + this.#globalConfig.version.directory = increase(path.join(__projetRoot, "directory")) } const directoryDir = path.resolve(__projetRoot, 'directory') writeSync((new EnvGenerator()).generate([ @@ -146,6 +146,9 @@ class ViteRunner { }, { key: "app_voice_url", value: this.#globalConfig.directory.voice + }, { + key: "showcase_version", + value: this.#globalConfig.version.showcase } ]), path.join(directoryDir, '.env')) this.#mode = process.argv[3]