From: Benjamin Auder Date: Sun, 15 Mar 2020 18:28:38 +0000 (+0100) Subject: Improve games/challenges display and fix MyGames page reactivity (using () for now...) X-Git-Url: https://git.auder.net/doc/current/%7B%7B%20asset%28%27mixstore/DESCRIPTION?a=commitdiff_plain;h=585d095517ca2aedab8ad125cc7c39b90e13d5cc;p=vchess.git Improve games/challenges display and fix MyGames page reactivity (using () for now...) --- diff --git a/client/src/components/GameList.vue b/client/src/components/GameList.vue index 354cfa03..1a50e956 100644 --- a/client/src/components/GameList.vue +++ b/client/src/components/GameList.vue @@ -9,7 +9,7 @@ div th {{ st.tr["Result"] }} tbody tr( - v-for="g in sortedGames" + v-for="g in sortedGames()" @click="$emit('show-game',g)" :class="{'my-turn': !!g.myTurn}" ) @@ -52,7 +52,21 @@ export default { } }); }, - computed: { + methods: { + player_s: function(g) { + if (this.showBoth) + return ( + (g.players[0].name || "@nonymous") + + " - " + + (g.players[1].name || "@nonymous") + ); + if ( + this.st.user.sid == g.players[0].sid || + this.st.user.id == g.players[0].uid + ) + return g.players[1].name || "@nonymous"; + return g.players[0].name || "@nonymous"; + }, sortedGames: function() { // Show in order: it's my turn, running games, completed games let minCreated = Number.MAX_SAFE_INTEGER; @@ -75,22 +89,6 @@ export default { ); }); }, - }, - methods: { - player_s: function(g) { - if (this.showBoth) - return ( - (g.players[0].name || "@nonymous") + - " - " + - (g.players[1].name || "@nonymous") - ); - if ( - this.st.user.sid == g.players[0].sid || - this.st.user.id == g.players[0].uid - ) - return g.players[1].name || "@nonymous"; - return g.players[0].name || "@nonymous"; - }, scoreClass: function(g) { if (g.score == "*" || !g.myColor) return {}; // Ok it's my finished game: determine if I won, drew or lost. diff --git a/client/src/views/Game.vue b/client/src/views/Game.vue index cb1b720d..e7db9729 100644 --- a/client/src/views/Game.vue +++ b/client/src/views/Game.vue @@ -7,7 +7,13 @@ main ) .card.text-center label.modal-close(for="modalInfo") - p(v-html="infoMessage") + p + span {{ st.tr["Rematch in progress:"] }} + a( + :href="'#/game/' + rematchId" + onClick="document.getElementById('modalInfo').checked=false" + ) + | {{ "#/game/" + rematchId }} input#modalChat.modal( type="checkbox" @click="resetChatColor()" @@ -161,7 +167,7 @@ export default { virtualClocks: [], vr: null, //"variant rules" object initialized from FEN drawOffer: "", - infoMessage: "", + rematchId: "", rematchOffer: "", lastateAsked: false, people: {}, //players + observers @@ -701,14 +707,7 @@ export default { }); urlRid += onlineSid[Math.floor(Math.random() * onlineSid.length)]; } - this.infoMessage = - this.st.tr["Rematch in progress:"] + - " " + - "#/game/" + - gameInfo.id + urlRid + - ""; + this.rematchId = gameInfo.id + urlRid; document.getElementById("modalInfo").checked = true; } break; @@ -833,7 +832,7 @@ export default { if (!err) { if (this.st.settings.sound) new Audio("/sounds/newgame.flac").play().catch(() => {}); - callback(); + if (!!callback) callback(); this.$router.push("/game/" + gameInfo.id); } }); diff --git a/client/src/views/Hall.vue b/client/src/views/Hall.vue index f4fc172c..f9519fe2 100644 --- a/client/src/views/Hall.vue +++ b/client/src/views/Hall.vue @@ -637,15 +637,14 @@ export default { } else { // Remove the matching live game if now unreachable const gid = data.page.match(/[a-zA-Z0-9]+$/)[0]; - const gidx = this.games.findIndex(g => g.id == gid); - if (gidx >= 0) { - const game = this.games[gidx]; - if ( - game.type == "live" && - game.rids.length == 1 && - game.rids[0] == data.from - ) { - this.games.splice(gidx, 1); + // Corr games are always reachable: + if (!gid.match(/^[0-9]+$/)) { + const gidx = this.games.findIndex(g => g.id == gid); + // NOTE: gidx should always be >= 0 (TODO?) + if (gidx >= 0) { + const game = this.games[gidx]; + ArrayFun.remove(game.rids, rid => rid == data.from); + if (game.rids.length == 0) this.games.splice(gidx, 1); } } } @@ -676,7 +675,7 @@ export default { alert(this.st.tr["New connexion detected: tab now offline"]); break; case "askidentity": { - // Request for identification (TODO: anonymous shouldn't need to reply) + // Request for identification const me = { // Decompose to avoid revealing email name: this.st.user.name, @@ -762,12 +761,12 @@ export default { } break; } - case "game": //individual request - case "newgame": { + case "game": { + // Individual request const game = data.data; // Ignore games where I play (will go in MyGames page) if (game.players.every(p => - p.sid != this.st.user.sid || p.uid != this.st.user.id)) + p.sid != this.st.user.sid && p.uid != this.st.user.id)) { let locGame = this.games.find(g => g.id == game.id); if (!locGame) { @@ -907,8 +906,9 @@ export default { else if ( ctype == "live" && Object.values(this.people).every(p => p.name != this.newchallenge.to) - ) + ) { error = this.newchallenge.to + " " + this.st.tr["is not online"]; + } } if (error) { alert(error); @@ -1120,10 +1120,7 @@ export default { if (!!oppsid) // Opponent is online this.send("startgame", { data: gameInfo, target: oppsid }); - // Send game info (only if live) to everyone except me and opponent - // TODO: this double message send could be avoided. - this.send("newgame", { data: gameInfo, oppsid: oppsid }); - // Also to MyGames page: + // Notify MyGames page: this.send( "notifynewgame", { @@ -1133,6 +1130,8 @@ export default { }) } ); + // NOTE: no need to send the game to the room, since I'll connect + // on game just after, the main Hall will be notified. }; if (c.type == "live") { notifyNewgame(); diff --git a/client/src/views/MyGames.vue b/client/src/views/MyGames.vue index c9c34f34..1362cb24 100644 --- a/client/src/views/MyGames.vue +++ b/client/src/views/MyGames.vue @@ -8,12 +8,14 @@ main button.tabbtn#corrGames(@click="setDisplay('corr',$event)") | {{ st.tr["Correspondance games"] }} GameList( + ref="livegames" v-show="display=='live'" :games="liveGames" @show-game="showGame" @abortgame="abortGame" ) GameList( + ref="corrgames" v-show="display=='corr'" :games="corrGames" @show-game="showGame" @@ -45,32 +47,6 @@ export default { }; }, created: function() { - GameStorage.getAll(localGames => { - localGames.forEach(g => g.type = "live"); - this.decorate(localGames); - this.liveGames = localGames; - }); - if (this.st.user.id > 0) { - ajax( - "/games", - "GET", - { - data: { uid: this.st.user.id }, - success: (res) => { - let serverGames = res.games.filter(g => { - const mySide = - g.players[0].uid == this.st.user.id - ? "White" - : "Black"; - return !g["deletedBy" + mySide]; - }); - serverGames.forEach(g => g.type = "corr"); - this.decorate(serverGames); - this.corrGames = serverGames; - } - } - ); - } // Initialize connection this.connexionString = params.socketUrl + @@ -87,8 +63,54 @@ export default { this.conn.onclose = this.socketCloseListener; }, mounted: function() { - const showType = localStorage.getItem("type-myGames") || "live"; - this.setDisplay(showType); + const adjustAndSetDisplay = () => { + // showType is the last type viwed by the user (default) + let showType = localStorage.getItem("type-myGames") || "live"; + // Live games, my turn: highest priority: + if (this.liveGames.some(g => !!g.myTurn)) showType = "live"; + // Then corr games, my turn: + else if (this.corrGames.some(g => !!g.myTurn)) showType = "corr"; + else { + // If a listing is empty, try showing the other (if non-empty) + const types = ["corr", "live"]; + for (let i of [0,1]) { + if ( + this[types[i] + "Games"].length > 0 && + this[types[1-i] + "Games"].length == 0 + ) { + showType = types[i]; + } + } + } + this.setDisplay(showType); + }; + GameStorage.getAll(localGames => { + localGames.forEach(g => g.type = "live"); + this.decorate(localGames); + this.liveGames = localGames; + if (this.st.user.id > 0) { + ajax( + "/games", + "GET", + { + data: { uid: this.st.user.id }, + success: (res) => { + let serverGames = res.games.filter(g => { + const mySide = + g.players[0].uid == this.st.user.id + ? "White" + : "Black"; + return !g["deletedBy" + mySide]; + }); + serverGames.forEach(g => g.type = "corr"); + this.decorate(serverGames); + this.corrGames = serverGames; + adjustAndSetDisplay(); + } + } + ); + } else adjustAndSetDisplay(); + }); }, beforeDestroy: function() { this.conn.send(JSON.stringify({code: "disconnect"})); @@ -145,9 +167,13 @@ export default { // "notifything" --> "thing": const thing = data.code.substr(6); game[thing] = info[thing]; - if (thing == "turn") game.myTurn = !game.myTurn; - this.$forceUpdate(); - this.tryShowNewsIndicator(type); + if (thing == "turn") { + game.myTurn = !game.myTurn; + if (game.myTurn) this.tryShowNewsIndicator(type); + } + // TODO: forcing refresh like that is ugly and wrong. + // How to do it cleanly? + this.$refs[type + "games"].$forceUpdate(); break; } case "notifynewgame": { @@ -170,8 +196,9 @@ export default { (type == "corr" && game.players[0].uid == this.st.user.id) || (type == "live" && game.players[0].sid == this.st.user.sid); gamesArrays[type].push(game); - this.$forceUpdate(); - this.tryShowNewsIndicator(type); + if (game.myTurn) this.tryShowNewsIndicator(type); + // TODO: cleaner refresh + this.$refs[type + "games"].$forceUpdate(); break; } } diff --git a/server/sockets.js b/server/sockets.js index c8f3c7f8..b16135bd 100644 --- a/server/sockets.js +++ b/server/sockets.js @@ -208,16 +208,13 @@ module.exports = function(wss) { case "drawoffer": case "rematchoffer": case "draw": - if (!!obj.oppsid) - // "newgame" message from Hall: do not target players - notifyAllBut(page, "newgame", {data: obj.data}, [sid, obj.oppsid]); - else notifyRoom(page, obj.code, {data: obj.data}); + notifyRoom(page, obj.code, {data: obj.data}); break; case "rnewgame": - // A rematch game started: players are already informed + // A rematch game started: + // NOTE: no need to explicitely notify Hall: the game will be sent notifyAllBut(page, "newgame", {data: obj.data}, [sid]); - notifyAllBut("/", "newgame", {data: obj.data}, [sid, obj.oppsid]); notifyRoom("/mygames", "newgame", {data: obj.data}); break;