chore(dev): image loading state in browser tool

This commit is contained in:
Soumyadas15 2025-05-27 10:47:15 +05:30
parent 0cda329161
commit a9f5f64f9d
1 changed files with 71 additions and 4 deletions

View File

@ -124,6 +124,15 @@ export function BrowserToolView({
const isRunning = isStreaming || agentStatus === 'running'; const isRunning = isStreaming || agentStatus === 'running';
const isLastToolCall = currentIndex === totalCalls - 1; const isLastToolCall = currentIndex === totalCalls - 1;
const [isIframeLoading, setIsIframeLoading] = React.useState(true);
// Reset loading state when VNC URL changes
React.useEffect(() => {
if (vncPreviewUrl) {
setIsIframeLoading(true);
}
}, [vncPreviewUrl]);
const vncIframe = useMemo(() => { const vncIframe = useMemo(() => {
if (!vncPreviewUrl) return null; if (!vncPreviewUrl) return null;
@ -133,6 +142,7 @@ export function BrowserToolView({
title="Browser preview" title="Browser preview"
className="w-full h-full border-0 min-h-[600px]" className="w-full h-full border-0 min-h-[600px]"
style={{ width: '100%', height: '100%', minHeight: '600px' }} style={{ width: '100%', height: '100%', minHeight: '600px' }}
onLoad={() => setIsIframeLoading(false)}
/> />
); );
}, [vncPreviewUrl]); }, [vncPreviewUrl]);
@ -157,24 +167,53 @@ export function BrowserToolView({
} }
}, [isRunning]); }, [isRunning]);
const [isScreenshotLoading, setIsScreenshotLoading] = React.useState(true);
// Reset screenshot loading state when screenshot data changes
React.useEffect(() => {
if (screenshotUrl || screenshotBase64) {
setIsScreenshotLoading(true);
}
}, [screenshotUrl, screenshotBase64]);
const renderScreenshot = () => { const renderScreenshot = () => {
if (screenshotUrl) { if (screenshotUrl) {
return ( return (
<div className="flex items-center justify-center w-full h-full min-h-[600px]" style={{ minHeight: '600px' }}> <div className="relative flex items-center justify-center w-full h-full min-h-[600px]" style={{ minHeight: '600px' }}>
{isScreenshotLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-black z-10">
<div className="flex flex-col items-center gap-4">
<CircleDashed className="h-8 w-8 animate-spin text-white" />
<p className="text-white text-sm">Loading screenshot...</p>
</div>
</div>
)}
<img <img
src={screenshotUrl} src={screenshotUrl}
alt="Browser Screenshot" alt="Browser Screenshot"
className="max-w-full max-h-full object-contain" className="max-w-full max-h-full object-contain"
onLoad={() => setIsScreenshotLoading(false)}
onError={() => setIsScreenshotLoading(false)}
/> />
</div> </div>
); );
} else if (screenshotBase64) { } else if (screenshotBase64) {
return ( return (
<div className="flex items-center justify-center w-full h-full min-h-[600px]" style={{ minHeight: '600px' }}> <div className="relative flex items-center justify-center w-full h-full min-h-[600px]" style={{ minHeight: '600px' }}>
{isScreenshotLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-black z-10">
<div className="flex flex-col items-center gap-4">
<CircleDashed className="h-8 w-8 animate-spin text-white" />
<p className="text-white text-sm">Loading screenshot...</p>
</div>
</div>
)}
<img <img
src={`data:image/jpeg;base64,${screenshotBase64}`} src={`data:image/jpeg;base64,${screenshotBase64}`}
alt="Browser Screenshot" alt="Browser Screenshot"
className="max-w-full max-h-full object-contain" className="max-w-full max-h-full object-contain"
onLoad={() => setIsScreenshotLoading(false)}
onError={() => setIsScreenshotLoading(false)}
/> />
</div> </div>
); );
@ -230,6 +269,14 @@ export function BrowserToolView({
isRunning && vncIframe ? ( isRunning && vncIframe ? (
<div className="flex flex-col items-center justify-center w-full h-full min-h-[600px]" style={{ minHeight: '600px' }}> <div className="flex flex-col items-center justify-center w-full h-full min-h-[600px]" style={{ minHeight: '600px' }}>
<div className="relative w-full h-full min-h-[600px]" style={{ minHeight: '600px' }}> <div className="relative w-full h-full min-h-[600px]" style={{ minHeight: '600px' }}>
{isIframeLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-black z-20">
<div className="flex flex-col items-center gap-4">
<CircleDashed className="h-8 w-8 animate-spin text-white" />
<p className="text-white text-sm">Loading browser preview...</p>
</div>
</div>
)}
{vncIframe} {vncIframe}
<div className="absolute top-4 right-4 z-10"> <div className="absolute top-4 right-4 z-10">
<Badge className="bg-blue-500/90 text-white border-none shadow-lg animate-pulse"> <Badge className="bg-blue-500/90 text-white border-none shadow-lg animate-pulse">
@ -243,7 +290,15 @@ export function BrowserToolView({
renderScreenshot() renderScreenshot()
) : vncIframe ? ( ) : vncIframe ? (
// Use the memoized iframe // Use the memoized iframe
<div className="flex flex-col items-center justify-center w-full h-full min-h-[600px]" style={{ minHeight: '600px' }}> <div className="relative flex flex-col items-center justify-center w-full h-full min-h-[600px]" style={{ minHeight: '600px' }}>
{isIframeLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-black z-10">
<div className="flex flex-col items-center gap-4">
<CircleDashed className="h-8 w-8 animate-spin text-white" />
<p className="text-white text-sm">Loading browser preview...</p>
</div>
</div>
)}
{vncIframe} {vncIframe}
</div> </div>
) : ( ) : (
@ -273,18 +328,30 @@ export function BrowserToolView({
) )
) : // For non-last tool calls, only show screenshot if available, otherwise show "No Browser State" ) : // For non-last tool calls, only show screenshot if available, otherwise show "No Browser State"
(screenshotUrl || screenshotBase64) ? ( (screenshotUrl || screenshotBase64) ? (
<div className="flex items-center justify-center w-full h-full max-h-[650px] overflow-auto"> <div className="relative flex items-center justify-center w-full h-full max-h-[650px] overflow-auto">
{isScreenshotLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-black z-10">
<div className="flex flex-col items-center gap-4">
<CircleDashed className="h-8 w-8 animate-spin text-white" />
<p className="text-white text-sm">Loading screenshot...</p>
</div>
</div>
)}
{screenshotUrl ? ( {screenshotUrl ? (
<img <img
src={screenshotUrl} src={screenshotUrl}
alt="Browser Screenshot" alt="Browser Screenshot"
className="max-w-full max-h-full object-contain" className="max-w-full max-h-full object-contain"
onLoad={() => setIsScreenshotLoading(false)}
onError={() => setIsScreenshotLoading(false)}
/> />
) : ( ) : (
<img <img
src={`data:image/jpeg;base64,${screenshotBase64}`} src={`data:image/jpeg;base64,${screenshotBase64}`}
alt="Browser Screenshot" alt="Browser Screenshot"
className="max-w-full max-h-full object-contain" className="max-w-full max-h-full object-contain"
onLoad={() => setIsScreenshotLoading(false)}
onError={() => setIsScreenshotLoading(false)}
/> />
)} )}
</div> </div>