From 9856f510126aac4cb835f8a3e250ffb2af861c7a Mon Sep 17 00:00:00 2001 From: Jakub Gonet Date: Fri, 5 Apr 2024 14:42:27 +0200 Subject: [PATCH] Fix stream closing when computer sleeps (#67) We use `` tag to display MJPEG stream of simulator frames. It appears that after computer goes to sleep, connection between `` and simulator server is dropped. This change periodically tries to check if `` contents is decodable and if not, remounts the image to establish a new connection. Note: there's similar problem with Vite HMR server. It's easier to test this change by using production build. Ref: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decode Fixes #41. --- .../src/webview/components/Preview.tsx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/packages/vscode-extension/src/webview/components/Preview.tsx b/packages/vscode-extension/src/webview/components/Preview.tsx index 9d693a8aa..ccd9fc1ba 100644 --- a/packages/vscode-extension/src/webview/components/Preview.tsx +++ b/packages/vscode-extension/src/webview/components/Preview.tsx @@ -44,6 +44,9 @@ function Preview({ isInspecting, setIsInspecting }: Props) { const [isPressing, setIsPressing] = useState(false); const previewRef = useRef(null); + // used for reestablishing connection to mjpeg stream + const [previewRefreshKey, setPreviewRefreshKey] = useState(0); + const { projectState, project } = useProject(); const hasBuildError = projectState?.status === "buildError"; @@ -55,6 +58,27 @@ function Preview({ isInspecting, setIsInspecting }: Props) { const previewURL = projectState?.previewURL; + useEffect(() => { + let timer: NodeJS.Timeout; + + async function checkIfImageLoaded() { + try { + if (previewRef.current !== null && previewURL !== undefined) { + // waits until image is ready to be displayed + await previewRef.current.decode(); + } + } catch { + // Stream connection was dropped + setPreviewRefreshKey((previousKey) => previousKey + 1); + } finally { + timer = setTimeout(checkIfImageLoaded, 2_000); + } + } + checkIfImageLoaded(); + + return () => clearTimeout(timer); + }, [previewURL, previewRef]); + const isStarting = hasBundleError || hasIncrementalBundleError || debugException ? false @@ -189,6 +213,7 @@ function Preview({ isInspecting, setIsInspecting }: Props) { {!isStarting && !hasBuildError && (