-
Notifications
You must be signed in to change notification settings - Fork 78
Prevent misclicks #762
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
Prevent misclicks #762
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,93 +1,79 @@ | ||
| function redButtonFunction() { | ||
| console.log('red'); | ||
| // if the button isn't disabled | ||
| if ( | ||
| document.querySelector('#red-button').classList.contains('disabled') === | ||
| false | ||
| ) { | ||
| if (isSpectator === true) { | ||
| } else if (gameStarted === false) { | ||
| // if we are spectating | ||
| if (document.querySelector('#red-button').innerText === 'Spectate') { | ||
| socket.emit('standUpFromGame'); | ||
| // remove claim status when a player sits down | ||
| // then stands up | ||
| socket.emit('setClaim', false); | ||
|
|
||
| enableDisableButtons(); | ||
| } | ||
| // we are the host, open kick menu | ||
| else { | ||
| // host kicking | ||
| // Set the kick modal content | ||
| let str = '<h4>Select the players you want to kick.</h4>'; | ||
|
|
||
| str += '<div class="btn-group-vertical" data-toggle="buttons">'; | ||
|
|
||
| for (let i = 0; i < roomPlayersData.length; i++) { | ||
| if (ownUsername !== roomPlayersData[i].username) { | ||
| str += '<label class="btn btn-mine">'; | ||
|
|
||
| str += `<input name="${roomPlayersData[i].username}" id="${roomPlayersData[i].username}" type="checkbox" autocomplete="off">${roomPlayersData[i].username}`; | ||
|
|
||
| str += '</label>'; | ||
| str += '<br>'; | ||
| } else { | ||
| str += '<label class="btn btn-mine" style="display: none;">'; | ||
|
|
||
| str += `<input name="${roomPlayersData[i].username}" id="${roomPlayersData[i].username}" type="checkbox" autocomplete="off">${roomPlayersData[i].username}`; | ||
| async function redButtonFunction() { | ||
| if (document.querySelector('#red-button').classList.contains('disabled') === true) { | ||
| return; | ||
| } | ||
|
|
||
| str += '</label>'; | ||
| str += '<br>'; | ||
| } | ||
| if (isSpectator === true) { | ||
| } else if (gameStarted === false) { | ||
| // non-host player standing up | ||
| if (document.querySelector('#red-button').innerText === 'Spectate') { | ||
| socket.emit('standUpFromGame'); | ||
| socket.emit('setClaim', false); | ||
| enableDisableButtons(); | ||
| } | ||
| // host opening kick menu | ||
| else { | ||
| let str = '<h4>Select the players you want to kick.</h4>'; | ||
| str += '<div class="btn-group-vertical" data-toggle="buttons">'; | ||
| for (let i = 0; i < roomPlayersData.length; i++) { | ||
| if (ownUsername !== roomPlayersData[i].username) { | ||
| str += '<label class="btn btn-mine">'; | ||
| str += `<input name="${roomPlayersData[i].username}" id="${roomPlayersData[i].username}" type="checkbox" autocomplete="off">${roomPlayersData[i].username}`; | ||
| str += '</label>'; | ||
| str += '<br>'; | ||
| } else { | ||
| str += '<label class="btn btn-mine" style="display: none;">'; | ||
| str += `<input name="${roomPlayersData[i].username}" id="${roomPlayersData[i].username}" type="checkbox" autocomplete="off">${roomPlayersData[i].username}`; | ||
| str += '</label>'; | ||
| str += '<br>'; | ||
| } | ||
|
|
||
| str += '</div>'; | ||
|
|
||
| $('#kickModalContent')[0].innerHTML = str; | ||
| } | ||
| } else if ( | ||
| gameData.phase === 'VotingTeam' || | ||
| gameData.phase === 'VotingMission' | ||
| ) { | ||
| socket.emit('gameMove', ['no', []]); | ||
| str += '</div>'; | ||
| $('#kickModalContent')[0].innerHTML = str; | ||
| } | ||
| $('#mainRoomBox div').removeClass('highlight-avatar'); | ||
| } else if ( | ||
| gameData.phase === 'VotingTeam' && | ||
| !(await preventMisclick('no')) | ||
| ) { | ||
| socket.emit('gameMove', ['no', []]); | ||
| } else if (gameData.phase === 'VotingMission') { | ||
| socket.emit('gameMove', ['no', []]); | ||
| } | ||
|
|
||
| $('#mainRoomBox div').removeClass('highlight-avatar'); | ||
| } | ||
|
|
||
| function greenButtonFunction() { | ||
| // if button isn't disabled: | ||
| if ( | ||
| document.querySelector('#green-button').classList.contains('disabled') === | ||
| false | ||
| ) { | ||
| if (isSpectator === true) { | ||
| socket.emit('join-game', roomId); | ||
| } else if (gameStarted === false) { | ||
| const startGameData = { | ||
| options: getOptions(), | ||
| gameMode: $($('.gameModeSelect')[1]).val(), | ||
| timeouts: { | ||
| default: ((parseInt($('#startGameOptionsDefaultPhaseTimeoutMin').val()) * 60 + parseInt($('#startGameOptionsDefaultPhaseTimeoutSec').val())) * 1000).toString(), | ||
| critMission: ((parseInt($('#startGameOptionsCritMissionTimeoutMin').val()) * 60 + parseInt($('#startGameOptionsCritMissionTimeoutSec').val())) * 1000).toString(), | ||
| assassination: ((parseInt($('#startGameOptionsAssassinationPhaseTimeoutMin').val()) * 60 + parseInt($('#startGameOptionsAssassinationPhaseTimeoutSec').val())) * 1000).toString(), | ||
| }, | ||
| anonymousMode: $('#startGameOptionsAnonymousMode')[0].checked, | ||
| }; | ||
|
|
||
| socket.emit('startGame', startGameData); | ||
| } else if ( | ||
| gameData.phase === 'VotingTeam' || | ||
| gameData.phase === 'VotingMission' | ||
| ) { | ||
| socket.emit('gameMove', ['yes', []]); | ||
| } else { | ||
| socket.emit('gameMove', ['yes', getHighlightedAvatars()]); | ||
| } | ||
| async function greenButtonFunction() { | ||
| if (document.querySelector('#green-button').classList.contains('disabled') === true) { | ||
| return; | ||
| } | ||
|
|
||
| $('#mainRoomBox div').removeClass('highlight-avatar'); | ||
| if (isSpectator === true) { | ||
| socket.emit('join-game', roomId); | ||
| } else if (gameStarted === false) { | ||
| const startGameData = { | ||
| options: getOptions(), | ||
| gameMode: $($('.gameModeSelect')[1]).val(), | ||
| timeouts: { | ||
| default: ((parseInt($('#startGameOptionsDefaultPhaseTimeoutMin').val()) * 60 + parseInt($('#startGameOptionsDefaultPhaseTimeoutSec').val())) * 1000).toString(), | ||
| critMission: ((parseInt($('#startGameOptionsCritMissionTimeoutMin').val()) * 60 + parseInt($('#startGameOptionsCritMissionTimeoutSec').val())) * 1000).toString(), | ||
| assassination: ((parseInt($('#startGameOptionsAssassinationPhaseTimeoutMin').val()) * 60 + parseInt($('#startGameOptionsAssassinationPhaseTimeoutSec').val())) * 1000).toString(), | ||
| }, | ||
| anonymousMode: $('#startGameOptionsAnonymousMode')[0].checked, | ||
| }; | ||
| socket.emit('startGame', startGameData); | ||
| } else if ( | ||
| gameData.phase === 'VotingTeam' && | ||
| !(await preventMisclick('yes')) | ||
| ) { | ||
| socket.emit('gameMove', ['yes', []]); | ||
| } else if (gameData.phase === 'VotingMission') { | ||
| socket.emit('gameMove', ['yes', []]); | ||
| } else if (gameData.phase === 'PickingTeam') { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this break anything? For example when using lady of the lake? I think it's safer to keep it as the old logic where it was just an else statement. |
||
| socket.emit('gameMove', ['yes', getHighlightedAvatars()]); | ||
| } | ||
|
|
||
| $('#mainRoomBox div').removeClass('highlight-avatar'); | ||
| } | ||
|
|
||
| //= ===================================== | ||
|
|
@@ -259,3 +245,48 @@ function handleTimeoutInput(inputId) { | |
| input.value = 60; | ||
| } | ||
| } | ||
|
|
||
| async function preventMisclick(button) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's looking good! Can we restructure the code a bit so each check is a bit clearer? E.g. This way you can get rid of isVoteExpected as well which is a bit confusing as a name for what it's doing. |
||
| if ( | ||
| $('#optionGameplayPreventMisclicks')[0].checked === false || | ||
| // only applies to 6 player | ||
| gameData.playerUsernamesOrdered.length !== 6 | ||
| ) { | ||
| return false; | ||
| } | ||
|
|
||
| const isPlayerOnTeam = gameData.proposedTeam.includes(gameData.username); | ||
| const missionsToCatchOnrej = [1, 2]; | ||
| const missionsToCatchOffapp = [1, 2, 3, 5]; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would've thought you'd want to check all missions for offapps? Or is the idea because at least one res has to approve mission 4 hammer? |
||
| let isVoteExpected = true; | ||
| let str = ''; | ||
| if (gameData.pickNum === 5) { | ||
| isVoteExpected = button === 'yes'; | ||
| str = 'Really reject hammer?' | ||
| } else if ( | ||
| isPlayerOnTeam && | ||
| missionsToCatchOnrej.includes(gameData.missionNum) | ||
| ) { | ||
| isVoteExpected = button === 'yes'; | ||
| str = 'You\'re on the team!' | ||
| } else if ( | ||
| !isPlayerOnTeam && | ||
| missionsToCatchOffapp.includes(gameData.missionNum) | ||
| ) { | ||
| isVoteExpected = button === 'no'; | ||
| str = 'You\'re off the team!' | ||
| } | ||
| if (isVoteExpected) { | ||
| return false; | ||
| } | ||
| // launch sweetalert to confirm click | ||
| const input = await swal({ | ||
| title: str, | ||
| type: 'warning', | ||
| showCancelButton: true, | ||
| reverseButtons: true, | ||
| confirmButtonText: button === 'yes' ? 'Approve' : 'Reject', | ||
| confirmButtonColor: button === 'yes' ? '#5cb85c' : '#d9534f', | ||
| }); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to add a tiny text at the bottom of the swal saying "you can disable misclick prevention in settings"? Just so we don't annoy the vets :). |
||
| return !input.value; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1193,6 +1193,29 @@ var userOptions = { | |
| ); | ||
| }, | ||
| }, | ||
|
|
||
| //--------------------------------------------- | ||
| // Gameplay | ||
| //--------------------------------------------- | ||
|
|
||
| optionGameplayPreventMisclicks: { | ||
| defaultValue: 'false', | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's put this on true and let people disable it as desired. |
||
| onLoad() { | ||
| if (docCookies.getItem('optionGameplayPreventMisclicks') === 'true') { | ||
| $('#optionGameplayPreventMisclicks')[0].checked = true; | ||
| } | ||
| }, | ||
| initialiseEventListener() { | ||
| $('#optionGameplayPreventMisclicks')[0].addEventListener('click', () => { | ||
| const { checked } = $('#optionGameplayPreventMisclicks')[0]; | ||
| docCookies.setItem( | ||
| 'optionGameplayPreventMisclicks', | ||
| checked.toString(), | ||
| Infinity | ||
| ); | ||
| }); | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| // run through each userOption load and initialiseEventListener | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
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.
Maybe instead of
preventMisclick, can we name thisconfirmUserClick? That way the return type is clearer. I.e. returning true means it's ok, and returning false means stop.Or we can call the function
isMisclickas well.