X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fviews%2FGame.vue;h=62611393b0b961dccf434ddd6a7e9ffe7809794b;hb=8948a2876de183467f610a703d8c7f6d7c2df570;hp=032f625edba450df85d9e5838268466b671d0d5a;hpb=1e02d16d2a376f7ef0af3c1ea36948a5f5926034;p=vchess.git diff --git a/client/src/views/Game.vue b/client/src/views/Game.vue index 032f625e..62611393 100644 --- a/client/src/views/Game.vue +++ b/client/src/views/Game.vue @@ -7,7 +7,7 @@ main ) .card label.modal-close(for="modalRules") - h4#variantNameInGame(@click="gotoRules") {{ game.vname }} + a#variantNameInGame(:href="'/#/variants/'+game.vname") {{ game.vname }} div(v-html="rulesContent") input#modalScore.modal(type="checkbox") div#scoreDiv( @@ -119,7 +119,7 @@ main ) 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( @@ -141,7 +141,7 @@ 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 - @@ -287,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() { @@ -300,14 +295,10 @@ 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 = {}; @@ -319,9 +310,6 @@ export default { ) ); }, - gotoRules: function() { - this.$router.push("/variants/" + this.game.vname); - }, participateInChat: function(p) { return Object.keys(p.tmpIds).some(x => p.tmpIds[x].focus) && !!p.name; }, @@ -438,10 +426,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 ( ( @@ -455,7 +447,7 @@ export default { ) || ( - !!player.id && + player.id > 0 && Object.values(this.people).some(p => { return ( p.id == player.id && @@ -679,7 +671,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 }); @@ -755,10 +746,15 @@ export default { if (!this.game || !this.game.moves) this.lastateAsked = true; else this.sendLastate(data.from); break; + // TODO: possible bad scenario: reload page while oppponent sends a + // move => get both lastate and newmove, process both, add move twice. + // Confirm scenario? Fix? case "lastate": { // Got opponent infos about last move this.gotLastate = true; this.lastate = data.data; + if (this.lastate.movesCount > this.gotMoveIdx) + this.gotMoveIdx = this.lastate.movesCount; if (this.game.rendered) // Game is rendered (Board component) this.processLastate(); @@ -766,6 +762,12 @@ export default { break; } case "newmove": { + +// DEBUG: +console.log("Receive move"); +console.log(data.data); +//moveslist not updated when receiving a move? (see in baseGame) + const movePlus = data.data; const movesCount = this.game.moves.length; if (movePlus.index > movesCount) { @@ -817,10 +819,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 ); } } @@ -863,7 +880,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; @@ -878,6 +895,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); @@ -930,8 +948,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 @@ -942,23 +960,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() { @@ -1020,7 +1062,7 @@ export default { let gameInfo = { id: getRandString(), //ignored if corr fen: V.GenRandInitFen(this.game.randomness), - players: this.game.players.reverse(), + players: [this.game.players[1], this.game.players[0]], vid: this.game.vid, cadence: this.game.cadence }; @@ -1090,7 +1132,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 ( @@ -1182,8 +1227,9 @@ export default { if ( (game.rematchOffer == "w" && myIdx == 0) || (game.rematchOffer == "b" && myIdx == 1) - ) + ) { this.rematchOffer = "sent"; + } else this.rematchOffer = "received"; } } @@ -1573,7 +1619,10 @@ export default { 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 @@ -1688,10 +1737,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 @@ -1727,19 +1780,19 @@ span.yourturn background-color: lightyellow .draw-received, .draw-received:hover - background-color: lightgreen + background-color: #73C6B6 .draw-threerep, .draw-threerep:hover - background-color: #e4d1fc + background-color: #D2B4DE .rematch-sent, .rematch-sent:hover background-color: lightyellow .rematch-received, .rematch-received:hover - background-color: lightgreen + background-color: #48C9B0 .somethingnew - background-color: #c5fefe + background-color: #D2B4DE .diagram margin: 0 auto @@ -1756,11 +1809,13 @@ button.acceptBtn button.refuseBtn background-color: red -h4#variantNameInGame - cursor: pointer +a#variantNameInGame + color: var(--card-fore-color) text-align: center - text-decoration: underline font-weight: bold + font-size: calc(1rem * var(--heading-ratio)) + line-height: 1.2 + margin: calc(1.5 * var(--universal-margin))