From e0e03e95b1b637aadfe8aa166e6d313a38f7cc76 Mon Sep 17 00:00:00 2001 From: john Date: Mon, 29 Jun 2026 11:15:40 +0800 Subject: [PATCH] fix(chat): speed up history switch --- src/components/HistorySidebar.tsx | 29 +++++++++++++++++++++++++++-- src/hooks/useTKMindChat.ts | 16 +++++++++------- src/index.css | 11 +++++++++++ 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/components/HistorySidebar.tsx b/src/components/HistorySidebar.tsx index 1d680e4..78e6b68 100644 --- a/src/components/HistorySidebar.tsx +++ b/src/components/HistorySidebar.tsx @@ -59,11 +59,13 @@ export function HistorySidebar({ const bodyRef = useRef(null); const [visibleCount, setVisibleCount] = useState(appConfig.sessionPageSize); const [pendingDeleteId, setPendingDeleteId] = useState(null); + const [pendingSelectId, setPendingSelectId] = useState(null); useEffect(() => { if (open) { setVisibleCount(appConfig.sessionPageSize); setPendingDeleteId(null); + setPendingSelectId(null); } }, [open, sessions.length]); @@ -77,6 +79,7 @@ export function HistorySidebar({ }, [visibleCount, sessions.length]); const handleDeleteClick = useCallback((sessionId: string) => { + setPendingSelectId(null); setPendingDeleteId(sessionId); }, []); @@ -92,6 +95,24 @@ export function HistorySidebar({ setPendingDeleteId(null); }, []); + const handleSelectClick = useCallback( + (sessionId: string) => { + if (pendingDeleteId === sessionId) return; + if (activeSessionId === sessionId) { + setPendingSelectId(null); + onSelect(sessionId); + return; + } + if (pendingSelectId === sessionId) { + setPendingSelectId(null); + onSelect(sessionId); + return; + } + setPendingSelectId(sessionId); + }, + [activeSessionId, onSelect, pendingDeleteId, pendingSelectId], + ); + if (!open) return null; const visibleSessions = sessions.slice(0, visibleCount); @@ -130,17 +151,21 @@ export function HistorySidebar({ {group.sessions.map((item) => { const label = getSessionListLabel(item); const isPending = pendingDeleteId === item.id; + const isPendingSelect = pendingSelectId === item.id; return (
  • {isPending ? (
    diff --git a/src/hooks/useTKMindChat.ts b/src/hooks/useTKMindChat.ts index 2163eb3..01b428f 100644 --- a/src/hooks/useTKMindChat.ts +++ b/src/hooks/useTKMindChat.ts @@ -610,22 +610,24 @@ export function useTKMindChat( setPendingTool(null); activeRequestId.current = null; - const resumed = options?.skipResume - ? (options.seedSession ?? null) - : await resumeSession(sessionId); - if (token !== connectTokenRef.current) return; - const knownSession = sessionsRef.current.find((s) => s.id === sessionId); const hints = knownSession ? { messageCount: knownSession.message_count, updatedAt: knownSession.updated_at } : undefined; - const { session: detail, messages: history } = await loadSessionDetail(sessionId, hints); + const detailPromise = loadSessionDetail(sessionId, hints); + const resumedPromise = options?.skipResume + ? Promise.resolve(options.seedSession ?? null) + : resumeSession(sessionId); + const { session: detail, messages: history } = await detailPromise; if (token !== connectTokenRef.current) return; writeStoredSessionId(userRef.current?.id, sessionId); - setSession({ ...detail, ...(resumed ?? {}), id: sessionId }); + setSession((current) => (current?.id === sessionId ? { ...detail, ...current, id: sessionId } : { ...detail, id: sessionId })); messagesRef.current = history; setMessages(history); + const resumed = await resumedPromise; + if (token !== connectTokenRef.current) return; + setSession({ ...detail, ...(resumed ?? {}), id: sessionId }); setChatState('idle'); setSessions((prev) => prependUnique(prev, { ...detail, ...resumed, id: sessionId })); diff --git a/src/index.css b/src/index.css index 9f3bf2f..3153151 100644 --- a/src/index.css +++ b/src/index.css @@ -253,6 +253,10 @@ body, color: var(--color-text-primary); } +.sidebar-item-pending { + background: rgba(255, 255, 255, 0.06); +} + .sidebar-item-title { display: block; font-size: 14px; @@ -269,6 +273,13 @@ body, color: var(--color-text-faint); } +.sidebar-item-hint { + display: block; + margin-top: 6px; + font-size: 11px; + color: var(--color-text-secondary); +} + .sidebar-item-confirming .sidebar-item { pointer-events: none; opacity: 0.6;