Files
nanobot/webui/src/lib/media.ts
T
Xubin RenandXubin Ren e52fe2a8e2 feat(webui): render video media attachments
Add signed media URLs to live WebSocket replies and teach the WebUI to classify and render video attachments, so bot-sent videos can play inline in both live chats and session history.

Made-with: Cursor
2026-04-25 03:20:40 +08:00

60 lines
1.2 KiB
TypeScript

import type { UIMediaAttachment, UIMediaKind } from "@/lib/types";
const IMAGE_EXTENSIONS = new Set([
".png",
".jpg",
".jpeg",
".gif",
".webp",
".bmp",
".ico",
".tif",
".tiff",
]);
const VIDEO_EXTENSIONS = new Set([
".mp4",
".webm",
".mov",
".m4v",
".avi",
".mkv",
".3gp",
]);
function cleanPath(value: string): string {
return value.split(/[?#]/, 1)[0]?.toLowerCase() ?? "";
}
function extensionOf(value?: string): string {
if (!value) return "";
const path = cleanPath(value);
const dot = path.lastIndexOf(".");
if (dot < 0) return "";
return path.slice(dot);
}
export function inferMediaKind(media: { url?: string; name?: string }): UIMediaKind {
const url = media.url ?? "";
if (url.startsWith("data:image/")) return "image";
if (url.startsWith("data:video/")) return "video";
const ext = extensionOf(media.name) || extensionOf(url);
if (IMAGE_EXTENSIONS.has(ext)) return "image";
if (VIDEO_EXTENSIONS.has(ext)) return "video";
return "file";
}
export function toMediaAttachment(media: {
url?: string;
name?: string;
kind?: UIMediaKind;
}): UIMediaAttachment {
return {
kind: media.kind ?? inferMediaKind(media),
url: media.url,
name: media.name,
};
}