diff --git a/frontend/app/view/waveai/waveai.tsx b/frontend/app/view/waveai/waveai.tsx index 0bdc2412b..63434914a 100644 --- a/frontend/app/view/waveai/waveai.tsx +++ b/frontend/app/view/waveai/waveai.tsx @@ -4,6 +4,7 @@ import { Button } from "@/app/element/button"; import { Markdown } from "@/app/element/markdown"; import { TypingIndicator } from "@/app/element/typingindicator"; +import { useDimensionsWithExistingRef } from "@/app/hook/useDimensions"; import { RpcResponseHelper, WshClient } from "@/app/store/wshclient"; import { RpcApi } from "@/app/store/wshclientapi"; import { makeFeBlockRouteId } from "@/app/store/wshrouter"; @@ -506,84 +507,88 @@ interface ChatWindowProps { messages: ChatMessageType[]; msgWidths: Object; model: WaveAiModel; + height: number; } const ChatWindow = memo( - forwardRef(({ chatWindowRef, messages, msgWidths, model }, ref) => { - const [isUserScrolling, setIsUserScrolling] = useState(false); + forwardRef( + ({ chatWindowRef, messages, msgWidths, model, height }, ref) => { + const [isUserScrolling, setIsUserScrolling] = useState(false); - const osRef = useRef(null); - const prevMessagesLenRef = useRef(messages.length); + const osRef = useRef(null); + const prevMessagesLenRef = useRef(messages.length); - useImperativeHandle(ref, () => osRef.current as OverlayScrollbarsComponentRef); + useImperativeHandle(ref, () => osRef.current as OverlayScrollbarsComponentRef); - useEffect(() => { - if (osRef.current && osRef.current.osInstance()) { - const { viewport } = osRef.current.osInstance().elements(); - const curMessagesLen = messages.length; - if (prevMessagesLenRef.current !== curMessagesLen || !isUserScrolling) { - setIsUserScrolling(false); - viewport.scrollTo({ - behavior: "auto", - top: chatWindowRef.current?.scrollHeight || 0, - }); - } - - prevMessagesLenRef.current = curMessagesLen; - } - }, [messages, isUserScrolling]); - - useEffect(() => { - if (osRef.current && osRef.current.osInstance()) { - const { viewport } = osRef.current.osInstance().elements(); - - const handleUserScroll = () => { - setIsUserScrolling(true); - }; - - viewport.addEventListener("wheel", handleUserScroll, { passive: true }); - viewport.addEventListener("touchmove", handleUserScroll, { passive: true }); - - return () => { - viewport.removeEventListener("wheel", handleUserScroll); - viewport.removeEventListener("touchmove", handleUserScroll); - if (osRef.current && osRef.current.osInstance()) { - osRef.current.osInstance().destroy(); + useEffect(() => { + if (osRef.current && osRef.current.osInstance()) { + const { viewport } = osRef.current.osInstance().elements(); + const curMessagesLen = messages.length; + if (prevMessagesLenRef.current !== curMessagesLen || !isUserScrolling) { + setIsUserScrolling(false); + viewport.scrollTo({ + behavior: "auto", + top: chatWindowRef.current?.scrollHeight || 0, + }); } - }; - } - }, []); - const handleScrollbarInitialized = (instance: OverlayScrollbars) => { - const { viewport } = instance.elements(); - viewport.removeAttribute("tabindex"); - viewport.scrollTo({ - behavior: "auto", - top: chatWindowRef.current?.scrollHeight || 0, - }); - }; + prevMessagesLenRef.current = curMessagesLen; + } + }, [messages, isUserScrolling]); - const handleScrollbarUpdated = (instance: OverlayScrollbars) => { - const { viewport } = instance.elements(); - viewport.removeAttribute("tabindex"); - }; + useEffect(() => { + if (osRef.current && osRef.current.osInstance()) { + const { viewport } = osRef.current.osInstance().elements(); - return ( - -
-
- {messages.map((chitem, idx) => ( - - ))} -
-
- ); - }) + const handleUserScroll = () => { + setIsUserScrolling(true); + }; + + viewport.addEventListener("wheel", handleUserScroll, { passive: true }); + viewport.addEventListener("touchmove", handleUserScroll, { passive: true }); + + return () => { + viewport.removeEventListener("wheel", handleUserScroll); + viewport.removeEventListener("touchmove", handleUserScroll); + if (osRef.current && osRef.current.osInstance()) { + osRef.current.osInstance().destroy(); + } + }; + } + }, []); + + const handleScrollbarInitialized = (instance: OverlayScrollbars) => { + const { viewport } = instance.elements(); + viewport.removeAttribute("tabindex"); + viewport.scrollTo({ + behavior: "auto", + top: chatWindowRef.current?.scrollHeight || 0, + }); + }; + + const handleScrollbarUpdated = (instance: OverlayScrollbars) => { + const { viewport } = instance.elements(); + viewport.removeAttribute("tabindex"); + }; + + return ( + +
+
+ {messages.map((chitem, idx) => ( + + ))} +
+
+ ); + } + ) ); interface ChatInputProps { @@ -657,6 +662,8 @@ const WaveAi = ({ model }: { model: WaveAiModel; blockId: string }) => { const chatWindowRef = useRef(null); const osRef = useRef(null); const inputRef = useRef(null); + const waveAiDims = useDimensionsWithExistingRef(waveaiRef); + const chatInputDims = useDimensionsWithExistingRef(inputRef); const [value, setValue] = useState(""); const [selectedBlockIdx, setSelectedBlockIdx] = useState(null); @@ -829,6 +836,8 @@ const WaveAi = ({ model }: { model: WaveAiModel; blockId: string }) => { messages={messages} msgWidths={msgWidths} model={model} + height={waveAiDims?.height - chatInputDims?.height - 28 ?? 400} + // the 28 is a magic number it the moment but it makes the spacing look good />