From 9996b1bfea5afaec26eb3ed84f215cb0daf8dfe7 Mon Sep 17 00:00:00 2001 From: Petar Petrov Date: Mon, 15 Dec 2025 17:59:57 +0200 Subject: [PATCH] Fix inability to leave scene creation page without saving (#28546) --- src/common/navigate.ts | 55 +++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/src/common/navigate.ts b/src/common/navigate.ts index f6265b43f1..a38e48f35d 100644 --- a/src/common/navigate.ts +++ b/src/common/navigate.ts @@ -17,25 +17,36 @@ export interface NavigateOptions { // max time to wait for dialogs to close before navigating const DIALOG_WAIT_TIMEOUT = 500; -export const navigate = async ( - path: string, - options?: NavigateOptions, - timestamp = Date.now() -) => { +/** + * Ensures all dialogs are closed before navigation. + * Returns true if navigation can proceed, false if a dialog refused to close. + */ +const ensureDialogsClosed = async (timestamp: number): Promise => { const { history } = mainWindow; - if (history.state?.dialog && Date.now() - timestamp < DIALOG_WAIT_TIMEOUT) { - const closed = await closeAllDialogs(); - if (!closed) { - // eslint-disable-next-line no-console - console.warn("Navigation blocked, because dialog refused to close"); - return false; - } - return new Promise((resolve) => { - // need to wait for history state to be updated in case a dialog was closed - setTimeout(() => { - navigate(path, options, timestamp).then(resolve); - }); - }); + + if (!history.state?.dialog || Date.now() - timestamp >= DIALOG_WAIT_TIMEOUT) { + return true; + } + + const closed = await closeAllDialogs(); + if (!closed) { + // eslint-disable-next-line no-console + console.warn("Navigation blocked, because dialog refused to close"); + return false; + } + + // wait for history state to be updated after dialog closed + await new Promise((resolve) => { + setTimeout(resolve); + }); + + return ensureDialogsClosed(timestamp); +}; + +export const navigate = async (path: string, options?: NavigateOptions) => { + const canProceed = await ensureDialogsClosed(Date.now()); + if (!canProceed) { + return false; } const replace = options?.replace || false; @@ -68,10 +79,14 @@ export const navigate = async ( * Navigate back in history, with fallback to a default path if no history exists. * This prevents a user from getting stuck when they navigate directly to a page with no history. */ -export const goBack = (fallbackPath?: string) => { - const { history } = mainWindow; +export const goBack = async (fallbackPath?: string): Promise => { + const canProceed = await ensureDialogsClosed(Date.now()); + if (!canProceed) { + return; + } // Check if we have history to go back to + const { history } = mainWindow; if (history.length > 1) { history.back(); return;