mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-25 19:15:18 +02:00
Merge pull request #1170 from SohamBhattacharjee2003/fix/optimize-dom-queries-in-thread
fix: optimize dom queries in thread
This commit is contained in:
commit
bc3e510968
1 changed files with 41 additions and 19 deletions
|
|
@ -28,7 +28,7 @@ import {
|
||||||
import { AnimatePresence, motion } from "motion/react";
|
import { AnimatePresence, motion } from "motion/react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { type FC, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { type FC, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
import {
|
import {
|
||||||
agentToolsAtom,
|
agentToolsAtom,
|
||||||
|
|
@ -338,11 +338,13 @@ const Composer: FC = () => {
|
||||||
const [showPromptPicker, setShowPromptPicker] = useState(false);
|
const [showPromptPicker, setShowPromptPicker] = useState(false);
|
||||||
const [mentionQuery, setMentionQuery] = useState("");
|
const [mentionQuery, setMentionQuery] = useState("");
|
||||||
const [actionQuery, setActionQuery] = useState("");
|
const [actionQuery, setActionQuery] = useState("");
|
||||||
|
const [containerPos, setContainerPos] = useState({ bottom: "200px", left: "50%", top: "auto" });
|
||||||
const editorRef = useRef<InlineMentionEditorRef>(null);
|
const editorRef = useRef<InlineMentionEditorRef>(null);
|
||||||
const editorContainerRef = useRef<HTMLDivElement>(null);
|
const editorContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const composerBoxRef = useRef<HTMLDivElement>(null);
|
const composerBoxRef = useRef<HTMLDivElement>(null);
|
||||||
const documentPickerRef = useRef<DocumentMentionPickerRef>(null);
|
const documentPickerRef = useRef<DocumentMentionPickerRef>(null);
|
||||||
const promptPickerRef = useRef<PromptPickerRef>(null);
|
const promptPickerRef = useRef<PromptPickerRef>(null);
|
||||||
|
const viewportRef = useRef<Element | null>(null);
|
||||||
const { search_space_id, chat_id } = useParams();
|
const { search_space_id, chat_id } = useParams();
|
||||||
const aui = useAui();
|
const aui = useAui();
|
||||||
const threadViewportStore = useThreadViewportStore();
|
const threadViewportStore = useThreadViewportStore();
|
||||||
|
|
@ -355,6 +357,36 @@ const Composer: FC = () => {
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Store viewport element reference on mount
|
||||||
|
useEffect(() => {
|
||||||
|
viewportRef.current = document.querySelector(".aui-thread-viewport");
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Compute picker positions using ResizeObserver to avoid layout reads during render
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (!editorContainerRef.current) return;
|
||||||
|
|
||||||
|
const updatePosition = () => {
|
||||||
|
if (!editorContainerRef.current) return;
|
||||||
|
const rect = editorContainerRef.current.getBoundingClientRect();
|
||||||
|
const composerRect = composerBoxRef.current?.getBoundingClientRect();
|
||||||
|
setContainerPos({
|
||||||
|
bottom: `${window.innerHeight - rect.top + 8}px`,
|
||||||
|
left: `${rect.left}px`,
|
||||||
|
top: composerRect ? `${composerRect.bottom + 8}px` : "auto",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
updatePosition();
|
||||||
|
const ro = new ResizeObserver(updatePosition);
|
||||||
|
ro.observe(editorContainerRef.current);
|
||||||
|
if (composerBoxRef.current) {
|
||||||
|
ro.observe(composerBoxRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => ro.disconnect();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const electronAPI = useElectronAPI();
|
const electronAPI = useElectronAPI();
|
||||||
const [clipboardInitialText, setClipboardInitialText] = useState<string | undefined>();
|
const [clipboardInitialText, setClipboardInitialText] = useState<string | undefined>();
|
||||||
const clipboardLoadedRef = useRef(false);
|
const clipboardLoadedRef = useRef(false);
|
||||||
|
|
@ -572,7 +604,7 @@ const Composer: FC = () => {
|
||||||
if (isThreadRunning || isBlockedByOtherUser) return;
|
if (isThreadRunning || isBlockedByOtherUser) return;
|
||||||
if (showDocumentPopover) return;
|
if (showDocumentPopover) return;
|
||||||
|
|
||||||
const viewportEl = document.querySelector(".aui-thread-viewport");
|
const viewportEl = viewportRef.current;
|
||||||
const heightBefore = viewportEl?.scrollHeight ?? 0;
|
const heightBefore = viewportEl?.scrollHeight ?? 0;
|
||||||
|
|
||||||
aui.composer().send();
|
aui.composer().send();
|
||||||
|
|
@ -599,7 +631,7 @@ const Composer: FC = () => {
|
||||||
|
|
||||||
const pollAndScroll = () => {
|
const pollAndScroll = () => {
|
||||||
if (cancelled) return;
|
if (cancelled) return;
|
||||||
const el = document.querySelector(".aui-thread-viewport");
|
const el = viewportRef.current;
|
||||||
if (el) {
|
if (el) {
|
||||||
const h = el.scrollHeight;
|
const h = el.scrollHeight;
|
||||||
if (h !== lastHeight) {
|
if (h !== lastHeight) {
|
||||||
|
|
@ -723,12 +755,8 @@ const Composer: FC = () => {
|
||||||
initialSelectedDocuments={mentionedDocuments}
|
initialSelectedDocuments={mentionedDocuments}
|
||||||
externalSearch={mentionQuery}
|
externalSearch={mentionQuery}
|
||||||
containerStyle={{
|
containerStyle={{
|
||||||
bottom: editorContainerRef.current
|
bottom: containerPos.bottom,
|
||||||
? `${window.innerHeight - editorContainerRef.current.getBoundingClientRect().top + 8}px`
|
left: containerPos.left,
|
||||||
: "200px",
|
|
||||||
left: editorContainerRef.current
|
|
||||||
? `${editorContainerRef.current.getBoundingClientRect().left}px`
|
|
||||||
: "50%",
|
|
||||||
}}
|
}}
|
||||||
/>,
|
/>,
|
||||||
document.body
|
document.body
|
||||||
|
|
@ -746,16 +774,10 @@ const Composer: FC = () => {
|
||||||
externalSearch={actionQuery}
|
externalSearch={actionQuery}
|
||||||
containerStyle={{
|
containerStyle={{
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
...(clipboardInitialText && composerBoxRef.current
|
...(clipboardInitialText
|
||||||
? { top: `${composerBoxRef.current.getBoundingClientRect().bottom + 8}px` }
|
? { top: containerPos.top }
|
||||||
: {
|
: { bottom: containerPos.bottom }),
|
||||||
bottom: editorContainerRef.current
|
left: containerPos.left,
|
||||||
? `${window.innerHeight - editorContainerRef.current.getBoundingClientRect().top + 8}px`
|
|
||||||
: "200px",
|
|
||||||
}),
|
|
||||||
left: editorContainerRef.current
|
|
||||||
? `${editorContainerRef.current.getBoundingClientRect().left}px`
|
|
||||||
: "50%",
|
|
||||||
zIndex: 50,
|
zIndex: 50,
|
||||||
}}
|
}}
|
||||||
/>,
|
/>,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue