feat(directory): added ability to show if any new operator is available
This commit is contained in:
@@ -154,6 +154,10 @@
|
|||||||
"search_by_name": {
|
"search_by_name": {
|
||||||
"zh-CN": "名字搜索",
|
"zh-CN": "名字搜索",
|
||||||
"en-US": "Search by Name"
|
"en-US": "Search by Name"
|
||||||
|
},
|
||||||
|
"new_op_wait_to_update": {
|
||||||
|
"zh-CN": "个新干员等待更新",
|
||||||
|
"en-US": "New Operator(s) Wait to Update"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,7 @@ import header from '@/scss/root/header.module.scss'
|
|||||||
import footer from '@/scss/root/footer.module.scss'
|
import footer from '@/scss/root/footer.module.scss'
|
||||||
import drawer from '@/scss/root/drawer.module.scss'
|
import drawer from '@/scss/root/drawer.module.scss'
|
||||||
import routes from '@/routes'
|
import routes from '@/routes'
|
||||||
|
import { useConfig } from '@/state/config';
|
||||||
import { useHeader } from '@/state/header';
|
import { useHeader } from '@/state/header';
|
||||||
import { useAppbar } from '@/state/appbar';
|
import { useAppbar } from '@/state/appbar';
|
||||||
import {
|
import {
|
||||||
@@ -43,6 +44,7 @@ export default function Root() {
|
|||||||
const {
|
const {
|
||||||
extraArea,
|
extraArea,
|
||||||
} = useAppbar()
|
} = useAppbar()
|
||||||
|
const { fetchOfficalUpdate } = useConfig()
|
||||||
|
|
||||||
const headerTabs = useMemo(() => {
|
const headerTabs = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
@@ -69,6 +71,10 @@ export default function Root() {
|
|||||||
}
|
}
|
||||||
}, [setCurrentTab, tabs])
|
}, [setCurrentTab, tabs])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchOfficalUpdate()
|
||||||
|
}, [fetchOfficalUpdate])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header className={header.header}>
|
<header className={header.header}>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
} from "react-router-dom";
|
} from "react-router-dom";
|
||||||
import classes from '@/scss/home/Home.module.scss'
|
import classes from '@/scss/home/Home.module.scss'
|
||||||
import { useConfig } from '@/state/config';
|
import { useConfig } from '@/state/config';
|
||||||
|
import { useI18n } from '@/state/language';
|
||||||
import {
|
import {
|
||||||
useLanguage
|
useLanguage
|
||||||
} from '@/state/language'
|
} from '@/state/language'
|
||||||
@@ -37,7 +38,8 @@ export default function Home() {
|
|||||||
setHeaderIcon,
|
setHeaderIcon,
|
||||||
setFastNavigation
|
setFastNavigation
|
||||||
} = useHeader()
|
} = useHeader()
|
||||||
const { config, operators } = useConfig()
|
const { config, operators, officalUpdate } = useConfig()
|
||||||
|
const { i18n } = useI18n()
|
||||||
const [content, setContent] = useState([])
|
const [content, setContent] = useState([])
|
||||||
const [voiceOn] = useAtom(voiceOnAtom)
|
const [voiceOn] = useAtom(voiceOnAtom)
|
||||||
const [voiceSrc, setVoiceSrc] = useState(null)
|
const [voiceSrc, setVoiceSrc] = useState(null)
|
||||||
@@ -163,6 +165,29 @@ export default function Home() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
|
{
|
||||||
|
officalUpdate.length > operators.length && (
|
||||||
|
<section>
|
||||||
|
<section className={classes['offical-update']}>
|
||||||
|
<section className={classes.info}>
|
||||||
|
<section className={classes.content}>
|
||||||
|
<section className={classes.text}>{officalUpdate.length - operators.length} {i18n("new_op_wait_to_update")}</section>
|
||||||
|
{officalUpdate[officalUpdate.latest].map((entry, index) => {
|
||||||
|
return (
|
||||||
|
<section key={index} className={classes.list}>
|
||||||
|
{`${i18n(entry.type)}: ${entry.codename[language]}`}
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<section className={classes.date}>{officalUpdate.latest}</section>
|
||||||
|
</section>
|
||||||
|
<Border />
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
content.map((v) => {
|
content.map((v) => {
|
||||||
const length = v.filter((v) => isShown(v.type)).length
|
const length = v.filter((v) => isShown(v.type)).length
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
.date {
|
||||||
|
margin: 1.5rem;
|
||||||
|
font-family: "Bender", "Noto Sans SC", "Noto Sans JP", "Noto Sans KR",
|
||||||
|
"Noto Sans", sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: right;
|
||||||
|
color: var(--date-color);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
letter-spacing: 0.1rem;
|
||||||
|
flex: auto;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
.group {
|
.group {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -5,18 +18,6 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
.date {
|
|
||||||
margin: 1.5rem;
|
|
||||||
font-family: "Bender", 'Noto Sans SC', 'Noto Sans JP', 'Noto Sans KR', 'Noto Sans', sans-serif;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: right;
|
|
||||||
color: var(--date-color);
|
|
||||||
font-size: 1.5rem;
|
|
||||||
letter-spacing: 0.1rem;
|
|
||||||
flex: auto;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -117,7 +118,8 @@
|
|||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
.text {
|
.text {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-family: "Geometos", 'Noto Sans SC', 'Noto Sans JP', 'Noto Sans KR', 'Noto Sans', sans-serif;
|
font-family: "Geometos", "Noto Sans SC", "Noto Sans JP",
|
||||||
|
"Noto Sans KR", "Noto Sans", sans-serif;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,26 @@
|
|||||||
@use '@/scss/_page_base.scss';
|
@use '@/scss/_page_base.scss';
|
||||||
|
|
||||||
|
.offical-update {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
.info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding-left: 1rem;
|
||||||
|
word-break: break-word;
|
||||||
|
margin-top: 1.25rem;
|
||||||
|
.content {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
.text {
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list {
|
||||||
|
display: list-item;
|
||||||
|
margin-left: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
import CONFIG from '@/_directory.json';
|
import CONFIG from '@/_directory.json';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { atom, useAtom } from 'jotai';
|
||||||
|
|
||||||
|
const officalUpdateAtom = atom({});
|
||||||
|
|
||||||
let operators = []
|
let operators = []
|
||||||
CONFIG.operators.forEach((item) => {
|
CONFIG.operators.forEach((item) => {
|
||||||
@@ -9,6 +13,18 @@ const OPERATORS = operators;
|
|||||||
export function useConfig() {
|
export function useConfig() {
|
||||||
const config = CONFIG;
|
const config = CONFIG;
|
||||||
const operators = OPERATORS;
|
const operators = OPERATORS;
|
||||||
|
const [officalUpdate, setOfficalUpdate] = useAtom(officalUpdateAtom);
|
||||||
|
|
||||||
return { config, operators };
|
const fetchOfficalUpdate = useCallback(async () => {
|
||||||
|
const res = await fetch('https://raw.githubusercontent.com/Halyul/aklive2d/main/offical_update.json')
|
||||||
|
const data = await res.json().catch((e) => {
|
||||||
|
console.error(e)
|
||||||
|
return {
|
||||||
|
length: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setOfficalUpdate(data);
|
||||||
|
}, [setOfficalUpdate])
|
||||||
|
|
||||||
|
return { config, operators, officalUpdate, fetchOfficalUpdate };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user