mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
fix: resolve webview loading screen hang issue (#5593)
- Add 10-second timeout to force hydration if state message is never received - Improve error handling in webview message handler with try-catch blocks - Add fallback state posting to prevent infinite loading scenarios - Add comprehensive test for timeout functionality Fixes #5593
This commit is contained in:
parent
b03d03d860
commit
082b827fa1
3 changed files with 61 additions and 7 deletions
|
|
@ -252,14 +252,29 @@ export const webviewMessageHandler = async (
|
|||
|
||||
switch (message.type) {
|
||||
case "webviewDidLaunch":
|
||||
// Load custom modes first
|
||||
const customModes = await provider.customModesManager.getCustomModes()
|
||||
await updateGlobalState("customModes", customModes)
|
||||
try {
|
||||
// Load custom modes first
|
||||
const customModes = await provider.customModesManager.getCustomModes()
|
||||
await updateGlobalState("customModes", customModes)
|
||||
|
||||
provider.postStateToWebview()
|
||||
provider.workspaceTracker?.initializeFilePaths() // Don't await.
|
||||
// Ensure state is posted to webview - this is critical for preventing loading screen hang
|
||||
await provider.postStateToWebview()
|
||||
provider.workspaceTracker?.initializeFilePaths() // Don't await.
|
||||
|
||||
getTheme().then((theme) => provider.postMessageToWebview({ type: "theme", text: JSON.stringify(theme) }))
|
||||
getTheme().then((theme) =>
|
||||
provider.postMessageToWebview({ type: "theme", text: JSON.stringify(theme) }),
|
||||
)
|
||||
} catch (error) {
|
||||
provider.log(`Error during webview launch: ${error instanceof Error ? error.message : String(error)}`)
|
||||
// Even if there's an error, try to post state to prevent infinite loading
|
||||
try {
|
||||
await provider.postStateToWebview()
|
||||
} catch (fallbackError) {
|
||||
provider.log(
|
||||
`Fallback state posting also failed: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// If MCP Hub is already initialized, update the webview with
|
||||
// current server list.
|
||||
|
|
|
|||
|
|
@ -350,7 +350,17 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
|
||||
useEffect(() => {
|
||||
vscode.postMessage({ type: "webviewDidLaunch" })
|
||||
}, [])
|
||||
|
||||
// Set a timeout to prevent infinite loading if state message is never received
|
||||
const loadingTimeout = setTimeout(() => {
|
||||
if (!didHydrateState) {
|
||||
console.warn("Webview state hydration timeout - forcing hydration to prevent infinite loading")
|
||||
setDidHydrateState(true)
|
||||
}
|
||||
}, 10000) // 10 second timeout
|
||||
|
||||
return () => clearTimeout(loadingTimeout)
|
||||
}, [didHydrateState])
|
||||
|
||||
const contextValue: ExtensionStateContextType = {
|
||||
...state,
|
||||
|
|
|
|||
|
|
@ -244,4 +244,33 @@ describe("mergeExtensionState", () => {
|
|||
multiFileApplyDiff: true,
|
||||
})
|
||||
})
|
||||
|
||||
it("forces hydration after timeout when state message is never received", async () => {
|
||||
// Mock timers to control timeout behavior
|
||||
vi.useFakeTimers()
|
||||
|
||||
const TestTimeoutComponent = () => {
|
||||
const { didHydrateState } = useExtensionState()
|
||||
return <div data-testid="hydration-state">{didHydrateState.toString()}</div>
|
||||
}
|
||||
|
||||
render(
|
||||
<ExtensionStateContextProvider>
|
||||
<TestTimeoutComponent />
|
||||
</ExtensionStateContextProvider>,
|
||||
)
|
||||
|
||||
// Initially should not be hydrated
|
||||
expect(screen.getByTestId("hydration-state").textContent).toBe("false")
|
||||
|
||||
// Fast-forward time by 10 seconds (the timeout duration)
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(10000)
|
||||
})
|
||||
|
||||
// Should now be hydrated due to timeout
|
||||
expect(screen.getByTestId("hydration-state").textContent).toBe("true")
|
||||
|
||||
vi.useRealTimers()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue