🚀 feat: Enhance Message Editing with File Resubmission (#2347)

* chore: fix type issue with File Table fakeData

* refactor: new lazy loading image strategy and load images/files as part of Message Container

* feat: resubmit files when editing messages with attached files
This commit is contained in:
Danny Avila 2024-04-07 13:25:24 -04:00 committed by GitHub
parent caabab4489
commit 3411d7a543
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 122 additions and 90 deletions

View file

@ -1,18 +1,35 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useRef, useMemo } from 'react';
import { LazyLoadImage } from 'react-lazy-load-image-component';
import * as Dialog from '@radix-ui/react-dialog';
import DialogImage from './DialogImage';
import { cn } from '~/utils';
const scaleImage = ({
originalWidth,
originalHeight,
containerRef,
}: {
originalWidth: number;
originalHeight: number;
containerRef: React.RefObject<HTMLDivElement>;
}) => {
const containerWidth = containerRef.current?.offsetWidth ?? 0;
if (containerWidth === 0 || originalWidth === undefined || originalHeight === undefined) {
return { width: 'auto', height: 'auto' };
}
const aspectRatio = originalWidth / originalHeight;
const scaledWidth = Math.min(containerWidth, originalWidth);
const scaledHeight = scaledWidth / aspectRatio;
return { width: `${scaledWidth}px`, height: `${scaledHeight}px` };
};
const Image = ({
imagePath,
altText,
height,
width,
placeholderDimensions,
}: // n,
// i,
{
}: {
imagePath: string;
altText: string;
height: number;
@ -21,69 +38,49 @@ const Image = ({
height: string;
width: string;
};
// n: number;
// i: number;
}) => {
const [isLoaded, setIsLoaded] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
const handleImageLoad = () => setIsLoaded(true);
const [minDisplayTimeElapsed, setMinDisplayTimeElapsed] = useState(false);
useEffect(() => {
let timer: NodeJS.Timeout;
if (isLoaded) {
timer = setTimeout(() => setMinDisplayTimeElapsed(true), 150);
}
return () => clearTimeout(timer);
}, [isLoaded]);
// const makeSquare = n >= 3 && i < 2;
let placeholderHeight = '288px';
if (placeholderDimensions?.height && placeholderDimensions?.width) {
placeholderHeight = placeholderDimensions.height;
} else if (height > width) {
placeholderHeight = '900px';
} else if (height === width) {
placeholderHeight = width + 'px';
}
const { width: scaledWidth, height: scaledHeight } = useMemo(
() =>
scaleImage({
originalWidth: Number(placeholderDimensions?.width?.split('px')[0]) ?? width,
originalHeight: Number(placeholderDimensions?.height?.split('px')[0]) ?? height,
containerRef,
}),
[placeholderDimensions, height, width],
);
return (
<Dialog.Root>
<div className="">
<div ref={containerRef}>
<div className="relative mt-1 flex h-auto w-full max-w-lg items-center justify-center overflow-hidden bg-gray-200 text-gray-500 dark:bg-gray-700 dark:text-gray-400">
<Dialog.Trigger asChild>
<button type="button" aria-haspopup="dialog" aria-expanded="false">
<LazyLoadImage
// loading="lazy"
alt={altText}
onLoad={handleImageLoad}
visibleByDefault={true}
className={cn(
'max-h-[900px] max-w-full opacity-100 transition-opacity duration-300',
// n >= 3 && i < 2 ? 'aspect-square object-cover' : '',
isLoaded && minDisplayTimeElapsed ? 'opacity-100' : 'opacity-0',
'opacity-100 transition-opacity duration-100',
isLoaded ? 'opacity-100' : 'opacity-0',
)}
src={imagePath}
style={{
height: isLoaded && minDisplayTimeElapsed ? 'auto' : placeholderHeight,
width: placeholderDimensions?.width ?? width,
width: scaledWidth,
height: 'auto',
color: 'transparent',
}}
placeholder={
<div
style={{
height: isLoaded && minDisplayTimeElapsed ? 'auto' : placeholderHeight,
width: placeholderDimensions?.width ?? width,
}}
/>
}
placeholder={<div style={{ width: scaledWidth, height: scaledHeight }} />}
/>
</button>
</Dialog.Trigger>
</div>
</div>
{isLoaded && minDisplayTimeElapsed && (
<DialogImage src={imagePath} height={height} width={width} />
)}
{isLoaded && <DialogImage src={imagePath} height={height} width={width} />}
</Dialog.Root>
);
};