web: tweak scrolling behavior
This commit is contained in:
@@ -452,6 +452,7 @@ export default function App() {
|
||||
const searchRunCounterRef = useRef(0);
|
||||
const shouldAutoScrollRef = useRef(true);
|
||||
const wasSendingRef = useRef(false);
|
||||
const pendingReplyScrollRef = useRef(false);
|
||||
const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
|
||||
const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);
|
||||
const [sidebarQuery, setSidebarQuery] = useState("");
|
||||
@@ -643,6 +644,12 @@ export default function App() {
|
||||
}, [providerModelPreferences]);
|
||||
|
||||
const selectedKey = selectedItem ? `${selectedItem.kind}:${selectedItem.id}` : null;
|
||||
const isChatReplyStreamingInView =
|
||||
isSending &&
|
||||
draftKind !== "search" &&
|
||||
selectedItem?.kind !== "search" &&
|
||||
!!pendingChatState &&
|
||||
(!pendingChatState.chatId || (selectedItem?.kind === "chat" && selectedItem.id === pendingChatState.chatId));
|
||||
|
||||
useEffect(() => {
|
||||
shouldAutoScrollRef.current = true;
|
||||
@@ -675,11 +682,27 @@ export default function App() {
|
||||
if (draftKind === "search" || selectedItem?.kind === "search") return;
|
||||
const wasSending = wasSendingRef.current;
|
||||
wasSendingRef.current = isSending;
|
||||
if (wasSending && !isSending) return;
|
||||
if (isSending) return;
|
||||
if (wasSending) {
|
||||
shouldAutoScrollRef.current = false;
|
||||
return;
|
||||
}
|
||||
if (!shouldAutoScrollRef.current) return;
|
||||
transcriptEndRef.current?.scrollIntoView({ behavior: isSending ? "smooth" : "auto", block: "end" });
|
||||
transcriptEndRef.current?.scrollIntoView({ behavior: "auto", block: "end" });
|
||||
}, [draftKind, selectedChat?.messages.length, isSending, selectedItem?.kind, selectedKey]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isChatReplyStreamingInView || !pendingReplyScrollRef.current) return;
|
||||
pendingReplyScrollRef.current = false;
|
||||
shouldAutoScrollRef.current = true;
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
const container = transcriptContainerRef.current;
|
||||
if (!container) return;
|
||||
container.scrollTo({ top: container.scrollHeight, behavior: "smooth" });
|
||||
});
|
||||
}, [isChatReplyStreamingInView, pendingChatState?.chatId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isSending) return;
|
||||
const hasWorkspaceSelection = Boolean(selectedItem) || draftKind !== null;
|
||||
@@ -697,13 +720,7 @@ export default function App() {
|
||||
const messages = selectedChat?.messages ?? [];
|
||||
const isSearchMode = draftKind ? draftKind === "search" : selectedItem?.kind === "search";
|
||||
const isSearchRunning = isSending && isSearchMode;
|
||||
const isSendingActiveChat =
|
||||
isSending &&
|
||||
!isSearchMode &&
|
||||
!!pendingChatState &&
|
||||
!!pendingChatState.chatId &&
|
||||
selectedItem?.kind === "chat" &&
|
||||
selectedItem.id === pendingChatState.chatId;
|
||||
const isSendingActiveChat = isChatReplyStreamingInView;
|
||||
const displayMessages = useMemo(() => {
|
||||
if (!pendingChatState) return messages.filter(isDisplayableMessage);
|
||||
if (pendingChatState.chatId) {
|
||||
@@ -837,6 +854,8 @@ export default function App() {
|
||||
}, [contextMenu]);
|
||||
|
||||
const handleSendChat = async (content: string) => {
|
||||
pendingReplyScrollRef.current = true;
|
||||
|
||||
const optimisticUserMessage: Message = {
|
||||
id: `temp-user-${Date.now()}`,
|
||||
createdAt: new Date().toISOString(),
|
||||
@@ -1424,7 +1443,7 @@ export default function App() {
|
||||
|
||||
<div
|
||||
ref={transcriptContainerRef}
|
||||
className="flex-1 overflow-y-auto px-4 pt-8 md:px-10 lg:px-14 pb-36 md:pb-44"
|
||||
className="flex-1 overflow-y-auto px-4 pt-8 md:px-10 lg:px-14 pb-36 md:pb-44 [overflow-anchor:none]"
|
||||
onScroll={() => {
|
||||
const container = transcriptContainerRef.current;
|
||||
if (!container) return;
|
||||
@@ -1443,6 +1462,9 @@ export default function App() {
|
||||
onStartChat={selectedSearch ? handleStartChatFromSearch : undefined}
|
||||
/>
|
||||
)}
|
||||
{isChatReplyStreamingInView ? (
|
||||
<div className="mx-auto mt-6 h-[52vh] min-h-72 max-h-[36rem] max-w-4xl" aria-hidden="true" />
|
||||
) : null}
|
||||
<div ref={transcriptEndRef} />
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user