X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fviews%2FGame.vue;h=e0eb1be0ce54a5c9cfd554a273ae161126409de5;hb=751d7ca49079f479d41ee201e9cfbeee35664c41;hp=6d506c5fb18de830255208536d516c4b0cbbc694;hpb=13d00ef164983c0e0a42b739a13bdc9eb3f1d21e;p=vchess.git diff --git a/client/src/views/Game.vue b/client/src/views/Game.vue index 6d506c5f..e0eb1be0 100644 --- a/client/src/views/Game.vue +++ b/client/src/views/Game.vue @@ -84,39 +84,42 @@ main @click="showNextGame()" ) | {{ st.tr["Next_g"] }} - button#chatBtn.tooltip( + button#chatBtn( + :class="btnTooltipClass()" onClick="window.doClick('modalChat')" aria-label="Chat" ) img(src="/images/icons/chat.svg") #actions(v-if="game.score=='*'") - button.tooltip( + button( @click="clickDraw()" - :class="{['draw-' + drawOffer]: true}" + :class="btnTooltipClass('draw')" :aria-label="st.tr['Draw']" ) img(src="/images/icons/draw.svg") - button.tooltip( - v-show="!!game.mycolor" + button( + v-if="!!game.mycolor" + :class="btnTooltipClass()" @click="abortGame()" :aria-label="st.tr['Abort']" ) img(src="/images/icons/abort.svg") - button.tooltip( - v-show="!!game.mycolor" + button( + v-if="!!game.mycolor" + :class="btnTooltipClass()" @click="resign()" :aria-label="st.tr['Resign']" ) img(src="/images/icons/resign.svg") - button.tooltip( + button( v-else + :class="btnTooltipClass('rematch')" @click="clickRematch()" - :class="{['rematch-' + rematchOffer]: true}" :aria-label="st.tr['Rematch']" ) img(src="/images/icons/rematch.svg") #playersInfo - p(v-if="isLargeScreen()") + div(v-if="isLargeScreen()") span.name(:class="{connected: isConnected(0)}") | {{ game.players[0].name || "@nonymous" }} span.time( @@ -138,30 +141,24 @@ main span.time-separator(v-if="!!virtualClocks[1][1]") : span.time-right(v-if="!!virtualClocks[1][1]") | {{ virtualClocks[1][1] }} - p(v-else) + div(v-else) span.name(:class="{connected: isConnected(0)}") | {{ game.players[0].name || "@nonymous" }} span.split-names - span.name(:class="{connected: isConnected(1)}") | {{ game.players[1].name || "@nonymous" }} - br - span.time( - v-if="game.score=='*'" - :class="{yourturn: !!vr && vr.turn == 'w'}" - ) - span.time-left {{ virtualClocks[0][0] }} - span.time-separator(v-if="!!virtualClocks[0][1]") : - span.time-right(v-if="!!virtualClocks[0][1]") - | {{ virtualClocks[0][1] }} - span.separator - span.time( - v-if="game.score=='*'" - :class="{yourturn: !!vr && vr.turn == 'b'}" - ) - span.time-left {{ virtualClocks[1][0] }} - span.time-separator(v-if="!!virtualClocks[1][1]") : - span.time-right(v-if="!!virtualClocks[1][1]") - | {{ virtualClocks[1][1] }} + div(v-if="game.score=='*'") + span.time(:class="{yourturn: !!vr && vr.turn == 'w'}") + span.time-left {{ virtualClocks[0][0] }} + span.time-separator(v-if="!!virtualClocks[0][1]") : + span.time-right(v-if="!!virtualClocks[0][1]") + | {{ virtualClocks[0][1] }} + span.separator + span.time(:class="{yourturn: !!vr && vr.turn == 'b'}") + span.time-left {{ virtualClocks[1][0] }} + span.time-separator(v-if="!!virtualClocks[1][1]") : + span.time-right(v-if="!!virtualClocks[1][1]") + | {{ virtualClocks[1][1] }} BaseGame( ref="basegame" :game="game" @@ -290,11 +287,6 @@ export default { visibilityChange: function() { // TODO: Use document.hidden? https://webplatform.news/issues/2019-03-27 this.focus = (document.visibilityState == "visible"); - if (!this.focus && !!this.rematchOffer) { - this.rematchOffer = ""; - this.send("rematchoffer", { data: false }); - // Do not remove rematch offer from (local) storage - } this.send(this.focus ? "getfocus" : "losefocus"); }, onFocus: function() { @@ -303,14 +295,20 @@ export default { }, onBlur: function() { this.focus = false; - if (!!this.rematchOffer) { - this.rematchOffer = ""; - this.send("rematchoffer", { data: false }); - } this.send("losefocus"); }, isLargeScreen: function() { - return window.innerWidth >= 500; + return window.innerWidth >= 768; + }, + btnTooltipClass: function(thing) { + let append = {}; + if (!!thing) append = { [thing + "-" + this[thing + "Offer"]]: true }; + return ( + Object.assign( + { tooltip: !("ontouchstart" in window) }, + append + ) + ); }, gotoRules: function() { this.$router.push("/variants/" + this.game.vname); @@ -431,10 +429,14 @@ export default { isConnected: function(index) { const player = this.game.players[index]; // Is it me ? In this case no need to bother with focus - if (this.st.user.sid == player.sid || this.st.user.id == player.id) + if ( + this.st.user.sid == player.sid || + (!!player.name && this.st.user.id == player.id) + ) { // Still have to check for name (because of potential multi-accounts // on same browser, although this should be rare...) return (!this.st.user.name || this.st.user.name == player.name); + } // Try to find a match in people: return ( ( @@ -448,7 +450,7 @@ export default { ) || ( - !!player.id && + player.id > 0 && Object.values(this.people).some(p => { return ( p.id == player.id && @@ -672,7 +674,6 @@ export default { !this.gotLastate && !!this.game.mycolor && this.game.type == "live" && - this.game.score == "*" && this.game.players.some(p => p.sid == user.sid) ) { this.send("asklastate", { target: user.sid }); @@ -810,10 +811,25 @@ export default { } } this.$refs["basegame"].play(movePlus.move, "received"); - this.game.clocks[moveColIdx] = movePlus.clock; - this.processMove( - movePlus.move, - { receiveMyMove: receiveMyMove } + // Freeze time while the move is being play + // (TODO: a callback would be cleaner here) + clearInterval(this.clockUpdate); + this.clockUpdate = null; + const freezeDuration = ["all", "highlight"].includes(V.ShowMoves) + // 250 = length of animation, 500 = delay between sub-moves + ? 250 + 750 * + (Array.isArray(movePlus.move) ? movePlus.move.length - 1 : 0) + // Incomplete information: no move animation + : 0; + setTimeout( + () => { + this.game.clocks[moveColIdx] = movePlus.clock; + this.processMove( + movePlus.move, + { receiveMyMove: receiveMyMove } + ); + }, + freezeDuration ); } } @@ -856,7 +872,7 @@ export default { if (!!this.game.mycolor && this.game.type == "live") { GameStorage.update( this.gameRef, - { rematchOffer: V.GetOppCol(this.game.mycolor) } + { rematchOffer: data.data ? V.GetOppCol(this.game.mycolor) : "" } ); } break; @@ -871,6 +887,7 @@ export default { this.addAndGotoLiveGame(gameInfo); } else if ( gameType == "corr" && + this.st.user.id > 0 && gameInfo.players.some(p => p.id == this.st.user.id) ) { this.$router.push("/game/" + gameInfo.id); @@ -923,8 +940,8 @@ export default { clock: this.game.clocks[myIdx], // Since we played a move (or abort or resign), // only drawOffer=="sent" is possible - drawSent: this.drawOffer == "sent", - rematchSent: this.rematchOffer == "sent", + drawSent: this.drawOffer == "sent" ? true : undefined, + rematchSent: this.rematchOffer == "sent" ? true : undefined, score: this.game.score != "*" ? this.game.score : undefined, scoreMsg: this.game.score != "*" ? this.game.scoreMsg : undefined, movesCount: L @@ -935,23 +952,47 @@ export default { processLastate: function() { const data = this.lastate; this.lastate = undefined; //security... - const L = this.game.moves.length; - const oppIdx = 1 - ["w", "b"].indexOf(this.game.mycolor); - this.game.clocks[oppIdx] = data.clock; - if (data.movesCount > L) { - // Just got last move from him - this.$refs["basegame"].play(data.lastMove, "received"); - this.processMove(data.lastMove); - } else { - if (!!this.clockUpdate) clearInterval(this.clockUpdate); - this.re_setClocks(); - } - if (data.drawSent) this.drawOffer = "received"; - if (data.rematchSent) this.rematchOffer = "received"; if (!!data.score) { - this.drawOffer = ""; - if (this.game.score == "*") - this.gameOver(data.score, data.scoreMsg); + const oppCol = V.GetOppCol(this.game.mycolor); + if (!!data.rematchSent) { + if (this.game.rematchOffer != oppCol) { + // Opponent sended rematch offer while we were offline: + this.rematchOffer = "received"; + GameStorage.update( + this.gameRef, + { rematchOffer: oppCol } + ); + } + } + else { + if (this.game.rematchOffer == oppCol) { + // Opponent cancelled rematch offer while we were offline: + this.rematchOffer = ""; + GameStorage.update( + this.gameRef, + { rematchOffer: "" } + ); + } + } + } + else { + const L = this.game.moves.length; + const oppIdx = 1 - ["w", "b"].indexOf(this.game.mycolor); + this.game.clocks[oppIdx] = data.clock; + if (data.movesCount > L) { + // Just got last move from him + this.$refs["basegame"].play(data.lastMove, "received"); + this.processMove(data.lastMove); + } else { + if (!!this.clockUpdate) clearInterval(this.clockUpdate); + this.re_setClocks(); + } + if (!!data.drawSent) this.drawOffer = "received"; + if (!!data.score) { + this.drawOffer = ""; + if (this.game.score == "*") + this.gameOver(data.score, data.scoreMsg); + } } }, clickDraw: function() { @@ -1083,7 +1124,10 @@ export default { const gtype = game.type || this.getGameType(game); const tc = extractTime(game.cadence); const myIdx = game.players.findIndex(p => { - return p.sid == this.st.user.sid || p.id == this.st.user.id; + return ( + p.sid == this.st.user.sid || + (!!p.name && p.id == this.st.user.id) + ); }); // Sometimes the name isn't stored yet (TODO: why?) if ( @@ -1175,8 +1219,9 @@ export default { if ( (game.rematchOffer == "w" && myIdx == 0) || (game.rematchOffer == "b" && myIdx == 1) - ) + ) { this.rematchOffer = "sent"; + } else this.rematchOffer = "received"; } } @@ -1207,17 +1252,6 @@ export default { }, game ); - if ("ontouchstart" in window) { - this.$nextTick(() => { - // Disable tooltips on smartphones: - document.querySelectorAll("#aboveBoard .tooltip").forEach(elt => { - -alert(elt); - - elt.classList.remove("tooltip"); - }); - }); - } this.$refs["basegame"].re_setVariables(this.game); if (!this.gameIsLoading) { // Initial loading: @@ -1570,15 +1604,6 @@ alert(elt); // In corr games, callback to change page only after score is set: gameOver: function(score, scoreMsg, callback) { this.game.score = score; - if ("ontouchstart" in window) { - this.$nextTick(() => { - // Disable tooltips on smartphones - // (might be required for rematch button at least): - document.querySelectorAll("#aboveBoard .tooltip").forEach(elt => { - elt.classList.remove("tooltip"); - }); - }); - } if (!scoreMsg) scoreMsg = getScoreMessage(score); this.game.scoreMsg = scoreMsg; document.getElementById("modalRules").checked = false; @@ -1586,7 +1611,10 @@ alert(elt); document.getElementById("modalScore").checked = true; this.$set(this.game, "scoreMsg", scoreMsg); const myIdx = this.game.players.findIndex(p => { - return p.sid == this.st.user.sid || p.id == this.st.user.id; + return ( + p.sid == this.st.user.sid || + (!!p.name && p.id == this.st.user.id) + ); }); if (myIdx >= 0) { // OK, I play in this game @@ -1701,10 +1729,14 @@ span.separator span.name font-size: 1.5rem + @media screen and (max-width: 767px) + font-size: 1.2rem padding: 0 3px span.time font-size: 2rem + @media screen and (max-width: 767px) + font-size: 1.5rem display: inline-block .time-left margin-left: 10px