mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
fix(frontend): V1 Loading UI (#11630)
This commit is contained in:
parent
9a7002d817
commit
7e824ca5dc
@ -97,24 +97,29 @@ export function ChatInterface() {
|
||||
|
||||
const isV1Conversation = conversation?.conversation_version === "V1";
|
||||
|
||||
// Instantly scroll to bottom when history loading completes
|
||||
const prevLoadingHistoryRef = React.useRef(
|
||||
// Track when we should show V1 messages (after DOM has rendered)
|
||||
const [showV1Messages, setShowV1Messages] = React.useState(false);
|
||||
const prevV1LoadingRef = React.useRef(
|
||||
conversationWebSocket?.isLoadingHistory,
|
||||
);
|
||||
|
||||
// Wait for DOM to render before showing V1 messages
|
||||
React.useEffect(() => {
|
||||
const wasLoading = prevLoadingHistoryRef.current;
|
||||
const wasLoading = prevV1LoadingRef.current;
|
||||
const isLoading = conversationWebSocket?.isLoadingHistory;
|
||||
|
||||
// When history loading transitions from true to false, instantly scroll to bottom
|
||||
if (wasLoading && !isLoading && scrollRef.current) {
|
||||
scrollRef.current.scrollTo({
|
||||
top: scrollRef.current.scrollHeight,
|
||||
behavior: "instant",
|
||||
if (wasLoading && !isLoading) {
|
||||
// Loading just finished - wait for next frame to ensure DOM is ready
|
||||
requestAnimationFrame(() => {
|
||||
setShowV1Messages(true);
|
||||
});
|
||||
} else if (isLoading) {
|
||||
// Reset when loading starts
|
||||
setShowV1Messages(false);
|
||||
}
|
||||
|
||||
prevLoadingHistoryRef.current = isLoading;
|
||||
}, [conversationWebSocket?.isLoadingHistory, scrollRef]);
|
||||
prevV1LoadingRef.current = isLoading;
|
||||
}, [conversationWebSocket?.isLoadingHistory]);
|
||||
|
||||
// Filter V0 events
|
||||
const v0Events = storeEvents
|
||||
@ -252,7 +257,7 @@ export function ChatInterface() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{conversationWebSocket?.isLoadingHistory &&
|
||||
{(conversationWebSocket?.isLoadingHistory || !showV1Messages) &&
|
||||
isV1Conversation &&
|
||||
!isTask && (
|
||||
<div className="flex justify-center">
|
||||
@ -269,7 +274,7 @@ export function ChatInterface() {
|
||||
/>
|
||||
)}
|
||||
|
||||
{!conversationWebSocket?.isLoadingHistory && v1UserEventsExist && (
|
||||
{showV1Messages && v1UserEventsExist && (
|
||||
<V1Messages messages={v1UiEvents} allEvents={v1FullEvents} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
import { RefObject, useEffect, useState, useCallback, useRef } from "react";
|
||||
import {
|
||||
RefObject,
|
||||
useState,
|
||||
useCallback,
|
||||
useRef,
|
||||
useLayoutEffect,
|
||||
} from "react";
|
||||
|
||||
export function useScrollToBottom(scrollRef: RefObject<HTMLDivElement | null>) {
|
||||
// Track whether we should auto-scroll to the bottom when content changes
|
||||
@ -65,20 +71,20 @@ export function useScrollToBottom(scrollRef: RefObject<HTMLDivElement | null>) {
|
||||
}, [scrollRef]);
|
||||
|
||||
// Auto-scroll effect that runs when content changes
|
||||
useEffect(() => {
|
||||
// Use useLayoutEffect to scroll after DOM updates but before paint
|
||||
useLayoutEffect(() => {
|
||||
// Only auto-scroll if autoscroll is enabled
|
||||
if (autoscroll) {
|
||||
const dom = scrollRef.current;
|
||||
if (dom) {
|
||||
requestAnimationFrame(() => {
|
||||
dom.scrollTo({
|
||||
top: dom.scrollHeight,
|
||||
behavior: "smooth",
|
||||
});
|
||||
// Scroll to bottom - this will trigger on any DOM change
|
||||
dom.scrollTo({
|
||||
top: dom.scrollHeight,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}); // No dependency array - runs after every render to follow new content
|
||||
|
||||
return {
|
||||
scrollRef,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user