release: bump version to 0.27.7
This commit is contained in:
@@ -21,8 +21,11 @@ let refreshPromise = null;
|
||||
let hlsPlayer = null;
|
||||
let hlsRecoveryAttempts = 0;
|
||||
let metaAutoCollapseTimer = null;
|
||||
const failedSourceIds = new Set();
|
||||
let probeTimer = null;
|
||||
|
||||
const META_AUTO_COLLAPSE_DELAY = 2500;
|
||||
const PROBE_INTERVAL_MS = 2 * 60 * 1000;
|
||||
|
||||
const HLS_MAX_RECOVERY_ATTEMPTS = 3;
|
||||
const HLS_RETRY_CONFIG = {
|
||||
@@ -392,7 +395,7 @@ function attachVideoSource(video, source) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!showEmbeddedFallback(source)) {
|
||||
if (!showEmbeddedFallback(source) && !tryFallbackSource()) {
|
||||
setPanelMessage(TV_STATUS_MESSAGE.videoError);
|
||||
}
|
||||
});
|
||||
@@ -425,6 +428,59 @@ function findSourceById(sourceId) {
|
||||
return tvPayload?.sources?.find((source) => source.id === sourceId) || null;
|
||||
}
|
||||
|
||||
function markSourceFailed(sourceId) {
|
||||
if (!sourceId) return;
|
||||
failedSourceIds.add(sourceId);
|
||||
renderSourceOptions();
|
||||
if (!probeTimer) {
|
||||
probeTimer = setInterval(probeFailedSources, PROBE_INTERVAL_MS);
|
||||
}
|
||||
}
|
||||
|
||||
function clearSourceFailed(sourceId) {
|
||||
if (!failedSourceIds.has(sourceId)) return;
|
||||
failedSourceIds.delete(sourceId);
|
||||
renderSourceOptions();
|
||||
if (failedSourceIds.size === 0 && probeTimer) {
|
||||
clearInterval(probeTimer);
|
||||
probeTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function probeFailedSources() {
|
||||
if (failedSourceIds.size === 0) {
|
||||
clearInterval(probeTimer);
|
||||
probeTimer = null;
|
||||
return;
|
||||
}
|
||||
for (const sourceId of [...failedSourceIds]) {
|
||||
const source = findSourceById(sourceId);
|
||||
if (!source) { failedSourceIds.delete(sourceId); continue; }
|
||||
const probeUrl = source.stream_url || source.embed_url;
|
||||
if (!probeUrl) continue;
|
||||
try {
|
||||
const resp = await fetch(probeUrl, {
|
||||
method: "HEAD",
|
||||
signal: AbortSignal.timeout(5000),
|
||||
});
|
||||
if (resp.ok) clearSourceFailed(sourceId);
|
||||
} catch {
|
||||
// 仍然失效,保持标记
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function tryFallbackSource() {
|
||||
const fallback = tvPayload?.fallback_source;
|
||||
if (!fallback || fallback.id === currentSourceId) return false;
|
||||
markSourceFailed(currentSourceId);
|
||||
currentSourceId = fallback.id;
|
||||
const { select } = getElements();
|
||||
if (select) select.value = currentSourceId;
|
||||
renderSource(fallback);
|
||||
return true;
|
||||
}
|
||||
|
||||
function getCurrentSource() {
|
||||
return findSourceById(currentSourceId);
|
||||
}
|
||||
@@ -487,10 +543,11 @@ function renderSourceOptions() {
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
sources.forEach((source) => {
|
||||
const marker = source.id === tvPayload?.default_source_id ? " · 默认" : "";
|
||||
const defaultMark = source.id === tvPayload?.default_source_id ? " · 默认" : "";
|
||||
const failMark = failedSourceIds.has(source.id) ? " ⚠" : "";
|
||||
const option = document.createElement("option");
|
||||
option.value = source.id;
|
||||
option.textContent = `${source.name}${marker}`;
|
||||
option.textContent = `${source.name}${defaultMark}${failMark}`;
|
||||
fragment.appendChild(option);
|
||||
});
|
||||
|
||||
@@ -660,17 +717,19 @@ export function initTVPanel() {
|
||||
|
||||
iframe?.addEventListener("load", () => {
|
||||
if (iframe.hidden) return;
|
||||
clearSourceFailed(currentSourceId);
|
||||
setPanelMessage(TV_STATUS_MESSAGE.iframeReady);
|
||||
});
|
||||
|
||||
video?.addEventListener("loadedmetadata", () => {
|
||||
if (video.hidden) return;
|
||||
clearSourceFailed(currentSourceId);
|
||||
setPanelMessage(TV_STATUS_MESSAGE.videoReady);
|
||||
});
|
||||
|
||||
video?.addEventListener("error", () => {
|
||||
const currentSource = getCurrentSource();
|
||||
if (!showEmbeddedFallback(currentSource)) {
|
||||
if (!showEmbeddedFallback(currentSource) && !tryFallbackSource()) {
|
||||
setPanelMessage(TV_STATUS_MESSAGE.videoError);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user