v3: fixed rich content extraction heuristics
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 3m15s

This commit is contained in:
khannurien
2026-04-11 13:13:43 +00:00
parent b822f861ed
commit 34933a3d4f
6 changed files with 280 additions and 32 deletions

View File

@@ -38,10 +38,28 @@ export function JournalCard(
navigate(dumpUrl(dump));
}
const thumbnailUrl = dump.kind === "file" &&
dump.fileMime?.startsWith("image/")
? `${API_URL}/api/files/${dump.id}?v=${dump.fileSize ?? 0}`
: (dump.richContent?.thumbnailUrl ?? null);
const rawThumbnail =
dump.kind === "file" && dump.fileMime?.startsWith("image/")
? `${API_URL}/api/files/${dump.id}?v=${dump.fileSize ?? 0}`
: (dump.richContent?.thumbnailUrl ?? null);
// Route external HTTP thumbnails through the server proxy to avoid
// mixed-content blocks when the frontend is served over HTTPS.
const thumbnailUrl = (() => {
if (!rawThumbnail) return null;
try {
const u = new URL(rawThumbnail);
if (
u.protocol === "http:" && u.hostname !== "localhost" &&
u.hostname !== "127.0.0.1"
) {
return `${API_URL}/api/proxy-image?url=${
encodeURIComponent(rawThumbnail)
}`;
}
} catch { /* relative URL */ }
return rawThumbnail;
})();
const fallbackIcon = dump.kind === "file"
? (() => {

View File

@@ -1,6 +1,21 @@
import { useContext } from "react";
import type { RichContent } from "../model.ts";
import { PlayerContext } from "../contexts/PlayerContext.ts";
import { API_URL } from "../config/api.ts";
/** Route HTTP thumbnail URLs through the server proxy to avoid mixed-content blocks. */
function proxyIfHttp(url: string): string {
try {
const u = new URL(url);
if (
u.protocol === "http:" && u.hostname !== "localhost" &&
u.hostname !== "127.0.0.1"
) {
return `${API_URL}/api/proxy-image?url=${encodeURIComponent(url)}`;
}
} catch { /* relative URL — leave as-is */ }
return url;
}
interface RichContentCardProps {
richContent: RichContent;
@@ -38,7 +53,7 @@ export default function RichContentCard(
{richContent.thumbnailUrl
? (
<img
src={richContent.thumbnailUrl}
src={proxyIfHttp(richContent.thumbnailUrl!)}
alt={richContent.title ?? ""}
className="rich-content-compact-thumbnail"
onError={(e) => {
@@ -65,7 +80,7 @@ export default function RichContentCard(
{richContent.thumbnailUrl
? (
<img
src={richContent.thumbnailUrl}
src={proxyIfHttp(richContent.thumbnailUrl!)}
alt={richContent.title ?? ""}
className="rich-content-compact-thumbnail"
onError={(e) => {
@@ -96,7 +111,7 @@ export default function RichContentCard(
aria-label="Play"
>
<img
src={richContent.thumbnailUrl}
src={proxyIfHttp(richContent.thumbnailUrl!)}
alt={richContent.title ?? ""}
className="rich-content-thumbnail"
onError={(e) => {
@@ -108,7 +123,7 @@ export default function RichContentCard(
)
: (
<img
src={richContent.thumbnailUrl}
src={proxyIfHttp(richContent.thumbnailUrl!)}
alt={richContent.title ?? ""}
className="rich-content-thumbnail"
onError={(e) => {