diff --git a/src/components/JournalCard.tsx b/src/components/JournalCard.tsx index 30daa10..8805210 100644 --- a/src/components/JournalCard.tsx +++ b/src/components/JournalCard.tsx @@ -41,12 +41,17 @@ export function JournalCard( navigate(dumpUrl(dump)); } - const thumbnailUrl = - dump.kind === "file" && dump.fileMime?.startsWith("image/") + // Mirrors FilePreview (the hot/new feeds) so a video shows its generated + // still here too, rather than degrading to a text card with a 🎬. + const thumbnailUrl = dump.thumbnailMime + ? dumpThumbnailUrl(dump, token) + : dump.kind === "file" + ? (dump.fileMime?.startsWith("image/") ? dumpFileUrl(dump, token) - : dump.thumbnailMime + : dump.fileMime?.startsWith("video/") ? dumpThumbnailUrl(dump, token) - : (dump.richContent?.thumbnailUrl ?? null); + : null) + : (dump.richContent?.thumbnailUrl ?? null); // Content mode is independent of grid footprint: a thumbnailed dump reads as // an image card, a thumbnail-less dump with a note becomes a pull-quote, and @@ -151,12 +156,16 @@ export function JournalCard(
{embedUrl && (
diff --git a/src/utils/journalLayout.ts b/src/utils/journalLayout.ts index 2fd239d..05a6914 100644 --- a/src/utils/journalLayout.ts +++ b/src/utils/journalLayout.ts @@ -17,7 +17,12 @@ export interface JournalEntry { /** A dump that can carry a real preview image (file image or rich thumbnail). */ export function hasThumbnail(dump: Dump): boolean { - if (dump.kind === "file" && dump.fileMime?.startsWith("image/")) return true; + if (dump.kind === "file") { + const mime = dump.fileMime ?? ""; + // Videos count: GET /api/thumbnails/:dumpId grabs a still with ffmpeg on + // first request and caches it, so there's art to show without any upload. + if (mime.startsWith("image/") || mime.startsWith("video/")) return true; + } if (dump.thumbnailMime) return true; return !!dump.richContent?.thumbnailUrl; } diff --git a/src/utils/thumbnailTint.ts b/src/utils/thumbnailTint.ts index 70d5932..d82ac76 100644 --- a/src/utils/thumbnailTint.ts +++ b/src/utils/thumbnailTint.ts @@ -43,13 +43,18 @@ function hostnameOf(url: string | undefined): string | undefined { /** * The page's own brand color when it declared a usable one, otherwise a hue * derived from its hostname — so every card gets a tint, including rows saved - * before accent extraction existed. + * before accent extraction existed. File dumps have no hostname to hash and + * pass `seed` (their filename) instead. */ export function tintFor( - { accentColor, url }: { accentColor?: string; url?: string }, + { accentColor, url, seed }: { + accentColor?: string; + url?: string; + seed?: string; + }, ): string { if (isSafeHex(accentColor)) return accentColor; - return hueFromString(hostnameOf(url) ?? url ?? ""); + return hueFromString(seed ?? hostnameOf(url) ?? url ?? ""); } /** The letter drawn when there's no favicon to show. */