From 6314ed8667914dc0724aee9397c3d9a9cfb9f9e1 Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Sun, 1 May 2022 20:56:11 -0700 Subject: [PATCH] Add performant list componant for rendering chat messages --- web/components/chat/ChatContainer.tsx | 20 +++++++-- web/components/ui/Sidebar/Sidebar.tsx | 2 + web/package-lock.json | 58 +++++++++++++++++++++++++++ web/package.json | 1 + web/stories/ChatContainer.stories.tsx | 2 +- 5 files changed, 79 insertions(+), 4 deletions(-) diff --git a/web/components/chat/ChatContainer.tsx b/web/components/chat/ChatContainer.tsx index 77ff5e3fe..01272806d 100644 --- a/web/components/chat/ChatContainer.tsx +++ b/web/components/chat/ChatContainer.tsx @@ -1,6 +1,9 @@ import { Spin } from 'antd'; +import { Virtuoso } from 'react-virtuoso'; +import { useState, useMemo, useCallback, useEffect, useRef } from 'react'; import { ChatMessage } from '../../interfaces/chat-message.model'; import { ChatState } from '../../interfaces/application-state'; +import ChatUserMessage from './ChatUserMessage'; interface Props { messages: ChatMessage[]; @@ -11,11 +14,22 @@ export default function ChatContainer(props: Props) { const { messages, state } = props; const loading = state === ChatState.Loading; + const chatContainerRef = useRef(null); + return (
- - Chat container with scrolling chat messages go here - + + + ( + + )} + followOutput="auto" + />
); } diff --git a/web/components/ui/Sidebar/Sidebar.tsx b/web/components/ui/Sidebar/Sidebar.tsx index 1f5b5256d..5ee44eb4e 100644 --- a/web/components/ui/Sidebar/Sidebar.tsx +++ b/web/components/ui/Sidebar/Sidebar.tsx @@ -4,6 +4,7 @@ import { ChatMessage } from '../../../interfaces/chat-message.model'; import ChatContainer from '../../chat/ChatContainer'; import { chatMessages, chatVisibility as chatVisibilityAtom } from '../../stores/ClientConfigStore'; import { ChatVisibilityState } from '../../../interfaces/application-state'; +import ChatTextField from '../../chat/ChatTextField'; export default function Sidebar() { const messages = useRecoilValue(chatMessages); @@ -21,6 +22,7 @@ export default function Sidebar() { }} > + ); } diff --git a/web/package-lock.json b/web/package-lock.json index 5751fc59e..d82a85105 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -30,6 +30,7 @@ "react-linkify": "1.0.0-alpha", "react-markdown": "8.0.0", "react-markdown-editor-lite": "1.3.2", + "react-virtuoso": "^2.10.2", "recoil": "^0.7.2", "ua-parser-js": "1.0.2", "video.js": "^7.18.1" @@ -11453,6 +11454,25 @@ "is-function": "^1.0.1" } }, + "node_modules/@virtuoso.dev/react-urx": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@virtuoso.dev/react-urx/-/react-urx-0.2.13.tgz", + "integrity": "sha512-MY0ugBDjFb5Xt8v2HY7MKcRGqw/3gTpMlLXId2EwQvYJoC8sP7nnXjAxcBtTB50KTZhO0SbzsFimaZ7pSdApwA==", + "dependencies": { + "@virtuoso.dev/urx": "^0.2.13" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/@virtuoso.dev/urx": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@virtuoso.dev/urx/-/urx-0.2.13.tgz", + "integrity": "sha512-iirJNv92A1ZWxoOHHDYW/1KPoi83939o83iUBQHIim0i3tMeSKEh+bxhJdTHQ86Mr4uXx9xGUTq69cp52ZP8Xw==" + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -26756,6 +26776,22 @@ "node": ">=8" } }, + "node_modules/react-virtuoso": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-2.10.2.tgz", + "integrity": "sha512-nQ8Wt/q64q6walcXo4y9SXkvZqjwuLiNUv7aKW3poKoZno8agTgeqcX1GMq3GPlaJ8wR5XMGwBxX4HONBMAGfg==", + "dependencies": { + "@virtuoso.dev/react-urx": "^0.2.12", + "@virtuoso.dev/urx": "^0.2.12" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16 || >=17 || >= 18", + "react-dom": ">=16 || >=17 || >= 18" + } + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -40135,6 +40171,19 @@ "is-function": "^1.0.1" } }, + "@virtuoso.dev/react-urx": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@virtuoso.dev/react-urx/-/react-urx-0.2.13.tgz", + "integrity": "sha512-MY0ugBDjFb5Xt8v2HY7MKcRGqw/3gTpMlLXId2EwQvYJoC8sP7nnXjAxcBtTB50KTZhO0SbzsFimaZ7pSdApwA==", + "requires": { + "@virtuoso.dev/urx": "^0.2.13" + } + }, + "@virtuoso.dev/urx": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@virtuoso.dev/urx/-/urx-0.2.13.tgz", + "integrity": "sha512-iirJNv92A1ZWxoOHHDYW/1KPoi83939o83iUBQHIim0i3tMeSKEh+bxhJdTHQ86Mr4uXx9xGUTq69cp52ZP8Xw==" + }, "@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -51972,6 +52021,15 @@ } } }, + "react-virtuoso": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-2.10.2.tgz", + "integrity": "sha512-nQ8Wt/q64q6walcXo4y9SXkvZqjwuLiNUv7aKW3poKoZno8agTgeqcX1GMq3GPlaJ8wR5XMGwBxX4HONBMAGfg==", + "requires": { + "@virtuoso.dev/react-urx": "^0.2.12", + "@virtuoso.dev/urx": "^0.2.12" + } + }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", diff --git a/web/package.json b/web/package.json index d52a4f01e..17841fcff 100644 --- a/web/package.json +++ b/web/package.json @@ -33,6 +33,7 @@ "react-linkify": "1.0.0-alpha", "react-markdown": "8.0.0", "react-markdown-editor-lite": "1.3.2", + "react-virtuoso": "^2.10.2", "recoil": "^0.7.2", "ua-parser-js": "1.0.2", "video.js": "^7.18.1" diff --git a/web/stories/ChatContainer.stories.tsx b/web/stories/ChatContainer.stories.tsx index 5a4eddc8b..a2126a6ac 100644 --- a/web/stories/ChatContainer.stories.tsx +++ b/web/stories/ChatContainer.stories.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { ComponentStory, ComponentMeta } from '@storybook/react'; import ChatContainer from '../components/chat/ChatContainer'; import { ChatMessage } from '../interfaces/chat-message.model';