Files
O96u ac65c1eb9d refactor: 重构设置、API、图库与存储页面前端结构。
将操作日志并入设置侧栏,补齐检查更新提示与版本接口刷新;拆分各模块组件并修复图库搜索分页变量。
2026-09-01 17:15:02 +08:00

78 lines
2.2 KiB
TypeScript

const GITHUB_REPO = 'O96u/PicHost'
const RELEASES_LATEST_URL = `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`
const CACHE_TTL_MS = 60 * 60 * 1000
export interface LatestReleaseInfo {
latestVersion: string
releaseUrl: string
}
let cachedRelease: { fetchedAt: number, value: LatestReleaseInfo | null } | null = null
export function normalizeVersionTag(tag: string): string {
return tag.trim().replace(/^v/i, '')
}
export function parseVersionParts(version: string): number[] {
return normalizeVersionTag(version)
.split('.')
.map(part => Number.parseInt(part, 10))
.map(part => (Number.isFinite(part) ? part : 0))
}
export function isVersionNewer(candidate: string, current: string): boolean {
const a = parseVersionParts(candidate)
const b = parseVersionParts(current)
const length = Math.max(a.length, b.length)
for (let i = 0; i < length; i++) {
const diff = (a[i] ?? 0) - (b[i] ?? 0)
if (diff !== 0) return diff > 0
}
return false
}
export async function fetchLatestGitHubRelease(force = false): Promise<LatestReleaseInfo | null> {
const now = Date.now()
if (!force && cachedRelease && now - cachedRelease.fetchedAt < CACHE_TTL_MS) {
return cachedRelease.value
}
try {
const response = await fetch(RELEASES_LATEST_URL, {
headers: {
'Accept': 'application/vnd.github+json',
'User-Agent': 'PicHost'
},
signal: AbortSignal.timeout(8000)
})
if (!response.ok) {
cachedRelease = { fetchedAt: now, value: null }
return null
}
const data = await response.json() as {
tag_name?: string
html_url?: string
}
const tag = typeof data.tag_name === 'string' ? data.tag_name : ''
const releaseUrl = typeof data.html_url === 'string' ? data.html_url : ''
if (!tag) {
cachedRelease = { fetchedAt: now, value: null }
return null
}
const value: LatestReleaseInfo = {
latestVersion: normalizeVersionTag(tag),
releaseUrl: releaseUrl || `https://github.com/${GITHUB_REPO}/releases/latest`
}
cachedRelease = { fetchedAt: now, value }
return value
} catch {
cachedRelease = { fetchedAt: now, value: null }
return null
}
}