mirror of
				https://github.com/cinnyapp/cinny.git
				synced 2025-11-04 14:30:29 +03:00 
			
		
		
		
	feat(message): prioritize thumbnail loading with fallback to original image
When viewing messages, thumbnails are loaded first, if loading fails, the original image is loaded as a fallback.
This commit is contained in:
		
							parent
							
								
									abd713d693
								
							
						
					
					
						commit
						0a659e174c
					
				
					 3 changed files with 38 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -184,13 +184,32 @@ export function RenderMessageContent({
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  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 (
 | 
			
		||||
      <>
 | 
			
		||||
        <MImage
 | 
			
		||||
          content={getContent()}
 | 
			
		||||
          content={content}
 | 
			
		||||
          renderImageContent={(props) => (
 | 
			
		||||
            <ImageContent
 | 
			
		||||
              {...props}
 | 
			
		||||
              {...thumbnail}
 | 
			
		||||
              autoPlay={mediaAutoLoad}
 | 
			
		||||
              renderImage={(p) => <Image {...p} loading="lazy" />}
 | 
			
		||||
              renderViewer={(p) => <ImageViewer {...p} />}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,9 @@ export type ImageContentProps = {
 | 
			
		|||
  autoPlay?: boolean;
 | 
			
		||||
  markedAsSpoiler?: boolean;
 | 
			
		||||
  spoilerReason?: string;
 | 
			
		||||
  imgWidth?: number;
 | 
			
		||||
  imgHeight?: number;
 | 
			
		||||
  resizeMethod?: string;
 | 
			
		||||
  renderViewer: (props: RenderViewerProps) => ReactNode;
 | 
			
		||||
  renderImage: (props: RenderImageProps) => ReactNode;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -70,6 +73,9 @@ export const ImageContent = as<'div', ImageContentProps>(
 | 
			
		|||
      autoPlay,
 | 
			
		||||
      markedAsSpoiler,
 | 
			
		||||
      spoilerReason,
 | 
			
		||||
      imgWidth,
 | 
			
		||||
      imgHeight,
 | 
			
		||||
      resizeMethod,
 | 
			
		||||
      renderViewer,
 | 
			
		||||
      renderImage,
 | 
			
		||||
      ...props
 | 
			
		||||
| 
						 | 
				
			
			@ -84,10 +90,11 @@ export const ImageContent = as<'div', ImageContentProps>(
 | 
			
		|||
    const [error, setError] = useState(false);
 | 
			
		||||
    const [viewer, setViewer] = useState(false);
 | 
			
		||||
    const [blurred, setBlurred] = useState(markedAsSpoiler ?? false);
 | 
			
		||||
    const [useThumbnail, setUseThumbnail] = useState(imgWidth && imgHeight && resizeMethod);
 | 
			
		||||
 | 
			
		||||
    const [srcState, loadSrc] = useAsyncCallback(
 | 
			
		||||
      useCallback(async () => {
 | 
			
		||||
        const mediaUrl = mxcUrlToHttp(mx, url, useAuthentication) ?? url;
 | 
			
		||||
        const mediaUrl = (useThumbnail ? mxcUrlToHttp(mx, url, useAuthentication) : mxcUrlToHttp(mx, url, useAuthentication, imgWidth, imgHeight, resizeMethod)) ?? url;
 | 
			
		||||
        if (encInfo) {
 | 
			
		||||
          const fileContent = await downloadEncryptedMedia(mediaUrl, (encBuf) =>
 | 
			
		||||
            decryptFile(encBuf, mimeType ?? FALLBACK_MIMETYPE, encInfo)
 | 
			
		||||
| 
						 | 
				
			
			@ -95,15 +102,20 @@ export const ImageContent = as<'div', ImageContentProps>(
 | 
			
		|||
          return URL.createObjectURL(fileContent);
 | 
			
		||||
        }
 | 
			
		||||
        return mediaUrl;
 | 
			
		||||
      }, [mx, url, useAuthentication, mimeType, encInfo])
 | 
			
		||||
      }, [mx, url, useAuthentication, mimeType, encInfo, useThumbnail, imgWidth, imgHeight, resizeMethod])
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const handleLoad = () => {
 | 
			
		||||
      setLoad(true);
 | 
			
		||||
    };
 | 
			
		||||
    const handleError = () => {
 | 
			
		||||
      setLoad(false);
 | 
			
		||||
      setError(true);
 | 
			
		||||
      if (useThumbnail) {
 | 
			
		||||
        setUseThumbnail(false);
 | 
			
		||||
        loadSrc();
 | 
			
		||||
      } else {
 | 
			
		||||
        setLoad(false);
 | 
			
		||||
        setError(true);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const handleRetry = () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -134,7 +146,7 @@ export const ImageContent = as<'div', ImageContentProps>(
 | 
			
		|||
                  onContextMenu={(evt: any) => evt.stopPropagation()}
 | 
			
		||||
                >
 | 
			
		||||
                  {renderViewer({
 | 
			
		||||
                    src: srcState.data,
 | 
			
		||||
                    src: useThumbnail ? (mxcUrlToHttp(mx, url, useAuthentication) ?? url) : srcState.data,
 | 
			
		||||
                    alt: body,
 | 
			
		||||
                    requestClose: () => setViewer(false),
 | 
			
		||||
                  })}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,6 +49,7 @@ export type IImageContent = {
 | 
			
		|||
  url?: string;
 | 
			
		||||
  info?: IImageInfo & IThumbnailContent;
 | 
			
		||||
  file?: IEncryptedFile;
 | 
			
		||||
  info?: { h: number, w: number };
 | 
			
		||||
  [MATRIX_SPOILER_PROPERTY_NAME]?: boolean;
 | 
			
		||||
  [MATRIX_SPOILER_REASON_PROPERTY_NAME]?: string;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue