mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
fix: add loading screen and retry logic to prevent webview lockup on startup
- Created LoadingScreen component to show proper loading state instead of blank screen - Added timeout handling to show message when loading takes longer than expected - Implemented retry logic in App and ExtensionStateContext to resend initialization message - Changed App to render LoadingScreen instead of null when waiting for state hydration This fixes the issue where the webview would show a blank screen indefinitely if the extension was slow to respond with the initial state. Fixes #6234
This commit is contained in:
parent
0504199ce4
commit
1f0ab5e5dc
3 changed files with 60 additions and 2 deletions
|
|
@ -25,6 +25,7 @@ import { AccountView } from "./components/account/AccountView"
|
|||
import { useAddNonInteractiveClickListener } from "./components/ui/hooks/useNonInteractiveClick"
|
||||
import { TooltipProvider } from "./components/ui/tooltip"
|
||||
import { STANDARD_TOOLTIP_DELAY } from "./components/ui/standard-tooltip"
|
||||
import { LoadingScreen } from "./components/common/LoadingScreen"
|
||||
|
||||
type Tab = "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "account"
|
||||
|
||||
|
|
@ -81,6 +82,7 @@ const App = () => {
|
|||
|
||||
const [showAnnouncement, setShowAnnouncement] = useState(false)
|
||||
const [tab, setTab] = useState<Tab>("chat")
|
||||
const [showTimeout, setShowTimeout] = useState(false)
|
||||
|
||||
const [humanRelayDialogState, setHumanRelayDialogState] = useState<HumanRelayDialogState>({
|
||||
isOpen: false,
|
||||
|
|
@ -207,6 +209,27 @@ const App = () => {
|
|||
console.debug("App initialized with source map support")
|
||||
}, [])
|
||||
|
||||
// Add timeout handling for extension state
|
||||
useEffect(() => {
|
||||
if (!didHydrateState) {
|
||||
// Show timeout message after 5 seconds
|
||||
const timeoutTimer = setTimeout(() => {
|
||||
setShowTimeout(true)
|
||||
}, 5000)
|
||||
|
||||
// Retry sending webviewDidLaunch after 3 seconds
|
||||
const retryTimer = setTimeout(() => {
|
||||
console.debug("Retrying webviewDidLaunch message...")
|
||||
vscode.postMessage({ type: "webviewDidLaunch" })
|
||||
}, 3000)
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeoutTimer)
|
||||
clearTimeout(retryTimer)
|
||||
}
|
||||
}
|
||||
}, [didHydrateState])
|
||||
|
||||
// Focus the WebView when non-interactive content is clicked (only in editor/tab mode)
|
||||
useAddNonInteractiveClickListener(
|
||||
useCallback(() => {
|
||||
|
|
@ -224,7 +247,7 @@ const App = () => {
|
|||
}, [tab])
|
||||
|
||||
if (!didHydrateState) {
|
||||
return null
|
||||
return <LoadingScreen showTimeout={showTimeout} />
|
||||
}
|
||||
|
||||
// Do not conditionally load ChatView, it's expensive and there's state we
|
||||
|
|
|
|||
24
webview-ui/src/components/common/LoadingScreen.tsx
Normal file
24
webview-ui/src/components/common/LoadingScreen.tsx
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import React from "react"
|
||||
import { VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
interface LoadingScreenProps {
|
||||
message?: string
|
||||
showTimeout?: boolean
|
||||
}
|
||||
|
||||
export const LoadingScreen: React.FC<LoadingScreenProps> = ({
|
||||
message = "Loading Roo Code...",
|
||||
showTimeout = false,
|
||||
}) => {
|
||||
return (
|
||||
<div className="fixed inset-0 flex flex-col items-center justify-center bg-vscode-editor-background">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<VSCodeProgressRing />
|
||||
<p className="text-vscode-foreground text-sm">{message}</p>
|
||||
{showTimeout && (
|
||||
<p className="text-vscode-descriptionForeground text-xs mt-2">Taking longer than expected...</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -360,8 +360,19 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
}, [handleMessage])
|
||||
|
||||
useEffect(() => {
|
||||
// Send initial launch message
|
||||
vscode.postMessage({ type: "webviewDidLaunch" })
|
||||
}, [])
|
||||
|
||||
// If we don't get a response within 2 seconds, try again
|
||||
const retryTimer = setTimeout(() => {
|
||||
if (!didHydrateState) {
|
||||
console.warn("No state received from extension, retrying webviewDidLaunch...")
|
||||
vscode.postMessage({ type: "webviewDidLaunch" })
|
||||
}
|
||||
}, 2000)
|
||||
|
||||
return () => clearTimeout(retryTimer)
|
||||
}, [didHydrateState])
|
||||
|
||||
const contextValue: ExtensionStateContextType = {
|
||||
...state,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue