|
1 | 1 | import { useCallback, useEffect, useMemo, useRef, useState } from 'react' |
2 | 2 | import { createLogger } from '@sim/logger' |
3 | 3 | import { useQueryClient } from '@tanstack/react-query' |
4 | | -import { usePathname } from 'next/navigation' |
| 4 | +import { usePathname, useRouter } from 'next/navigation' |
5 | 5 | import { toDisplayMessage } from '@/lib/copilot/chat/display-message' |
6 | 6 | import type { |
7 | 7 | PersistedFileAttachment, |
@@ -709,6 +709,7 @@ export function useChat( |
709 | 709 | options?: UseChatOptions |
710 | 710 | ): UseChatReturn { |
711 | 711 | const pathname = usePathname() |
| 712 | + const router = useRouter() |
712 | 713 | const queryClient = useQueryClient() |
713 | 714 | const [messages, setMessages] = useState<ChatMessage[]>([]) |
714 | 715 | const [isSending, setIsSending] = useState(false) |
@@ -962,6 +963,8 @@ export function useChat( |
962 | 963 | const recoveringClientWorkflowToolIdsRef = useRef<Set<string>>(new Set()) |
963 | 964 | const executionStream = useExecutionStream() |
964 | 965 | const isHomePage = pathname.endsWith('/home') |
| 966 | + const wasHomePageRef = useRef(isHomePage) |
| 967 | + const pendingHomeResetRef = useRef(false) |
965 | 968 |
|
966 | 969 | const setTransportIdle = useCallback(() => { |
967 | 970 | sendingRef.current = false |
@@ -994,6 +997,25 @@ export function useChat( |
994 | 997 | resetStreamingBuffers() |
995 | 998 | }, [resetStreamingBuffers]) |
996 | 999 |
|
| 1000 | + const resetHomeChatState = useCallback(() => { |
| 1001 | + streamGenRef.current++ |
| 1002 | + chatIdRef.current = undefined |
| 1003 | + lastCursorRef.current = '0' |
| 1004 | + locallyTerminalStreamIdRef.current = undefined |
| 1005 | + clearActiveTurn() |
| 1006 | + setResolvedChatId(undefined) |
| 1007 | + appliedChatHistoryKeyRef.current = undefined |
| 1008 | + abortControllerRef.current = null |
| 1009 | + setMessages([]) |
| 1010 | + setError(null) |
| 1011 | + setTransportIdle() |
| 1012 | + setResources([]) |
| 1013 | + setActiveResourceId(null) |
| 1014 | + resetEphemeralPreviewState() |
| 1015 | + setMessageQueue([]) |
| 1016 | + clearQueueDispatchState() |
| 1017 | + }, [clearActiveTurn, clearQueueDispatchState, resetEphemeralPreviewState, setTransportIdle]) |
| 1018 | + |
997 | 1019 | const mergeServerMessagesWithActiveTurn = useCallback( |
998 | 1020 | (serverMessages: ChatMessage[], previousMessages: ChatMessage[]) => { |
999 | 1021 | const activeTurn = activeTurnRef.current |
@@ -1196,31 +1218,33 @@ export function useChat( |
1196 | 1218 | ]) |
1197 | 1219 |
|
1198 | 1220 | useEffect(() => { |
1199 | | - if (workflowIdRef.current) return |
1200 | | - if (!isHomePage || !chatIdRef.current) return |
1201 | | - streamGenRef.current++ |
1202 | | - chatIdRef.current = undefined |
1203 | | - lastCursorRef.current = '0' |
1204 | | - locallyTerminalStreamIdRef.current = undefined |
1205 | | - clearActiveTurn() |
1206 | | - setResolvedChatId(undefined) |
1207 | | - appliedChatHistoryKeyRef.current = undefined |
1208 | | - abortControllerRef.current = null |
1209 | | - setMessages([]) |
1210 | | - setError(null) |
1211 | | - setTransportIdle() |
1212 | | - setResources([]) |
1213 | | - setActiveResourceId(null) |
1214 | | - resetEphemeralPreviewState() |
1215 | | - setMessageQueue([]) |
1216 | | - clearQueueDispatchState() |
1217 | | - }, [ |
1218 | | - isHomePage, |
1219 | | - resetEphemeralPreviewState, |
1220 | | - clearQueueDispatchState, |
1221 | | - clearActiveTurn, |
1222 | | - setTransportIdle, |
1223 | | - ]) |
| 1221 | + const wasHomePage = wasHomePageRef.current |
| 1222 | + wasHomePageRef.current = isHomePage |
| 1223 | + |
| 1224 | + if (!isHomePage) { |
| 1225 | + pendingHomeResetRef.current = false |
| 1226 | + return |
| 1227 | + } |
| 1228 | + if (workflowIdRef.current || !chatIdRef.current) return |
| 1229 | + |
| 1230 | + const shouldHandleHomeReset = pendingHomeResetRef.current || !wasHomePage |
| 1231 | + if (!shouldHandleHomeReset) return |
| 1232 | + |
| 1233 | + const hasActiveTransport = |
| 1234 | + isSending || |
| 1235 | + sendingRef.current || |
| 1236 | + isReconnecting || |
| 1237 | + abortControllerRef.current !== null || |
| 1238 | + streamReaderRef.current !== null |
| 1239 | + |
| 1240 | + if (hasActiveTransport) { |
| 1241 | + pendingHomeResetRef.current = true |
| 1242 | + return |
| 1243 | + } |
| 1244 | + |
| 1245 | + pendingHomeResetRef.current = false |
| 1246 | + resetHomeChatState() |
| 1247 | + }, [isHomePage, isReconnecting, isSending, resetHomeChatState]) |
1224 | 1248 |
|
1225 | 1249 | useEffect(() => { |
1226 | 1250 | if (!chatHistory) return |
@@ -1583,11 +1607,9 @@ export function useChat( |
1583 | 1607 | }) |
1584 | 1608 | } |
1585 | 1609 | if (!workflowIdRef.current) { |
1586 | | - window.history.replaceState( |
1587 | | - null, |
1588 | | - '', |
1589 | | - `/workspace/${workspaceId}/task/${payloadChatId}` |
1590 | | - ) |
| 1610 | + router.replace(`/workspace/${workspaceId}/task/${payloadChatId}`, { |
| 1611 | + scroll: false, |
| 1612 | + }) |
1591 | 1613 | } |
1592 | 1614 | } |
1593 | 1615 | } |
@@ -2153,6 +2175,7 @@ export function useChat( |
2153 | 2175 | }, |
2154 | 2176 | [ |
2155 | 2177 | workspaceId, |
| 2178 | + router, |
2156 | 2179 | queryClient, |
2157 | 2180 | addResource, |
2158 | 2181 | removeResource, |
|
0 commit comments