diff --git a/client/src/common/types.ts b/client/src/common/types.ts
index e4f1b16df2..86590c3ffd 100644
--- a/client/src/common/types.ts
+++ b/client/src/common/types.ts
@@ -181,6 +181,7 @@ export type TAskProps = {
export type TOptions = {
editedMessageId?: string | null;
editedText?: string | null;
+ resubmitFiles?: boolean;
isRegenerate?: boolean;
isContinued?: boolean;
isEdited?: boolean;
diff --git a/client/src/components/Chat/Input/Files/Table/fakeData.ts b/client/src/components/Chat/Input/Files/Table/fakeData.ts
index c56cc3737f..46f01bd0df 100644
--- a/client/src/components/Chat/Input/Files/Table/fakeData.ts
+++ b/client/src/components/Chat/Input/Files/Table/fakeData.ts
@@ -17,6 +17,7 @@ export const files: TFile[] = [
updatedAt: '2024-01-23T18:25:48.153Z',
usage: 0,
user: '652ac880c4102a77fe54c5db',
+ embedded: false,
},
{
_id: '65b004abd70ce86b9146e861',
@@ -34,6 +35,7 @@ export const files: TFile[] = [
usage: 0,
user: '652ac880c4102a77fe54c5db',
width: 1024,
+ embedded: false,
},
{
_id: '65b00495d70ce86b9146adc1',
@@ -51,6 +53,7 @@ export const files: TFile[] = [
usage: 0,
user: '652ac880c4102a77fe54c5db',
width: 1024,
+ embedded: false,
},
{
_id: '65b00494d70ce86b9146ace6',
@@ -68,5 +71,6 @@ export const files: TFile[] = [
usage: 0,
user: '652ac880c4102a77fe54c5db',
width: 1024,
+ embedded: false,
},
];
diff --git a/client/src/components/Chat/Messages/Content/Container.tsx b/client/src/components/Chat/Messages/Content/Container.tsx
index b26c014c88..bfb2ee2938 100644
--- a/client/src/components/Chat/Messages/Content/Container.tsx
+++ b/client/src/components/Chat/Messages/Content/Container.tsx
@@ -1,6 +1,9 @@
-// Container Component
-const Container = ({ children }: { children: React.ReactNode }) => (
+import { TMessage } from 'librechat-data-provider';
+import Files from './Files';
+
+const Container = ({ children, message }: { children: React.ReactNode; message: TMessage }) => (
+ {message.isCreatedByUser && }
{children}
);
diff --git a/client/src/components/Chat/Messages/Content/ContentParts.tsx b/client/src/components/Chat/Messages/Content/ContentParts.tsx
index 031795773f..9aff7db9fd 100644
--- a/client/src/components/Chat/Messages/Content/ContentParts.tsx
+++ b/client/src/components/Chat/Messages/Content/ContentParts.tsx
@@ -38,7 +38,7 @@ any) => {
{!isSubmitting && unfinished && (
-
+
)}
diff --git a/client/src/components/Chat/Messages/Content/EditMessage.tsx b/client/src/components/Chat/Messages/Content/EditMessage.tsx
index 0c830e04fe..e17a17356d 100644
--- a/client/src/components/Chat/Messages/Content/EditMessage.tsx
+++ b/client/src/components/Chat/Messages/Content/EditMessage.tsx
@@ -3,10 +3,10 @@ import { EModelEndpoint } from 'librechat-data-provider';
import { useState, useRef, useEffect, useCallback } from 'react';
import { useUpdateMessageMutation } from 'librechat-data-provider/react-query';
import type { TEditProps } from '~/common';
-import Container from '~/components/Messages/Content/Container';
import { cn, removeFocusOutlines } from '~/utils';
import { useChatContext } from '~/Providers';
import { useLocalize } from '~/hooks';
+import Container from './Container';
const EditMessage = ({
text,
@@ -39,11 +39,16 @@ const EditMessage = ({
const resubmitMessage = () => {
if (message.isCreatedByUser) {
- ask({
- text: editedText,
- parentMessageId,
- conversationId,
- });
+ ask(
+ {
+ text: editedText,
+ parentMessageId,
+ conversationId,
+ },
+ {
+ resubmitFiles: true,
+ },
+ );
setSiblingIdx((siblingIdx ?? 0) - 1);
} else {
@@ -105,7 +110,7 @@ const EditMessage = ({
);
return (
-
+
{
diff --git a/client/src/components/Chat/Messages/Content/Files.tsx b/client/src/components/Chat/Messages/Content/Files.tsx
new file mode 100644
index 0000000000..beff81b58b
--- /dev/null
+++ b/client/src/components/Chat/Messages/Content/Files.tsx
@@ -0,0 +1,39 @@
+import { useMemo, memo } from 'react';
+import type { TFile, TMessage } from 'librechat-data-provider';
+import FileContainer from '~/components/Chat/Input/Files/FileContainer';
+import Image from './Image';
+
+const Files = ({ message }: { message: TMessage }) => {
+ const imageFiles = useMemo(() => {
+ return message?.files?.filter((file) => file.type?.startsWith('image/')) || [];
+ }, [message?.files]);
+
+ const otherFiles = useMemo(() => {
+ return message?.files?.filter((file) => !file.type?.startsWith('image/')) || [];
+ }, [message?.files]);
+
+ return (
+ <>
+ {otherFiles.length > 0 &&
+ otherFiles.map((file) => )}
+ {imageFiles &&
+ imageFiles.map((file) => (
+
+ ))}
+ >
+ );
+};
+
+export default memo(Files);
diff --git a/client/src/components/Chat/Messages/Content/Image.tsx b/client/src/components/Chat/Messages/Content/Image.tsx
index 4176815dec..18bafa49ea 100644
--- a/client/src/components/Chat/Messages/Content/Image.tsx
+++ b/client/src/components/Chat/Messages/Content/Image.tsx
@@ -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;
+}) => {
+ 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(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 (
-
+
- {isLoaded && minDisplayTimeElapsed && (
-
- )}
+ {isLoaded &&
}
);
};
diff --git a/client/src/components/Chat/Messages/Content/MessageContent.tsx b/client/src/components/Chat/Messages/Content/MessageContent.tsx
index ea761c6569..5f75fc3b74 100644
--- a/client/src/components/Chat/Messages/Content/MessageContent.tsx
+++ b/client/src/components/Chat/Messages/Content/MessageContent.tsx
@@ -1,7 +1,6 @@
import { Fragment, Suspense } from 'react';
-import type { TResPlugin, TFile } from 'librechat-data-provider';
-import type { TMessageContentProps, TText, TDisplayProps } from '~/common';
-import FileContainer from '~/components/Chat/Input/Files/FileContainer';
+import type { TMessage, TResPlugin } from 'librechat-data-provider';
+import type { TMessageContentProps, TDisplayProps } from '~/common';
import Plugin from '~/components/Messages/Content/Plugin';
import Error from '~/components/Messages/Content/Error';
import { DelayedRender } from '~/components/ui';
@@ -9,11 +8,14 @@ import EditMessage from './EditMessage';
import Container from './Container';
import Markdown from './Markdown';
import { cn } from '~/utils';
-import Image from './Image';
-export const ErrorMessage = ({ text, className = '' }: TText) => {
+export const ErrorMessage = ({
+ text,
+ message,
+ className = '',
+}: Pick
) => {
return (
-
+
{
// Display Message Component
const DisplayMessage = ({ text, isCreatedByUser, message, showCursor }: TDisplayProps) => {
- const files: TFile[] = [];
- const imageFiles = message?.files
- ? message.files.filter((file) => {
- if (file.type && file.type.startsWith('image/')) {
- return true;
- }
-
- files.push(file);
- })
- : null;
return (
-
- {files.length > 0 && files.map((file) => )}
- {imageFiles &&
- imageFiles.map((file) => (
-
- ))}
+
(
-
+export const UnfinishedMessage = ({ message }: { message: TMessage }) => (
+
);
// Content Component
@@ -86,7 +68,7 @@ const MessageContent = ({
...props
}: TMessageContentProps) => {
if (error) {
- return
;
+ return
;
} else if (edit) {
return
;
} else {
@@ -143,7 +125,7 @@ const MessageContent = ({
{!isSubmitting && unfinished && (
-
+
)}
diff --git a/client/src/components/Chat/Messages/Content/Part.tsx b/client/src/components/Chat/Messages/Content/Part.tsx
index e52ccfd082..e01e11d03b 100644
--- a/client/src/components/Chat/Messages/Content/Part.tsx
+++ b/client/src/components/Chat/Messages/Content/Part.tsx
@@ -53,11 +53,11 @@ export default function Part({
}
if (part.type === ContentTypes.ERROR) {
- return
;
+ return
;
} else if (part.type === ContentTypes.TEXT) {
// Access the value property
return (
-
+