fix(browser): wait for panel surface before capture

This commit is contained in:
Bohdan Triapitsyn
2026-08-28 20:08:58 +03:00
parent 4e857b7877
commit e00ebea262
2 changed files with 27 additions and 1 deletions
@@ -339,6 +339,25 @@ const WebviewBrowser: React.FC<BrowserPaneProps> = ({ initialUrl, directory, tab
}
if (action === 'browser.capture') {
// A user may close the panel after browser.open. Chromium then removes
// the zero-width webview's composited surface and capturePage() fails
// with UnknownVizError. Reveal this existing browser tab again and let
// the layout paint before asking Electron for the image.
useUIStore.getState().openContextBrowser(directory, webview.getURL());
const surfaceDeadline = Date.now() + 1_200;
let previousWidth = 0;
let stableSamples = 0;
while (stableSamples < 2 && Date.now() < surfaceDeadline) {
const width = webview.getBoundingClientRect().width;
stableSamples = width >= 2 && Math.abs(width - previousWidth) < 0.5
? stableSamples + 1
: 0;
previousWidth = width;
await new Promise((resolve) => setTimeout(resolve, 50));
}
await new Promise<void>((resolve) => {
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
});
// Wait for a settled page first: a screenshot of a half-painted layout is
// worse than none, because it looks like a finished one.
await waitForIdle();
@@ -450,7 +469,7 @@ const WebviewBrowser: React.FC<BrowserPaneProps> = ({ initialUrl, directory, tab
await waitForIdle();
}
return result;
}, [annotationHost, loadUrl, waitForIdle]);
}, [annotationHost, directory, loadUrl, waitForIdle]);
React.useEffect(
() => registerBrowserController({ run: runControlAction }),
@@ -15,6 +15,7 @@ import { useUIStore } from '@/stores/useUIStore';
const __dirname = dirname(fileURLToPath(import.meta.url));
const contextPanelSource = readFileSync(join(__dirname, '..', 'ContextPanel.tsx'), 'utf-8');
const browserPaneSource = readFileSync(join(__dirname, '..', '..', 'browser', 'BrowserPane.tsx'), 'utf-8');
const DIRECTORY = '/path/to/repository';
beforeEach(() => {
@@ -40,4 +41,10 @@ describe('issue #3175 browser capture while the context panel is closed', () =>
expect(panel.tabs[0]?.mode).toBe('browser');
expect(panel.tabs[0]?.targetPath).toBe('https://example.com');
});
test('reveals the browser again if it was closed before capture', () => {
expect(browserPaneSource).toContain(
'openContextBrowser(directory, webview.getURL())',
);
});
});