Resolve external embed previews and keep their real MIME types
This commit is contained in:
+34
-20
@@ -392,24 +392,38 @@
|
||||
return el(className ?? "figcaption", "vk-media-banner", parts.join(" · "));
|
||||
}
|
||||
|
||||
/** Grid thumbnail source: cached preview, then the local file, then the original link. */
|
||||
/**
|
||||
* Grid thumbnail source: cached preview, then the local file.
|
||||
* Attachment URLs are direct files; embed URLs are pages, never rendered as media.
|
||||
*/
|
||||
function gridSource(item) {
|
||||
return item.thumbUrl || item.localUrl || item.url;
|
||||
if (item.thumbUrl) return item.thumbUrl;
|
||||
if (item.localUrl) return item.localUrl;
|
||||
if (item.source !== "embed") return item.url;
|
||||
return null;
|
||||
}
|
||||
|
||||
function placeholder(media, item) {
|
||||
media.replaceChildren(el("span", "vk-media-card-kind", item.kind.toUpperCase()));
|
||||
}
|
||||
|
||||
function playIcon(item) {
|
||||
const play = el("span", "vk-media-play", "▶");
|
||||
play.title = "Play";
|
||||
play.addEventListener("click", event => {
|
||||
event.stopPropagation();
|
||||
openViewer(item, true);
|
||||
});
|
||||
return play;
|
||||
}
|
||||
|
||||
function renderCard(item) {
|
||||
const figure = el("figure", "vk-media-figure");
|
||||
const media = el("div", "vk-media-media");
|
||||
const source = gridSource(item);
|
||||
const visual = item.kind === "image" || item.kind === "gif" || item.kind === "video";
|
||||
const playable = /\.(mp4|webm|m4v)(\?|$)/i.test(item.url ?? "");
|
||||
|
||||
if (visual && /^(https?:|\/)/.test(source) && item.kind !== "video") {
|
||||
const img = document.createElement("img");
|
||||
img.loading = "lazy";
|
||||
img.src = source;
|
||||
img.alt = item.kind;
|
||||
media.append(img);
|
||||
} else if (item.kind === "video" && /^(https?:|\/)/.test(source)) {
|
||||
if (item.kind === "video" && source && item.source !== "embed" && playable) {
|
||||
// Discord has no server-side video thumbnails; the browser shows the first frame.
|
||||
const video = document.createElement("video");
|
||||
video.preload = "metadata";
|
||||
@@ -423,20 +437,20 @@
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
video.addEventListener("error", () => placeholder(media, item), { once: true });
|
||||
media.append(video);
|
||||
} else if (source && /^(https?:|\/)/.test(source)) {
|
||||
const img = document.createElement("img");
|
||||
img.loading = "lazy";
|
||||
img.src = source;
|
||||
img.alt = item.kind;
|
||||
img.addEventListener("error", () => placeholder(media, item), { once: true });
|
||||
media.append(img);
|
||||
} else {
|
||||
media.append(el("span", "vk-media-card-kind", item.kind.toUpperCase()));
|
||||
placeholder(media, item);
|
||||
}
|
||||
|
||||
if (item.kind === "video") {
|
||||
const play = el("span", "vk-media-play", "▶");
|
||||
play.title = "Play";
|
||||
play.addEventListener("click", event => {
|
||||
event.stopPropagation();
|
||||
openViewer(item, true);
|
||||
});
|
||||
media.append(play);
|
||||
}
|
||||
if (item.kind === "video") media.append(playIcon(item));
|
||||
|
||||
media.addEventListener("click", () => openViewer(item, false));
|
||||
figure.append(media);
|
||||
|
||||
Reference in New Issue
Block a user