Add confirmation on beforeunload during an ongoing game that you're in

This commit is contained in:
Andrio Celos 2023-06-15 22:44:52 +10:00
parent 0906969365
commit 8a9511889b
5 changed files with 41 additions and 2 deletions

View File

@ -3,6 +3,7 @@ let clientToken = window.localStorage.getItem('clientToken') || '';
/** The data of the current game, or null if not in a game. */
let currentGame: {
id: string,
state: GameState,
/** The list of players in the current game. */
players: Player[],
/** The maximum number of players in the game. */

View File

@ -183,7 +183,7 @@ function stopEditingDeck() {
function onBeforeUnload_deckEditor(e: BeforeUnloadEvent) {
e.preventDefault();
return 'You have unsaved changes to your deck that will be lost. Are you sure you want to continue?';
return 'You have unsaved changes to your deck that will be lost.';
}
function addTestStage(stage: Stage) {

View File

@ -130,7 +130,7 @@ function initTest(stage: Stage) {
clear();
testMode = true;
gamePage.classList.add('deckTest');
currentGame = { id: 'test', maxPlayers: 2, players: [ ], webSocket: null, turnNumber: 1, turnTimeLimit: null, turnTimeLeft: null, me: { playerIndex: 0, move: null, deck: null, hand: null, cardsUsed: [ ] } };
currentGame = { id: 'test', state: GameState.Ongoing, maxPlayers: 2, players: [ ], webSocket: null, turnNumber: 1, turnTimeLimit: null, turnTimeLeft: null, me: { playerIndex: 0, move: null, deck: null, hand: null, cardsUsed: [ ] } };
board.resize(stage.copyGrid());
const startSpaces = stage.getStartSpaces(2);
board.startSpaces = startSpaces;

View File

@ -312,6 +312,7 @@ function loadReplay(base64: string) {
currentGame = {
id: 'replay',
state: GameState.Redraw,
me: null,
players: players,
maxPlayers: numPlayers,

View File

@ -14,6 +14,7 @@ const decks: Deck[] = [ new Deck('Starter Deck', [ 6, 34, 159, 13, 45, 137, 22,
let selectedDeck: Deck | null = null;
let editingDeck = false;
let deckModified = false;
let shouldConfirmLeavingGame = false;
function delay(ms: number, abortSignal?: AbortSignal) {
return new Promise((resolve, reject) => {
@ -92,6 +93,8 @@ function onGameStateChange(game: any, playerData: PlayerData | null) {
if (currentGame == null)
throw new Error('currentGame is null');
clearPlayContainers();
currentGame.state = game.state;
if (game.board) {
board.flip = playerData != null && playerData.playerIndex % 2 != 0;
if (board.flip) gamePage.classList.add('boardFlipped');
@ -109,11 +112,13 @@ function onGameStateChange(game: any, playerData: PlayerData | null) {
switch (game.state) {
case GameState.WaitingForPlayers:
showPage('lobby');
clearConfirmLeavingGame();
lobbySelectedStageSection.hidden = true;
lobbyStageSection.hidden = !playerData || game.players[playerData.playerIndex]?.isReady;
break;
case GameState.Preparing:
showPage('lobby');
if (currentGame.me) setConfirmLeavingGame();
if (selectedStageButton)
lobbySelectedStageSection.removeChild(selectedStageButton.element);
selectedStageButton = new StageButton(stageDatabase.stages?.find(s => s.name == game.stage)!);
@ -142,6 +147,7 @@ function onGameStateChange(game: any, playerData: PlayerData | null) {
switch (game.state) {
case GameState.Redraw:
if (currentGame.me) setConfirmLeavingGame();
redrawModal.hidden = currentGame.me == null || currentGame.players[currentGame.me.playerIndex].isReady;
turnNumberLabel.setTurnNumber(null);
canPlay = false;
@ -149,6 +155,7 @@ function onGameStateChange(game: any, playerData: PlayerData | null) {
timeLabel.paused = false;
break;
case GameState.Ongoing:
if (currentGame.me) setConfirmLeavingGame();
turnNumberLabel.setTurnNumber(game.turnNumber);
board.autoHighlight = true;
canPlay = currentGame.me != null && !currentGame.players[currentGame.me.playerIndex].isReady;
@ -157,6 +164,7 @@ function onGameStateChange(game: any, playerData: PlayerData | null) {
setupControlsForPlay();
break;
case GameState.Ended:
clearConfirmLeavingGame();
gamePage.classList.add('gameEnded');
turnNumberLabel.setTurnNumber(null);
timeLabel.hide();
@ -170,6 +178,7 @@ function onGameStateChange(game: any, playerData: PlayerData | null) {
let errorDialogCallback: ((e: Event) => void) | null = null;
function communicationError(message?: string, showButton?: boolean, callback?: (e: Event) => void) {
clearConfirmLeavingGame();
preGameLoadingSection.hidden = true;
errorMessage.innerText = message ?? 'A communication error has occurred.\nPlease reload the page to rejoin.';
errorDialogCallback = callback ?? null;
@ -218,6 +227,7 @@ function setupWebSocket(gameID: string, myPlayerIndex: number | null) {
} else {
currentGame = {
id: gameID,
state: payload.data.state,
me: payload.playerData,
players: payload.data.players,
maxPlayers: payload.data.maxPlayers,
@ -355,6 +365,8 @@ function setupWebSocket(gameID: string, myPlayerIndex: number | null) {
turnNumberLabel.setTurnNumber(payload.data.game.turnNumber);
clearPlayContainers();
if (payload.event == 'gameEnd') {
currentGame.state = GameState.Ended;
clearConfirmLeavingGame();
gameButtonsContainer.hidden = true;
passButton.enabled = false;
specialButton.enabled = false;
@ -382,17 +394,37 @@ function setupWebSocket(gameID: string, myPlayerIndex: number | null) {
return myPlayerIndex;
}
function setConfirmLeavingGame() {
if (!shouldConfirmLeavingGame) {
shouldConfirmLeavingGame = true;
window.addEventListener('beforeunload', onBeforeUnload_game);
}
}
function clearConfirmLeavingGame() {
if (shouldConfirmLeavingGame) {
shouldConfirmLeavingGame = false;
window.removeEventListener('beforeunload', onBeforeUnload_game);
}
}
function processUrl() {
if (deckModified) {
if (!confirm('You have unsaved changes to your deck. Are you sure you want to leave?')) {
setUrl('deckeditor');
return false;
}
} else if (shouldConfirmLeavingGame) {
if (!confirm('This will disconnect you from a game in progress. Are you sure you want to leave?')) {
setUrl(`game/${currentGame!.id}`);
return false;
}
}
stopEditingDeck();
errorDialog.close();
currentGame = null;
currentReplay = null;
clearConfirmLeavingGame();
if (location.pathname.endsWith('/deckeditor') || location.hash == '#deckeditor')
onInitialise(showDeckList);
else {
@ -417,6 +449,11 @@ function processUrl() {
return true;
}
function onBeforeUnload_game(e: BeforeUnloadEvent) {
e.preventDefault();
return 'This will disconnect you from a game in progress.';
}
function parseGameID(s: string) {
const m = /(?:^|[#/])([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i.exec(s);
return m ? m[1] : null;