mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-03-11 05:18:32 +00:00
Ensure video thumbnails fall back to placeholder
This commit is contained in:
88
js/app.js
88
js/app.js
@@ -2422,6 +2422,12 @@ class bitvidApp {
|
||||
this.videoList.innerHTML = "";
|
||||
this.videoList.appendChild(fragment);
|
||||
|
||||
// Ensure every thumbnail can recover with a fallback image if the primary
|
||||
// source fails to load or returns a zero-sized response (some CDNs error
|
||||
// with HTTP 200 + empty body). We set up the listeners before kicking off
|
||||
// any lazy-loading observers so cached failures are covered as well.
|
||||
this.bindThumbnailFallbacks(this.videoList);
|
||||
|
||||
// Lazy-load images
|
||||
const lazyEls = this.videoList.querySelectorAll("[data-lazy]");
|
||||
lazyEls.forEach((el) => this.mediaLoader.observe(el));
|
||||
@@ -2504,6 +2510,88 @@ class bitvidApp {
|
||||
});
|
||||
}
|
||||
|
||||
bindThumbnailFallbacks(container) {
|
||||
if (!container || typeof container.querySelectorAll !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
const thumbnails = container.querySelectorAll("[data-video-thumbnail]");
|
||||
thumbnails.forEach((img) => {
|
||||
if (!img) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ensureFallbackSource = () => {
|
||||
let fallbackSrc = "";
|
||||
if (typeof img.dataset.fallbackSrc === "string") {
|
||||
fallbackSrc = img.dataset.fallbackSrc.trim();
|
||||
}
|
||||
|
||||
if (!fallbackSrc) {
|
||||
const attr = img.getAttribute("data-fallback-src") || "";
|
||||
fallbackSrc = attr.trim();
|
||||
}
|
||||
|
||||
if (!fallbackSrc && img.tagName === "IMG") {
|
||||
fallbackSrc = FALLBACK_THUMBNAIL_SRC;
|
||||
}
|
||||
|
||||
if (fallbackSrc) {
|
||||
if (img.dataset.fallbackSrc !== fallbackSrc) {
|
||||
img.dataset.fallbackSrc = fallbackSrc;
|
||||
}
|
||||
if (!img.getAttribute("data-fallback-src")) {
|
||||
img.setAttribute("data-fallback-src", fallbackSrc);
|
||||
}
|
||||
}
|
||||
|
||||
return fallbackSrc;
|
||||
};
|
||||
|
||||
const applyFallback = () => {
|
||||
const fallbackSrc = ensureFallbackSource() || FALLBACK_THUMBNAIL_SRC;
|
||||
if (!fallbackSrc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (img.src !== fallbackSrc) {
|
||||
img.src = fallbackSrc;
|
||||
}
|
||||
|
||||
img.dataset.thumbnailFailed = "true";
|
||||
};
|
||||
|
||||
const handleLoad = () => {
|
||||
if (
|
||||
(img.naturalWidth === 0 && img.naturalHeight === 0) ||
|
||||
!img.currentSrc
|
||||
) {
|
||||
applyFallback();
|
||||
} else {
|
||||
delete img.dataset.thumbnailFailed;
|
||||
}
|
||||
};
|
||||
|
||||
ensureFallbackSource();
|
||||
|
||||
if (img.dataset.thumbnailFallbackBound === "true") {
|
||||
if (img.complete) {
|
||||
handleLoad();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
img.addEventListener("error", applyFallback);
|
||||
img.addEventListener("load", handleLoad);
|
||||
|
||||
img.dataset.thumbnailFallbackBound = "true";
|
||||
|
||||
if (img.complete) {
|
||||
handleLoad();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the modal to reflect current torrent stats.
|
||||
* We remove the unused torrent.status references,
|
||||
|
||||
Reference in New Issue
Block a user