v3: fixed rich content extraction heuristics
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 3m15s
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 3m15s
This commit is contained in:
@@ -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"
|
||||
? (() => {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user