diff --git a/src/components/chat/ChatMediaRenderer.tsx b/src/components/chat/ChatMediaRenderer.tsx
index e9284ed..e6233fd 100644
--- a/src/components/chat/ChatMediaRenderer.tsx
+++ b/src/components/chat/ChatMediaRenderer.tsx
@@ -5,12 +5,31 @@
* [icon] filename [size] [blossom-link]
*/
+import { useState } from "react";
import { Image, Video, Music, File, Flower2 } from "lucide-react";
import { getHashFromURL } from "blossom-client-sdk/helpers/url";
import { useGrimoire } from "@/core/state";
import { formatFileSize } from "@/lib/imeta";
+import { MediaDialog } from "@/components/nostr/MediaDialog";
import type { MediaRendererProps } from "@/components/nostr/RichText";
+/**
+ * Extract file extension from URL
+ */
+function getExtension(url: string): string | null {
+ try {
+ const urlObj = new URL(url);
+ const pathname = urlObj.pathname;
+ const lastSegment = pathname.split("/").pop() || "";
+ if (lastSegment.includes(".")) {
+ return lastSegment.split(".").pop() || null;
+ }
+ return null;
+ } catch {
+ return null;
+ }
+}
+
/**
* Extract filename from URL
*/
@@ -22,7 +41,7 @@ function getFilename(url: string): string {
// If it's a blossom hash, truncate it
const hash = getHashFromURL(url);
if (hash) {
- const ext = lastSegment.includes(".") ? lastSegment.split(".").pop() : "";
+ const ext = getExtension(url);
return ext ? `${hash.slice(0, 8)}...${ext}` : `${hash.slice(0, 8)}...`;
}
// Decode URI component for readable filenames
@@ -69,6 +88,7 @@ function MediaIcon({ type }: { type: "image" | "video" | "audio" }) {
export function ChatMediaRenderer({ url, type, imeta }: MediaRendererProps) {
const { addWindow } = useGrimoire();
+ const [dialogOpen, setDialogOpen] = useState(false);
const filename = imeta?.alt || getFilename(url);
const size = imeta?.size ? formatFileSize(imeta.size) : null;
@@ -86,35 +106,47 @@ export function ChatMediaRenderer({ url, type, imeta }: MediaRendererProps) {
}
};
- const handleFileClick = (e: React.MouseEvent) => {
+ const handleMediaClick = (e: React.MouseEvent) => {
+ e.preventDefault();
e.stopPropagation();
+ // Images and videos open in dialog, audio opens in new tab
+ if (type === "image" || type === "video") {
+ setDialogOpen(true);
+ } else {
+ window.open(url, "_blank", "noopener,noreferrer");
+ }
};
return (
-
-
-
- {filename}
-
- {size && (
- {size}
- )}
- {blossom && (
+ <>
+
+
- )}
-
+ {size && (
+ {size}
+ )}
+ {blossom && (
+
+ )}
+
+
+ >
);
}