refactor(chat): share media image rendering
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
"use client";
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
|
||||
import Image from "next/image";
|
||||
import type { MouseEventHandler, ReactNode } from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
import {
|
||||
isBrowserLocalChatImageSource,
|
||||
normalizeChatImageSource,
|
||||
} from "@/lib/chat/chat_media_url";
|
||||
import { useCachedChatMediaUrl } from "@/lib/chat/use_cached_chat_media_url";
|
||||
|
||||
export interface ChatMediaImageProps {
|
||||
messageId?: string;
|
||||
remoteUrl: string;
|
||||
alt?: string;
|
||||
className?: string;
|
||||
nativeClassName?: string;
|
||||
errorClassName?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
fill?: boolean;
|
||||
sizes?: string;
|
||||
showErrorFallback?: boolean;
|
||||
onClick?: MouseEventHandler<HTMLImageElement>;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export function ChatMediaImage({
|
||||
messageId,
|
||||
remoteUrl,
|
||||
alt = "",
|
||||
className,
|
||||
nativeClassName,
|
||||
errorClassName,
|
||||
width = 240,
|
||||
height = 240,
|
||||
fill = false,
|
||||
sizes,
|
||||
showErrorFallback = true,
|
||||
onClick,
|
||||
children,
|
||||
}: ChatMediaImageProps) {
|
||||
const [errorSrc, setErrorSrc] = useState<string | null>(null);
|
||||
const { mediaUrl, isUsingCachedMedia, reportMediaError } =
|
||||
useCachedChatMediaUrl({
|
||||
messageId,
|
||||
remoteUrl,
|
||||
kind: "image",
|
||||
});
|
||||
|
||||
const src = normalizeChatImageSource(mediaUrl || remoteUrl);
|
||||
const shouldUseNativeImage = isBrowserLocalChatImageSource(src);
|
||||
const hasError = errorSrc === src;
|
||||
|
||||
const handleImageError = () => {
|
||||
if (isUsingCachedMedia) {
|
||||
reportMediaError();
|
||||
return;
|
||||
}
|
||||
setErrorSrc(src);
|
||||
};
|
||||
|
||||
if (hasError && showErrorFallback) {
|
||||
return <div className={errorClassName}>🖼</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{shouldUseNativeImage ? (
|
||||
<img
|
||||
className={nativeClassName ?? className}
|
||||
src={src}
|
||||
alt={alt}
|
||||
onError={handleImageError}
|
||||
onClick={onClick}
|
||||
/>
|
||||
) : fill ? (
|
||||
<Image
|
||||
className={className}
|
||||
src={src}
|
||||
alt={alt}
|
||||
fill
|
||||
sizes={sizes}
|
||||
onError={handleImageError}
|
||||
onClick={onClick}
|
||||
/>
|
||||
) : (
|
||||
<Image
|
||||
className={className}
|
||||
src={src}
|
||||
alt={alt}
|
||||
width={width}
|
||||
height={height}
|
||||
sizes={sizes}
|
||||
onError={handleImageError}
|
||||
onClick={onClick}
|
||||
/>
|
||||
)}
|
||||
{hasError ? null : children}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user