feat(directory): proper cache handling
This commit is contained in:
@@ -1,4 +1,2 @@
|
|||||||
VITE_APP_TITLE=AKLive2D
|
VITE_APP_TITLE=AKLive2D
|
||||||
VITE_VERSION=0.5.9
|
|
||||||
VITE_APP_VOICE_URL=jp/CN_037.ogg
|
VITE_APP_VOICE_URL=jp/CN_037.ogg
|
||||||
VITE_SHOWCASE_VERSION=3.3.13
|
|
||||||
@@ -1 +1 @@
|
|||||||
0.5.9
|
0.5.12
|
||||||
@@ -1,29 +1,91 @@
|
|||||||
import { createContext, useState, useEffect } from "react"
|
import { createContext, useState, useEffect, useCallback } from "react"
|
||||||
import db from "@/db"
|
import db, { invalidateCache } from "@/db"
|
||||||
|
|
||||||
|
const versionCompare = (v1, v2) => {
|
||||||
|
const v1Arr = v1.split(".")
|
||||||
|
const v2Arr = v2.split(".")
|
||||||
|
for (let i = 0; i < v1Arr.length; i++) {
|
||||||
|
if (v1Arr[i] > v2Arr[i]) {
|
||||||
|
return 1
|
||||||
|
} else if (v1Arr[i] < v2Arr[i]) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
const invalidateRules = (local, version) => {
|
||||||
|
if (local === undefined) {
|
||||||
|
// no local version
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (version === undefined) {
|
||||||
|
// no remote version
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return versionCompare(local, version) < 0
|
||||||
|
}
|
||||||
|
|
||||||
export const ConfigContext = createContext()
|
export const ConfigContext = createContext()
|
||||||
|
|
||||||
export function ConfigProvider(props) {
|
export function ConfigProvider(props) {
|
||||||
const [config, setConfig] = useState([])
|
const [config, setConfig] = useState([])
|
||||||
const [operators, setOperators] = useState([])
|
const [operators, setOperators] = useState([])
|
||||||
|
const [version, setVersion] = useState({})
|
||||||
|
|
||||||
useEffect(() => {
|
const fetchConfig = (version) => {
|
||||||
fetch("/_assets/directory.json").then(res => res.json()).then(data => {
|
fetch("/_assets/directory.json").then(res => res.json()).then(data => {
|
||||||
setConfig(data)
|
setConfig(data)
|
||||||
db.config.put({ key: "config", value: data })
|
db.config.put({ key: "config", value: data })
|
||||||
let operatorsList = []
|
resolveOperators(data)
|
||||||
data.operators.forEach((item) => {
|
db.config.put({ key: "version", value: version })
|
||||||
operatorsList = [...operatorsList, ...item]
|
|
||||||
})
|
|
||||||
setOperators(operatorsList)
|
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolveOperators = useCallback((data) => {
|
||||||
|
let operatorsList = []
|
||||||
|
data.operators.forEach((item) => {
|
||||||
|
operatorsList = [...operatorsList, ...item]
|
||||||
|
})
|
||||||
|
setOperators(operatorsList)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
fetch("/_assets/version.json").then(res => res.json()).then(data => {
|
fetch("/_assets/version.json").then(res => res.json()).then(data => {
|
||||||
db.config.put({ key: "version", value: data })
|
db.config.get({ key: "version" }).then((local) => {
|
||||||
|
if (local === undefined || invalidateRules(local.value.directory, data.directory) || invalidateRules(local.value.showcase, data.showcase)) {
|
||||||
|
invalidateCache()
|
||||||
|
fetchConfig(data)
|
||||||
|
} else {
|
||||||
|
db.config.get({ key: "config" }).then((local) => {
|
||||||
|
if (local) {
|
||||||
|
setConfig(local.value)
|
||||||
|
resolveOperators(local.value)
|
||||||
|
} else {
|
||||||
|
fetchConfig(data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setVersion(data)
|
||||||
})
|
})
|
||||||
|
/*
|
||||||
|
local.directory | version.directory | action
|
||||||
|
--------------- | ----------------- | ------
|
||||||
|
1.0.0 | 1.0.0 | use cache
|
||||||
|
1.0.0 | 1.0.1 | invalidate cache
|
||||||
|
1.0.1 | 1.0.0 | impossible
|
||||||
|
|
||||||
|
local.showcase | version.showcase | action
|
||||||
|
-------------- | ---------------- | ------
|
||||||
|
1.0.0 | 1.0.0 | use cache
|
||||||
|
1.0.0 | 1.0.1 | invalidate cache
|
||||||
|
1.0.1 | 1.0.0 | use cache
|
||||||
|
*/
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigContext.Provider value={{ config, operators }}>
|
<ConfigContext.Provider value={{ config, operators, version }}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</ConfigContext.Provider>
|
</ConfigContext.Provider>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,4 +7,10 @@ db.version(2).stores({
|
|||||||
config: '++key, value',
|
config: '++key, value',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export function invalidateCache() {
|
||||||
|
db.image.clear();
|
||||||
|
db.voice.clear();
|
||||||
|
db.config.clear();
|
||||||
|
}
|
||||||
|
|
||||||
export default db;
|
export default db;
|
||||||
@@ -87,15 +87,15 @@ export default function Home() {
|
|||||||
const loadVoice = (link) => {
|
const loadVoice = (link) => {
|
||||||
if (!voiceOn) return
|
if (!voiceOn) return
|
||||||
db.voice.get({ key: link }).then((v) => {
|
db.voice.get({ key: link }).then((v) => {
|
||||||
if (v === undefined) {
|
if (v) {
|
||||||
|
playVoice(v.blob)
|
||||||
|
} else {
|
||||||
fetch(`/${link}/assets/voice/${import.meta.env.VITE_APP_VOICE_URL}`)
|
fetch(`/${link}/assets/voice/${import.meta.env.VITE_APP_VOICE_URL}`)
|
||||||
.then(res => res.blob())
|
.then(res => res.blob())
|
||||||
.then(blob => {
|
.then(blob => {
|
||||||
db.voice.put({ key: link, blob: blob })
|
db.voice.put({ key: link, blob: blob })
|
||||||
playVoice(blob)
|
playVoice(blob)
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
playVoice(v.blob)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -162,15 +162,15 @@ function ImageElement({ item, language }) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
db.image.get({ key: item.link }).then((v) => {
|
db.image.get({ key: item.link }).then((v) => {
|
||||||
if (v === undefined) {
|
if (v) {
|
||||||
|
setBlobUrl(URL.createObjectURL(v.blob))
|
||||||
|
} else {
|
||||||
fetch(`/${item.link}/assets/${item.fallback_name.replace("#", "%23")}_portrait.png`)
|
fetch(`/${item.link}/assets/${item.fallback_name.replace("#", "%23")}_portrait.png`)
|
||||||
.then(res => res.blob())
|
.then(res => res.blob())
|
||||||
.then(blob => {
|
.then(blob => {
|
||||||
db.image.put({ key: item.link, blob: blob })
|
db.image.put({ key: item.link, blob: blob })
|
||||||
setBlobUrl(URL.createObjectURL(blob))
|
setBlobUrl(URL.createObjectURL(blob))
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
setBlobUrl(URL.createObjectURL(v.blob))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [item.link])
|
}, [item.link])
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
} from "react-router-dom";
|
} from "react-router-dom";
|
||||||
import './root.css'
|
import './root.css'
|
||||||
import routes from '@/routes'
|
import routes from '@/routes'
|
||||||
|
import { ConfigContext } from '@/context/useConfigContext';
|
||||||
import { HeaderContext } from '@/context/useHeaderContext';
|
import { HeaderContext } from '@/context/useHeaderContext';
|
||||||
import { LanguageContext } from '@/context/useLanguageContext';
|
import { LanguageContext } from '@/context/useLanguageContext';
|
||||||
import Dropdown from '@/component/dropdown';
|
import Dropdown from '@/component/dropdown';
|
||||||
@@ -34,6 +35,7 @@ export default function Root(props) {
|
|||||||
currentTab, setCurrentTab,
|
currentTab, setCurrentTab,
|
||||||
appbarExtraArea
|
appbarExtraArea
|
||||||
} = useContext(HeaderContext)
|
} = useContext(HeaderContext)
|
||||||
|
const { version } = useContext(ConfigContext)
|
||||||
const [drawerDestinations, setDrawerDestinations] = useState(null)
|
const [drawerDestinations, setDrawerDestinations] = useState(null)
|
||||||
const currentYear = new Date().getFullYear()
|
const currentYear = new Date().getFullYear()
|
||||||
const [headerTabs, setHeaderTabs] = useState(null)
|
const [headerTabs, setHeaderTabs] = useState(null)
|
||||||
@@ -197,15 +199,11 @@ export default function Root(props) {
|
|||||||
<span>Spine Runtimes © 2013 - 2019 Esoteric Software LLC</span>
|
<span>Spine Runtimes © 2013 - 2019 Esoteric Software LLC</span>
|
||||||
<span>Assets © 2017 - {currentYear} Arknights/Hypergryph Co., Ltd</span>
|
<span>Assets © 2017 - {currentYear} Arknights/Hypergryph Co., Ltd</span>
|
||||||
<span>Source Code © 2021 - {currentYear} Halyul</span>
|
<span>Source Code © 2021 - {currentYear} Halyul</span>
|
||||||
<span>Version: {import.meta.env.VITE_VERSION}</span>
|
<span>Directory @ {version.directory}</span>
|
||||||
|
<span>Showcase @ {version.showcase}</span>
|
||||||
</section>
|
</section>
|
||||||
</footer>
|
</footer>
|
||||||
<ScrollRestoration
|
<ScrollRestoration />
|
||||||
getKey={(location, matches) => {
|
|
||||||
// default behavior
|
|
||||||
return location.pathname;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import getConfig from './libs/config.js'
|
|||||||
import { rmdir, writeSync } from './libs/file.js'
|
import { rmdir, writeSync } from './libs/file.js'
|
||||||
import { increase } from './libs/version.js'
|
import { increase } from './libs/version.js'
|
||||||
import EnvGenerator from './libs/env_generator.js'
|
import EnvGenerator from './libs/env_generator.js'
|
||||||
|
import directory from './libs/directory.js'
|
||||||
|
|
||||||
global.__projetRoot = path.dirname(fileURLToPath(import.meta.url))
|
global.__projetRoot = path.dirname(fileURLToPath(import.meta.url))
|
||||||
|
|
||||||
@@ -134,21 +135,17 @@ class ViteRunner {
|
|||||||
get #directoryConfig() {
|
get #directoryConfig() {
|
||||||
if (process.env.npm_lifecycle_event === 'vite:directory:build') {
|
if (process.env.npm_lifecycle_event === 'vite:directory:build') {
|
||||||
this.#globalConfig.version.directory = increase(path.join(__projetRoot, "directory"))
|
this.#globalConfig.version.directory = increase(path.join(__projetRoot, "directory"))
|
||||||
|
global.__config = this.#globalConfig
|
||||||
|
directory()
|
||||||
}
|
}
|
||||||
const directoryDir = path.resolve(__projetRoot, 'directory')
|
const directoryDir = path.resolve(__projetRoot, 'directory')
|
||||||
writeSync((new EnvGenerator()).generate([
|
writeSync((new EnvGenerator()).generate([
|
||||||
{
|
{
|
||||||
key: "app_title",
|
key: "app_title",
|
||||||
value: this.#globalConfig.directory.title
|
value: this.#globalConfig.directory.title
|
||||||
}, {
|
}, {
|
||||||
key: "version",
|
|
||||||
value: this.#globalConfig.version.directory
|
|
||||||
}, {
|
|
||||||
key: "app_voice_url",
|
key: "app_voice_url",
|
||||||
value: this.#globalConfig.directory.voice
|
value: this.#globalConfig.directory.voice
|
||||||
}, {
|
|
||||||
key: "showcase_version",
|
|
||||||
value: this.#globalConfig.version.showcase
|
|
||||||
}
|
}
|
||||||
]), path.join(directoryDir, '.env'))
|
]), path.join(directoryDir, '.env'))
|
||||||
this.#mode = process.argv[3]
|
this.#mode = process.argv[3]
|
||||||
|
|||||||
Reference in New Issue
Block a user