Merge origin/master into hermes/hermes-4fd30995

This commit is contained in:
2026-05-15 03:41:50 +08:00
348 changed files with 31117 additions and 4591 deletions

View File

@@ -0,0 +1,93 @@
const PUZZLE_HISTORY_ASSET_FALLBACK_NAME = '历史拼图素材';
function safeDecodePathSegment(value: string) {
try {
return decodeURIComponent(value);
} catch {
return value;
}
}
function parsePuzzleHistoryTimestamp(value: string) {
const trimmed = value.trim();
if (!trimmed) {
return null;
}
const directDate = new Date(trimmed);
if (!Number.isNaN(directDate.getTime())) {
return directDate;
}
const numericMatch = /^(-?\d+)(?:\.(\d{1,9}))?Z?$/u.exec(trimmed);
if (!numericMatch) {
return null;
}
const wholeSeconds = Number.parseInt(numericMatch[1] ?? '', 10);
if (!Number.isFinite(wholeSeconds)) {
return null;
}
const fractionalMillis = Number.parseInt(
(numericMatch[2] ?? '').padEnd(3, '0').slice(0, 3) || '0',
10,
);
const normalizedMillis = Number.isFinite(fractionalMillis)
? fractionalMillis
: 0;
const useMilliseconds =
Math.abs(wholeSeconds) >= 100_000_000_000 ||
(numericMatch[1] ?? '').length > 10;
const timestampMs = useMilliseconds
? wholeSeconds + (wholeSeconds < 0 ? -normalizedMillis : normalizedMillis)
: wholeSeconds * 1000 +
(wholeSeconds < 0 ? -normalizedMillis : normalizedMillis);
return new Date(timestampMs);
}
export function getPuzzleHistoryAssetDisplayName(
imageSrc: string | null | undefined,
) {
const trimmed = imageSrc?.trim() ?? '';
if (!trimmed) {
return PUZZLE_HISTORY_ASSET_FALLBACK_NAME;
}
const pathOnly = trimmed.split(/[?#]/u)[0]?.trim() ?? '';
if (!pathOnly) {
return PUZZLE_HISTORY_ASSET_FALLBACK_NAME;
}
const fileName = pathOnly.replace(/^\/+/u, '').split('/').filter(Boolean).pop();
const displayName = safeDecodePathSegment(fileName ?? '').trim();
return displayName || PUZZLE_HISTORY_ASSET_FALLBACK_NAME;
}
export function formatPuzzleHistoryAssetCreatedAt(value: string) {
const parsedDate = parsePuzzleHistoryTimestamp(value);
if (!parsedDate) {
return '未知时间';
}
return new Intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false,
}).format(parsedDate);
}
export function getPuzzleHistoryAssetReferenceLabel(
imageSrc: string | null | undefined,
) {
const displayName = getPuzzleHistoryAssetDisplayName(imageSrc);
if (displayName === PUZZLE_HISTORY_ASSET_FALLBACK_NAME) {
return '历史素材';
}
return `历史素材 · ${displayName}`;
}