This commit is contained in:
纳西妲 · Nahida 2025-10-16 16:46:47 +02:00 committed by GitHub
commit f35d43124c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 45 additions and 9 deletions

View file

@ -184,13 +184,32 @@ export function RenderMessageContent({
} }
if (msgType === MsgType.Image) { if (msgType === MsgType.Image) {
const content: IImageContent = getContent();
const width = content?.info?.w;
const height = content?.info?.h;
let thumbnail: {
imgWidth: number,
imgHeight: number,
resizeMethod: string
} | undefined;
if (width && height) {
const scale = (width > height ? width : height) / 800;
if (width > 800 || height > 800 && scale > 1) {
thumbnail = {
imgWidth: width / scale,
imgHeight: height / scale,
resizeMethod: "scale",
}
}
}
return ( return (
<> <>
<MImage <MImage
content={getContent()} content={content}
renderImageContent={(props) => ( renderImageContent={(props) => (
<ImageContent <ImageContent
{...props} {...props}
{...thumbnail}
autoPlay={mediaAutoLoad} autoPlay={mediaAutoLoad}
renderImage={(p) => <Image {...p} loading="lazy" />} renderImage={(p) => <Image {...p} loading="lazy" />}
renderViewer={(p) => <ImageViewer {...p} />} renderViewer={(p) => <ImageViewer {...p} />}

View file

@ -55,6 +55,9 @@ export type ImageContentProps = {
autoPlay?: boolean; autoPlay?: boolean;
markedAsSpoiler?: boolean; markedAsSpoiler?: boolean;
spoilerReason?: string; spoilerReason?: string;
imgWidth?: number;
imgHeight?: number;
resizeMethod?: string;
renderViewer: (props: RenderViewerProps) => ReactNode; renderViewer: (props: RenderViewerProps) => ReactNode;
renderImage: (props: RenderImageProps) => ReactNode; renderImage: (props: RenderImageProps) => ReactNode;
}; };
@ -70,6 +73,9 @@ export const ImageContent = as<'div', ImageContentProps>(
autoPlay, autoPlay,
markedAsSpoiler, markedAsSpoiler,
spoilerReason, spoilerReason,
imgWidth,
imgHeight,
resizeMethod,
renderViewer, renderViewer,
renderImage, renderImage,
...props ...props
@ -84,26 +90,36 @@ export const ImageContent = as<'div', ImageContentProps>(
const [error, setError] = useState(false); const [error, setError] = useState(false);
const [viewer, setViewer] = useState(false); const [viewer, setViewer] = useState(false);
const [blurred, setBlurred] = useState(markedAsSpoiler ?? false); const [blurred, setBlurred] = useState(markedAsSpoiler ?? false);
const [useThumbnail, setUseThumbnail] = useState(imgWidth && imgHeight && resizeMethod);
const [srcState, loadSrc] = useAsyncCallback( const [srcState, loadSrc] = useAsyncCallback(
useCallback(async () => { useCallback(async () => {
const mediaUrl = mxcUrlToHttp(mx, url, useAuthentication) ?? url; const mediaUrl = (useThumbnail ? mxcUrlToHttp(mx, url, useAuthentication, imgWidth, imgHeight, resizeMethod) : mxcUrlToHttp(mx, url, useAuthentication)) ?? url;
if (encInfo) { if (encInfo) {
const fileContent = await downloadEncryptedMedia(mediaUrl, (encBuf) => const decrypt = (encBuf: ArrayBuffer) => decryptFile(encBuf, mimeType ?? FALLBACK_MIMETYPE, encInfo);
decryptFile(encBuf, mimeType ?? FALLBACK_MIMETYPE, encInfo) let fileContent;
); try {
fileContent = await downloadEncryptedMedia(mediaUrl, decrypt);
} catch {
fileContent = await downloadEncryptedMedia(mxcUrlToHttp(mx, url, useAuthentication) ?? url, decrypt);
}
return URL.createObjectURL(fileContent); return URL.createObjectURL(fileContent);
} }
return mediaUrl; return mediaUrl;
}, [mx, url, useAuthentication, mimeType, encInfo]) }, [mx, url, useAuthentication, mimeType, encInfo, useThumbnail, imgWidth, imgHeight, resizeMethod])
); );
const handleLoad = () => { const handleLoad = () => {
setLoad(true); setLoad(true);
}; };
const handleError = () => { const handleError = () => {
if (useThumbnail) {
setUseThumbnail(false);
loadSrc();
} else {
setLoad(false); setLoad(false);
setError(true); setError(true);
}
}; };
const handleRetry = () => { const handleRetry = () => {
@ -134,7 +150,7 @@ export const ImageContent = as<'div', ImageContentProps>(
onContextMenu={(evt: any) => evt.stopPropagation()} onContextMenu={(evt: any) => evt.stopPropagation()}
> >
{renderViewer({ {renderViewer({
src: srcState.data, src: useThumbnail ? (mxcUrlToHttp(mx, url, useAuthentication) ?? url) : srcState.data,
alt: body, alt: body,
requestClose: () => setViewer(false), requestClose: () => setViewer(false),
})} })}

View file

@ -49,6 +49,7 @@ export type IImageContent = {
url?: string; url?: string;
info?: IImageInfo & IThumbnailContent; info?: IImageInfo & IThumbnailContent;
file?: IEncryptedFile; file?: IEncryptedFile;
info?: { h: number, w: number };
[MATRIX_SPOILER_PROPERTY_NAME]?: boolean; [MATRIX_SPOILER_PROPERTY_NAME]?: boolean;
[MATRIX_SPOILER_REASON_PROPERTY_NAME]?: string; [MATRIX_SPOILER_REASON_PROPERTY_NAME]?: string;
}; };