-
Notifications
You must be signed in to change notification settings - Fork 786
Fix: confirmation for back button not working on mobile and in spawn p… #3015
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…hase and before first click after spawn phase
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/client/Main.ts (1)
595-611: Preventhashchangeevent after canceled back button in active game.When user presses back with an active game and cancels the confirmation,
pushStateat line 602 can trigger ahashchangeevent, which runsonHashUpdate→onJoinChanged→handleLeaveLobby, defeating the cancel. Add a simple guard flag to prevent this race condition.Proposed fix
const onHashUpdate = () => { + if (preventHashUpdate) { + preventHashUpdate = false; + return; + } // Reset the UI to its initial state this.joinModal?.close(); onJoinChanged(); }; const onPopState = () => { if (this.currentUrl !== null && this.gameStop !== null) { console.info("Game is active"); if (!this.gameStop()) { console.info("Player is active, ask before leaving game"); // Rollback navigator history (here so the confirm dialog also works on mobile) + preventHashUpdate = true; history.pushState(null, "", this.currentUrl); const isConfirmed = confirm( translateText("help_modal.exit_confirmation"), ); if (!isConfirmed) { return; }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/client/Main.ts (1)
595-618: Add a guard flag to prevent hashchange after canceling back navigationWhen the user cancels leaving the game, the history manipulation triggers a hashchange event that executes onHashUpdate and calls
onJoinChanged(), which can exit the game despite the user canceling. Use a flag to skip the next hashchange when canceling, matching the previous implementation pattern.🔧 Suggested fix
+ let preventHashUpdate = false; + const onHashUpdate = () => { + if (preventHashUpdate) { + preventHashUpdate = false; + return; + } // Reset the UI to its initial state this.joinModal?.close(); onJoinChanged(); }; const onPopState = () => { if (this.currentUrl !== null && this.gameStop !== null) { console.info("Game is active"); if (!this.gameStop()) { console.info("Player is active, ask before leaving game"); + preventHashUpdate = true; // 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 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 history.replaceState(null, "", window.location.origin + "#refresh"); history.pushState(null, "", this.currentUrl); return; }
|
Points 2 and maybe 3 are by design and consistency with the exit button: you need to confirm the action only if you are active in the game. Otherwise, exit immediately. |
| // Rollback navigator history to stay in game on cancel | ||
| // Before calling confirm so dialog also shows on mobile | ||
| history.pushState(null, "", window.location.origin + "#refresh"); | ||
| history.pushState(null, "", this.currentUrl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm not mistaken, you are rolling navigation back even if the user confirms he wants to exit the game.
Am I right?
|
Nevermind, I think I got your point |
Description:
Fix for v29. PR #2397 added confirmation dialog on browser back button, back to v29. However the confirm dialog wasn't working in three cases: 1) not displayed on mobile, you were instead directly returned to the main page. 2) Also the dialog wasn't shown during spawn phase and 3) not shown directly after spawn phase before first click on the map.
This PR fixes all three issues. The confirm dialog is still only shown during a game, not elsewhere.
But this PR introduces one small unpreventable edge case regression. This is explained in the code comments. On back button click, then cancel, then back button click again, browser can block popState event for user safety. So nothing happens on repeated back button clicks on desktop and on mobile the browser back button is greyed out/blocked.
But after user then clicks somewhere on the page, the back button triggers popState and thus the confirm modal again.
Only way to prevent popState blocking by the browser was the previous way of doing it; only have pushState after !isConfirmed, but that breaks the confirm dialog on mobile. Also this edge case isn't something the average user will notice, normally they won't click the back button right away after first clicking it and then cancelling it. They'll do some clicks playing the game before deciding to click the back button again, which prevents popState from being blocked by the browser. And the better way to leave a game is still the Exit button in the top right so they'll have a way out even when the browser blocks the back button temporarily.
BEFORE:
https://github.com/user-attachments/assets/90a01887-59cf-436a-91a3-3f617cf8a89e
AFTER:
https://github.com/user-attachments/assets/7c3c340e-2bd6-4785-8bbf-ba0705a5940c
Please complete the following:
Please put your Discord username so you can be contacted if a bug or regression is found:
tryout33