Files
KVideo/lib/utils/grouped-sources-cache.ts
kuekhaoyang 0e87c94a64 feat: 修复超长 URL (414) 问题,添加分辨率检测,修复高级模式 bug,提升兼容性
- 将 groupedSources 存储在 sessionStorage 中而非 URL 参数里,以防止因 URL 过长导致的 CDN 414 错误 (#112)
- 自动将旧版 groupedSources URL 迁移至短 gs 键
- 从视频元素中检测并显示实际视频分辨率(例如 1920x1080),不再依赖来源提供的标签
- 修复 PlayerNavbar 设置链接在高级模式下总是跳转到 /settings 而非 /premium/settings 的问题 (#106)
- 修复 WatchHistorySidebar 未向 HistoryList 传递 isPremium,导致历史记录项 URL 丢失 premium=1 参数的问题 (#106)
- 为 HLS 播放添加多级浏览器回退机制 (HLS.js → 原生 → 代理 → 错误并提供浏览器建议) (#104)
- 在 IPTV 播放器中添加 HEVC/H.265 级别过滤,防止 CCTV 等频道出现仅有音频播放的问题 (#81)
- 更新依赖并升级版本至 4.5.0
2026-03-12 22:58:30 +08:00

86 lines
2.3 KiB
TypeScript

/**
* Grouped Sources Cache
* Stores groupedSources data in sessionStorage to avoid extremely long URLs
* that cause HTTP 414 errors on CDNs (e.g., Cloudflare, AWS CloudFront).
*
* Instead of passing the full JSON array in the URL parameter,
* we store it in sessionStorage and pass a short key in the URL.
*/
const CACHE_PREFIX = 'gs:';
const MAX_CACHE_SIZE = 100;
/**
* Store grouped sources data and return a short cache key.
*/
export function storeGroupedSources(data: any[]): string {
if (typeof window === 'undefined') return '';
const key = generateKey();
try {
// Cleanup old entries if too many
cleanupOldEntries();
sessionStorage.setItem(
`${CACHE_PREFIX}${key}`,
JSON.stringify({ data, ts: Date.now() })
);
} catch {
// sessionStorage full or unavailable — fall back gracefully
}
return key;
}
/**
* Retrieve grouped sources data by cache key.
*/
export function retrieveGroupedSources(key: string): any[] | null {
if (typeof window === 'undefined' || !key) return null;
try {
const raw = sessionStorage.getItem(`${CACHE_PREFIX}${key}`);
if (!raw) return null;
const parsed = JSON.parse(raw);
return parsed?.data || null;
} catch {
return null;
}
}
/**
* Generate a short random key (8 chars, base36).
*/
function generateKey(): string {
return Math.random().toString(36).slice(2, 10);
}
/**
* Remove oldest entries when cache exceeds max size.
*/
function cleanupOldEntries(): void {
try {
const entries: { key: string; ts: number }[] = [];
for (let i = 0; i < sessionStorage.length; i++) {
const key = sessionStorage.key(i);
if (key?.startsWith(CACHE_PREFIX)) {
try {
const raw = sessionStorage.getItem(key);
const parsed = raw ? JSON.parse(raw) : null;
entries.push({ key, ts: parsed?.ts || 0 });
} catch {
entries.push({ key, ts: 0 });
}
}
}
if (entries.length >= MAX_CACHE_SIZE) {
// Sort by timestamp ascending and remove oldest half
entries.sort((a, b) => a.ts - b.ts);
const toRemove = entries.slice(0, Math.floor(entries.length / 2));
for (const entry of toRemove) {
sessionStorage.removeItem(entry.key);
}
}
} catch {
// Ignore cleanup errors
}
}