Add per-kind stats, GIF hover playback, and static gif previews

This commit is contained in:
Fisto
2026-09-16 13:36:51 +02:00
parent 612b2504dc
commit 0081224954
13 changed files with 189 additions and 57 deletions
+45 -6
View File
@@ -191,11 +191,31 @@
return `${kind}${source}${channel}${author}${aspect}${resolution}${after}${before}`;
}
function kindTotals(field) {
const stats = state.stats ?? {};
return {
images: (stats.image?.[field] ?? 0) + (stats.gif?.[field] ?? 0),
videos: stats.video?.[field] ?? 0
};
}
function countLoaded() {
let images = 0;
let videos = 0;
for (const item of state.items) {
if (item.kind === "video") videos++;
else if (item.kind === "image" || item.kind === "gif") images++;
}
return { images, videos };
}
function renderStatus() {
const stats = state.stats ?? { total: 0, downloaded: 0, cached: 0, notDownloaded: 0 };
const downloaded = kindTotals("downloaded");
const cached = kindTotals("cached");
const loaded = countLoaded();
setStatus(
`(Images/Videos) | Downloaded ${stats.downloaded}/${stats.total} | ` +
`Cached ${stats.cached}/${stats.total} (excl Downl) | Loaded ${state.items.length}/${stats.total}`
`(Images/Videos) | Downloaded ${downloaded.images}/${downloaded.videos} | ` +
`Cached ${cached.images}/${cached.videos} | Loaded ${loaded.images}/${loaded.videos}`
);
}
@@ -428,15 +448,22 @@
const figure = el("figure", "vk-media-figure");
const media = el("div", "vk-media-media");
const source = gridSource(item);
const playable = /\.(mp4|webm|m4v)(\?|$)/i.test(item.url ?? "");
const videoSource = item.localUrl || item.playUrl || (item.source !== "embed" ? item.url : null);
const playableVideo =
!!videoSource &&
(/\.(mp4|webm|m4v)(\?|$)/i.test(videoSource) || videoSource === item.playUrl);
const animatedGif =
item.kind === "gif" && item.remotePreviewUrl && /\.gif(\?|$)/i.test(item.remotePreviewUrl)
? item.remotePreviewUrl
: null;
if (item.kind === "video" && source && item.source !== "embed" && playable) {
if (item.kind === "video" && videoSource && playableVideo) {
// Discord has no server-side video thumbnails; the browser shows the first frame.
const video = document.createElement("video");
video.preload = "metadata";
video.muted = true;
video.playsInline = true;
video.src = source;
video.src = videoSource;
video.addEventListener(
"loadedmetadata",
() => {
@@ -452,11 +479,23 @@
img.src = source;
img.alt = item.kind;
img.addEventListener("error", () => placeholder(media, item), { once: true });
// GIFs stay static in the grid and play while hovered.
if (animatedGif) {
media.addEventListener("mouseenter", () => {
img.src = animatedGif;
});
media.addEventListener("mouseleave", () => {
img.src = source;
});
}
media.append(img);
} else {
placeholder(media, item);
}
if (item.kind === "gif") media.append(el("span", "vk-media-gif-label", "GIF"));
if (item.kind === "video") media.append(playIcon(item));
media.addEventListener("click", () => openViewer(item, false));