feat: add error handling to player core functions
This commit is contained in:
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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 [];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user