feat: add error handling to player core functions

This commit is contained in:
2026-06-16 14:00:38 +02:00
committed by Milas Holsting
parent 3a1a2129d9
commit 2a8294c405
9 changed files with 45 additions and 22 deletions

View File

@@ -38,8 +38,9 @@ const mark = (name: string): void => {
const measure = (name: string, startMark: string): void => {
try {
performance.measure(`mal.hls.${name}`, `mal.hls.${startMark}`);
} catch {
} catch (error) {
// Missing marks can happen if HLS.js emits a later event after cleanup.
console.debug("failed to measure performance:", error);
}
};

View File

@@ -172,7 +172,8 @@ const initPlayer = (): void => {
sessionStorage.removeItem("mal:resume-after-mode-switch");
const parsed = Number(raw);
return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
} catch {
} catch (error) {
console.error("failed to parse resume state:", error);
return null;
}
})();
@@ -200,7 +201,9 @@ const initPlayer = (): void => {
// autoplay if not already playing (inline script may have already called play())
// but don't autoplay if we've reached the end
if (!isAtEnd && (state.playback.shouldAutoPlay || state.elements.video.paused)) {
state.elements.video.play().catch(() => undefined);
state.elements.video.play().catch((error) => {
console.debug("failed to autoplay video:", error);
});
}
updateTimeline(state.elements.video.currentTime);
@@ -279,7 +282,8 @@ const initPlayer = (): void => {
try {
(e.currentTarget as HTMLElement).setPointerCapture((e as PointerEvent).pointerId);
} catch (e) {
console.warn("Failed to capture pointer:", e);
console.error("failed to capture pointer:", e);
throw e;
}
scrubToPointer(e.clientX, true);
},

View File

@@ -75,8 +75,8 @@ export const switchMode = (mode: string): void => {
const next = new URL(window.location.href);
next.searchParams.set("mode", expectedMode);
window.location.href = next.toString();
} catch {
// no-op
} catch (error) {
console.error("failed to save resume state or switch mode:", error);
}
}, 800);
}

View File

@@ -71,7 +71,8 @@ export const saveProgress = async (
seconds: savedTime,
};
} catch (e) {
console.warn("Progress save failed:", e);
console.error("progress save failed:", e);
throw e;
}
})();
@@ -113,7 +114,9 @@ export const markEpisodeTransition = (episodeNumber: number): void => {
headers: { "Content-Type": "application/json" },
keepalive: true,
body: payload,
}).catch(() => undefined);
}).catch((error) => {
console.debug("failed to save progress:", error);
});
}
};

View File

@@ -211,7 +211,12 @@ export const setupSegmentEditor = (): void => {
});
if (!res.ok) {
let message = res.status === 401 ? "Login required." : "Failed to save segment.";
const payload = (await res.json().catch(() => null)) as { error?: string } | null;
let payload: { error?: string } | null = null;
try {
payload = await res.json();
} catch (error) {
console.error("failed to parse response json:", error);
}
if (payload?.error) message = payload.error;
setError(message);
return;
@@ -235,8 +240,10 @@ export const setupSegmentEditor = (): void => {
window.showToast?.({ message: "Segment saved." });
close();
} catch {
setError("Failed to save segment.");
} catch (error) {
setError("Failed To Save Segment.");
console.error("failed to save segment:", error);
throw error;
} finally {
saveBtn.disabled = false;
saveBtn.classList.remove("opacity-70");

View File

@@ -204,7 +204,8 @@ export const initState = (c: HTMLElement): boolean => {
const safeJsonUnknown = (raw: string | undefined): unknown => {
try {
return JSON.parse(raw ?? "");
} catch {
} catch (error) {
console.error("failed to parse json:", error);
return null;
}
};
@@ -237,7 +238,8 @@ export const initState = (c: HTMLElement): boolean => {
const modeParam = u.searchParams.get("mode");
if (modeParam === "sub" || modeParam === "dub") return modeParam;
return null;
} catch {
} catch (error) {
console.error("failed to parse mode url:", error);
return null;
}
};

View File

@@ -3,7 +3,8 @@ export type StorageLike = Pick<Storage, "getItem" | "setItem" | "removeItem">;
const getLocalStorage = (): StorageLike | null => {
try {
return window.localStorage;
} catch {
} catch (error) {
console.error("failed to access localstorage:", error);
return null;
}
};
@@ -14,7 +15,8 @@ export const safeLocalStorage = {
if (!storage) return null;
try {
return storage.getItem(key);
} catch {
} catch (error) {
console.error(`failed to get localstorage item '${key}':`, error);
return null;
}
},
@@ -23,8 +25,8 @@ export const safeLocalStorage = {
if (!storage) return;
try {
storage.setItem(key, value);
} catch {
// ignore
} catch (error) {
console.error(`failed to set localstorage item '${key}':`, error);
}
},
removeItem(key: string): void {
@@ -32,8 +34,8 @@ export const safeLocalStorage = {
if (!storage) return;
try {
storage.removeItem(key);
} catch {
// ignore
} catch (error) {
console.error(`failed to remove localstorage item '${key}':`, error);
}
},
};

View File

@@ -32,7 +32,8 @@ const loadSubtitle = async (url: string): Promise<SubtitleCue[]> => {
const res = await fetch(url);
if (!res.ok) return [];
return parseVtt(await res.text());
} catch {
} catch (error) {
console.error("failed to load subtitle:", error);
return [];
}
};

View File

@@ -26,7 +26,8 @@ const shouldUseHLS = (type: string | undefined, url: string): boolean => {
const parsed = new URL(url, window.location.href);
if (parsed.searchParams.get("hls") === "1") return true;
return parsed.pathname.toLowerCase().endsWith(".m3u8");
} catch {
} catch (error) {
console.error("Failed to parse video URL:", error);
return url.toLowerCase().includes(".m3u8");
}
};
@@ -65,6 +66,8 @@ export const loadVideoSource = (url: string, type?: string): void => {
}
if (wasPlaying) {
state.elements.video.play().catch(() => undefined);
state.elements.video.play().catch((error) => {
console.debug("failed to play video:", error);
});
}
};