feat(media): implement caching for chat media and update components to use cached media
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
"use client";
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
/**
|
||||
* ImageBubble 图片气泡
|
||||
*
|
||||
@@ -13,6 +14,7 @@ import { useState } from "react";
|
||||
|
||||
import { ROUTE_BUILDERS } from "@/router/routes";
|
||||
|
||||
import { useCachedChatMediaUrl } from "../hooks/use-cached-chat-media-url";
|
||||
import styles from "./image-bubble.module.css";
|
||||
|
||||
export interface ImageBubbleProps {
|
||||
@@ -28,9 +30,15 @@ export function ImageBubble({
|
||||
}: ImageBubbleProps) {
|
||||
const router = useRouter();
|
||||
const [error, setError] = useState(false);
|
||||
const { mediaUrl } = useCachedChatMediaUrl({
|
||||
messageId,
|
||||
remoteUrl: imageUrl,
|
||||
kind: "image",
|
||||
});
|
||||
|
||||
const src = decodeBase64Image(imageUrl);
|
||||
const src = decodeBase64Image(mediaUrl || imageUrl);
|
||||
const canOpen = Boolean(messageId);
|
||||
const shouldUseNativeImage = isBrowserLocalImageSrc(src);
|
||||
|
||||
const openImage = () => {
|
||||
if (!messageId) return;
|
||||
@@ -54,6 +62,13 @@ export function ImageBubble({
|
||||
>
|
||||
{error ? (
|
||||
<div className={styles.errorFallback}>🖼</div>
|
||||
) : shouldUseNativeImage ? (
|
||||
<img
|
||||
className={styles.image}
|
||||
src={src}
|
||||
alt=""
|
||||
onError={() => setError(true)}
|
||||
/>
|
||||
) : (
|
||||
<Image
|
||||
className={styles.image}
|
||||
@@ -80,3 +95,7 @@ function decodeBase64Image(uri: string): string {
|
||||
// 裸 base64 字符串 → 包装成 data URI(PNG 兜底)
|
||||
return `data:image/png;base64,${uri}`;
|
||||
}
|
||||
|
||||
function isBrowserLocalImageSrc(src: string): boolean {
|
||||
return src.startsWith("blob:") || src.startsWith("data:");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user