feat(canvas): show loading state while agent history loads
Track agent history loading in the workspace and render a spinner with a localized "loading conversation history" message in the assistant feed, so the empty state no longer flashes before history resolves. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -341,6 +341,7 @@
|
||||
"conversation": "Chat",
|
||||
"newChat": "New chat",
|
||||
"conversationHistory": "History",
|
||||
"loadingConversationHistory": "Loading conversation history...",
|
||||
"scrollToLatest": "Scroll to latest",
|
||||
"searchConversationPlaceholder": "Search conversations",
|
||||
"deleteConversation": "Delete conversation",
|
||||
|
||||
@@ -341,6 +341,7 @@
|
||||
"conversation": "对话",
|
||||
"newChat": "新对话",
|
||||
"conversationHistory": "历史对话",
|
||||
"loadingConversationHistory": "正在加载历史对话...",
|
||||
"scrollToLatest": "回到底部",
|
||||
"searchConversationPlaceholder": "请输入搜索关键词",
|
||||
"deleteConversation": "删除对话",
|
||||
|
||||
@@ -575,6 +575,7 @@ export function CanvasWorkspace({ projectId, shareAccess = ownerWorkspaceAccess
|
||||
const { project, setProject, projectRef, viewport, setViewport, viewportRef, nodes, setNodes, nodesRef, applyProjectDocument } = useCanvasDocument();
|
||||
const { selectedId, selectedIds, setSelectedIds, selectedNodes, selectedNode, selectOnlyNode, selectNodes, toggleNodeSelection } = useCanvasSelection(nodes);
|
||||
const [messages, setMessages] = useState<AgentMessage[]>([]);
|
||||
const [agentHistoryLoading, setAgentHistoryLoading] = useState(canViewChat);
|
||||
const [prompt, setPrompt] = useState("");
|
||||
const [agentStarterConfig, setAgentStarterConfig] = useState<AgentStarterConfig>(() => defaultAgentStarterConfig(t));
|
||||
const [agentThreads, setAgentThreads] = useState<AgentThreadSummary[]>([]);
|
||||
@@ -901,17 +902,20 @@ export function CanvasWorkspace({ projectId, shareAccess = ownerWorkspaceAccess
|
||||
useEffect(() => {
|
||||
selectedAgentThreadIdRef.current = null;
|
||||
setSelectedAgentThreadId(null);
|
||||
setAgentHistoryLoading(canViewChat);
|
||||
setAgentThreads([]);
|
||||
setAgentHistorySearch("");
|
||||
setAgentHistoryOpen(false);
|
||||
autoScrollAgentFeedRef.current = false;
|
||||
}, [projectId]);
|
||||
}, [canViewChat, projectId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (agentHistoryOpen) void loadAgentThreads();
|
||||
}, [agentHistoryOpen, loadAgentThreads]);
|
||||
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
setAgentHistoryLoading(canViewChat);
|
||||
designGateway
|
||||
.getProject(projectId)
|
||||
.then(({ project: nextProject }) => {
|
||||
@@ -961,7 +965,13 @@ export function CanvasWorkspace({ projectId, shareAccess = ownerWorkspaceAccess
|
||||
return;
|
||||
}
|
||||
setError(toUserMessageText(err, "generateError"));
|
||||
})
|
||||
.finally(() => {
|
||||
if (active) setAgentHistoryLoading(false);
|
||||
});
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}, [applyProject, canViewChat, projectId, startProjectEvents]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -2649,6 +2659,7 @@ export function CanvasWorkspace({ projectId, shareAccess = ownerWorkspaceAccess
|
||||
autoScrollAgentFeedRef.current = false;
|
||||
selectedAgentThreadIdRef.current = newAgentConversationId;
|
||||
setSelectedAgentThreadId(newAgentConversationId);
|
||||
setAgentHistoryLoading(false);
|
||||
setAgentHistoryOpen(false);
|
||||
setPrompt("");
|
||||
setMessages([]);
|
||||
@@ -4124,7 +4135,12 @@ export function CanvasWorkspace({ projectId, shareAccess = ownerWorkspaceAccess
|
||||
</div>
|
||||
|
||||
<div className="assistant-feed" ref={assistantFeedRef} onScroll={updateAssistantScrollButton}>
|
||||
{!hasCurrentConversation && !agentTimelineActive ? (
|
||||
{agentHistoryLoading ? (
|
||||
<div className="assistant-history-loading" role="status" aria-live="polite" data-testid="agent-history-loading">
|
||||
<Loader2 className="spin" size={20} aria-hidden="true" />
|
||||
<span>{t("loadingConversationHistory")}</span>
|
||||
</div>
|
||||
) : !hasCurrentConversation && !agentTimelineActive ? (
|
||||
<CanvasAgentEmptyState config={agentStarterConfig} disabled={!canEdit} onSelectPrompt={selectAgentStarterPrompt} />
|
||||
) : (
|
||||
<CanvasAgentTimeline messages={messages} nodes={nodes} active={agentTimelineActive} />
|
||||
|
||||
@@ -3789,6 +3789,24 @@ button:disabled {
|
||||
background: #dfe0e2;
|
||||
}
|
||||
|
||||
.assistant-history-loading {
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
flex: 1 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
color: #8a9099;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.assistant-history-loading svg {
|
||||
color: #646a73;
|
||||
}
|
||||
|
||||
.assistant-scroll-to-end {
|
||||
position: absolute;
|
||||
inset-inline: 0;
|
||||
|
||||
Reference in New Issue
Block a user