From 47e1030d66327044532e3e062d62b6716732da3d Mon Sep 17 00:00:00 2001 From: variablevince <24507472+VariableVince@users.noreply.github.com> Date: Sat, 24 Jan 2026 18:12:10 +0100 Subject: [PATCH 1/5] Fix confirmation for back button not working on mobile and in spawn phase and before first click after spawn phase --- src/client/ClientGameRunner.ts | 8 ++++++-- src/client/Main.ts | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts index bd377d35d9..8fbb152d97 100644 --- a/src/client/ClientGameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -281,12 +281,16 @@ export class ClientGameRunner { * the window or navigate away during an active game session. * * @returns {boolean} `true` if the window close should be prevented - * (when the player is alive in the game), `false` otherwise + * (when the player is alive in the game or during spawn phase), `false` otherwise * (when the player is not alive or doesn't exist) */ public shouldPreventWindowClose(): boolean { // Show confirmation dialog if player is alive in the game - return !!this.myPlayer?.isAlive(); + // gameView, not this.myPlayer, so it works before 1st click after spawn phase too + return ( + (this.gameView.myPlayer()?.isAlive() ?? false) || + this.gameView.inSpawnPhase() + ); } private async saveGame(update: WinUpdate) { diff --git a/src/client/Main.ts b/src/client/Main.ts index 8858b2f43f..f761a1239e 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -599,13 +599,14 @@ class Client { if (!this.gameStop()) { console.info("Player is active, ask before leaving game"); + // Rollback navigator history (here so the confirm dialog also works on mobile) + history.pushState(null, "", this.currentUrl); + const isConfirmed = confirm( translateText("help_modal.exit_confirmation"), ); if (!isConfirmed) { - // Rollback navigator history - history.pushState(null, "", this.currentUrl); return; } } From bcd4e21c8f3e434113002a1c721cda4d0f60a98c Mon Sep 17 00:00:00 2001 From: variablevince <24507472+VariableVince@users.noreply.github.com> Date: Sat, 24 Jan 2026 20:17:12 +0100 Subject: [PATCH 2/5] Prevent navigation back to homepage on repeated back button click --- src/client/Main.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/client/Main.ts b/src/client/Main.ts index f761a1239e..155a918a52 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -599,14 +599,22 @@ class Client { if (!this.gameStop()) { console.info("Player is active, ask before leaving game"); - // Rollback navigator history (here so the confirm dialog also works on mobile) - history.pushState(null, "", this.currentUrl); + // Rollback navigator history to stay in game on cancel + // Before calling confirm so dialog also shows on mobile + history.replaceState(null, "", this.currentUrl); const isConfirmed = confirm( translateText("help_modal.exit_confirmation"), ); if (!isConfirmed) { + // Rebuild stack: + // - prevent being put back homepage when clicking back button again after cancelling + // - replaceState instead of 2x pushState for cleaner history + // Can't prevent browser blocking popState on clicking back button again without in-game click first + // - preventable by only having pushState this.currentUrl here, which breaks confirm on mobile + history.replaceState(null, "", window.location.origin + "#refresh"); + history.pushState(null, "", this.currentUrl); return; } } From 7db746b2c01eab25478460d70163359bd5ba33a4 Mon Sep 17 00:00:00 2001 From: variablevince <24507472+VariableVince@users.noreply.github.com> Date: Sat, 24 Jan 2026 20:33:17 +0100 Subject: [PATCH 3/5] Type and remove old redundant comment --- src/client/ClientGameRunner.ts | 1 - src/client/Main.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts index 8fbb152d97..aed695dc79 100644 --- a/src/client/ClientGameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -285,7 +285,6 @@ export class ClientGameRunner { * (when the player is not alive or doesn't exist) */ public shouldPreventWindowClose(): boolean { - // Show confirmation dialog if player is alive in the game // gameView, not this.myPlayer, so it works before 1st click after spawn phase too return ( (this.gameView.myPlayer()?.isAlive() ?? false) || diff --git a/src/client/Main.ts b/src/client/Main.ts index 155a918a52..e14e706b70 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -609,7 +609,7 @@ class Client { if (!isConfirmed) { // Rebuild stack: - // - prevent being put back homepage when clicking back button again after cancelling + // - prevent being put back to homepage when clicking back button again after cancelling // - replaceState instead of 2x pushState for cleaner history // Can't prevent browser blocking popState on clicking back button again without in-game click first // - preventable by only having pushState this.currentUrl here, which breaks confirm on mobile From 54790ecf65dde4bf00ad65af1ca7b751b51db775 Mon Sep 17 00:00:00 2001 From: variablevince <24507472+VariableVince@users.noreply.github.com> Date: Sat, 24 Jan 2026 20:55:49 +0100 Subject: [PATCH 4/5] Test for mobile repeated click on back button.. --- src/client/Main.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/client/Main.ts b/src/client/Main.ts index e14e706b70..e3f140464e 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -601,6 +601,7 @@ class Client { // Rollback navigator history to stay in game on cancel // Before calling confirm so dialog also shows on mobile + history.replaceState(null, "", window.location.origin + "#refresh"); history.replaceState(null, "", this.currentUrl); const isConfirmed = confirm( @@ -613,8 +614,8 @@ class Client { // - replaceState instead of 2x pushState for cleaner history // Can't prevent browser blocking popState on clicking back button again without in-game click first // - preventable by only having pushState this.currentUrl here, which breaks confirm on mobile - history.replaceState(null, "", window.location.origin + "#refresh"); - history.pushState(null, "", this.currentUrl); + // history.replaceState(null, "", window.location.origin + "#refresh"); + // history.pushState(null, "", this.currentUrl); return; } } From d7a4bc557486b828cf42fb0d09132552291321c6 Mon Sep 17 00:00:00 2001 From: variablevince <24507472+VariableVince@users.noreply.github.com> Date: Sat, 24 Jan 2026 21:14:10 +0100 Subject: [PATCH 5/5] Test --- src/client/Main.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/Main.ts b/src/client/Main.ts index e3f140464e..e7a25f7c49 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -601,8 +601,8 @@ class Client { // Rollback navigator history to stay in game on cancel // Before calling confirm so dialog also shows on mobile - history.replaceState(null, "", window.location.origin + "#refresh"); - history.replaceState(null, "", this.currentUrl); + history.pushState(null, "", window.location.origin + "#refresh"); + history.pushState(null, "", this.currentUrl); const isConfirmed = confirm( translateText("help_modal.exit_confirmation"),