mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-04 22:40:29 +03:00
Merge 09e445453c into 46c02b89de
This commit is contained in:
commit
f35d43124c
3 changed files with 45 additions and 9 deletions
|
|
@ -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} />}
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue