From 749b0a3dfcf702cd79726ba13ce7a91558890160 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 31 Mar 2026 22:13:17 +0000 Subject: [PATCH 1/2] fix: queue/setup loading Cancel above StreamView and abort launch cleanly Raise StreamLoading z-index above StreamView so Cancel receives clicks. Add launch abort ref: cancel during queue/setup skips exit dialog, sets abort before stopSession, and exits the poll loop without duplicate cleanup. Co-authored-by: Zortos --- opennow-stable/src/renderer/src/App.tsx | 21 +++++++++++++++++++++ opennow-stable/src/renderer/src/styles.css | 3 ++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/opennow-stable/src/renderer/src/App.tsx b/opennow-stable/src/renderer/src/App.tsx index 0be7fd6..5932f46 100644 --- a/opennow-stable/src/renderer/src/App.tsx +++ b/opennow-stable/src/renderer/src/App.tsx @@ -648,6 +648,7 @@ export function App(): JSX.Element { const hasInitializedRef = useRef(false); const regionsRequestRef = useRef(0); const launchInFlightRef = useRef(false); + const launchAbortRef = useRef(false); const streamStatusRef = useRef(streamStatus); const exitPromptResolverRef = useRef<((confirmed: boolean) => void) | null>(null); @@ -1552,6 +1553,7 @@ export function App(): JSX.Element { } launchInFlightRef.current = true; + launchAbortRef.current = false; let loadingStep: StreamLoadingStatus = "queue"; const updateLoadingStep = (next: StreamLoadingStatus): void => { loadingStep = next; @@ -1674,6 +1676,10 @@ export function App(): JSX.Element { attempt++; await sleep(SESSION_READY_POLL_INTERVAL_MS); + if (launchAbortRef.current) { + return; + } + const polled = await window.openNow.pollSession({ token: token || undefined, streamingBaseUrl: newSession.streamingBaseUrl ?? effectiveStreamingBaseUrl, @@ -1684,6 +1690,10 @@ export function App(): JSX.Element { deviceId: newSession.deviceId, }); + if (launchAbortRef.current) { + return; + } + setSession(polled); setQueuePosition(polled.queuePosition); @@ -1821,6 +1831,10 @@ export function App(): JSX.Element { const handleStopStream = useCallback(async () => { try { resolveExitPrompt(false); + const status = streamStatusRef.current; + if (status !== "idle" && status !== "streaming") { + launchAbortRef.current = true; + } await window.openNow.disconnectSignaling(); const current = sessionRef.current; @@ -1922,6 +1936,13 @@ export function App(): JSX.Element { await releasePointerLockIfNeeded(); + const loadingPhases: StreamStatus[] = ["queue", "setup", "starting", "connecting"]; + if (loadingPhases.includes(streamStatus)) { + launchAbortRef.current = true; + await handleStopStream(); + return; + } + const gameName = (streamingGame?.title || "this game").trim(); const shouldExit = await requestExitPrompt(gameName); if (!shouldExit) { diff --git a/opennow-stable/src/renderer/src/styles.css b/opennow-stable/src/renderer/src/styles.css index 0550169..709a4bf 100644 --- a/opennow-stable/src/renderer/src/styles.css +++ b/opennow-stable/src/renderer/src/styles.css @@ -4068,7 +4068,8 @@ button.game-card-store-chip.active:hover { .sload { position: fixed; inset: 0; - z-index: 1000; + /* Above StreamView (.sv, z-index 1000) so queue/setup Cancel receives clicks */ + z-index: 1100; display: flex; align-items: center; justify-content: center; From dd5a1a7cbc0084d3a88e07e0b2321a1f2e811dea Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 1 Apr 2026 07:53:03 +0000 Subject: [PATCH 2/2] Fix launch cancel path to suppress abort errors Co-authored-by: Zortos --- opennow-stable/src/renderer/src/App.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opennow-stable/src/renderer/src/App.tsx b/opennow-stable/src/renderer/src/App.tsx index 5932f46..b26e9ba 100644 --- a/opennow-stable/src/renderer/src/App.tsx +++ b/opennow-stable/src/renderer/src/App.tsx @@ -1748,6 +1748,9 @@ export function App(): JSX.Element { signalingUrl: sessionToConnect.signalingUrl, }); } catch (error) { + if (launchAbortRef.current) { + return; + } console.error("Launch failed:", error); setLaunchError(toLaunchErrorState(error, loadingStep)); await window.openNow.disconnectSignaling().catch(() => {});