fix(browser): wait for panel surface before capture
This commit is contained in:
@@ -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 }),
|
||||
|
||||
+7
@@ -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())',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user