Refactor models (merge Players in Games), add cursor to correspondance games. Finishe...
[vchess.git] / client / src / views / Game.vue
index 024847c..a401e46 100644 (file)
@@ -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()"
@@ -89,7 +95,7 @@ main
         )
           img(src="/images/icons/resign.svg")
       button.tooltip(
-        v-else-if="!!game.mycolor"
+        v-else
         @click="clickRematch()"
         :class="{['rematch-' + rematchOffer]: true}"
         :aria-label="st.tr['Rematch']"
@@ -161,11 +167,10 @@ export default {
       virtualClocks: [],
       vr: null, //"variant rules" object initialized from FEN
       drawOffer: "",
-      infoMessage: "",
+      rematchId: "",
       rematchOffer: "",
       lastateAsked: false,
       people: {}, //players + observers
-      onMygames: [], //opponents (or me) on "MyGames" page
       lastate: undefined, //used if opponent send lastate before game is ready
       repeat: {}, //detect position repetition
       curDiag: "", //for corr moves confirmation
@@ -217,12 +222,13 @@ export default {
   },
   mounted: function() {
     document.addEventListener('visibilitychange', this.visibilityChange);
-    document
-      .getElementById("chatWrap")
-      .addEventListener("click", processModalClick);
+    ["chatWrap", "infoDiv"].forEach(eltName => {
+      document.getElementById(eltName)
+        .addEventListener("click", processModalClick);
+    });
     if ("ontouchstart" in window) {
       // Disable tooltips on smartphones:
-      document.getElementsByClassName("tooltip").forEach(elt => {
+      document.querySelectorAll("#aboveBoard .tooltip").forEach(elt => {
         elt.classList.remove("tooltip");
       });
     }
@@ -271,7 +277,6 @@ export default {
       this.drawOffer = "";
       this.lastateAsked = false;
       this.rematchOffer = "";
-      this.onMygames = [];
       this.lastate = undefined;
       this.newChat = "";
       this.roomInitialized = false;
@@ -290,6 +295,8 @@ export default {
         params.socketUrl +
         "/?sid=" +
         this.st.user.sid +
+        "&id=" +
+        this.st.user.id +
         "&tmpId=" +
         getRandString() +
         "&page=" +
@@ -345,7 +352,7 @@ 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.uid)
+      if (this.st.user.sid == player.sid || 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);
@@ -358,9 +365,9 @@ export default {
         )
         ||
         (
-          player.uid &&
+          player.id &&
           Object.values(this.people).some(p =>
-            p.id == player.uid && p.focus)
+            p.id == player.id && p.focus)
         )
       );
     },
@@ -401,17 +408,17 @@ export default {
     getGameType: function(game) {
       return game.cadence.indexOf("d") >= 0 ? "corr" : "live";
     },
-    // Notify turn after a new move (to opponent and me on MyGames page)
-    notifyTurn: function(sid) {
-      const player = this.people[sid];
-      const colorIdx = this.game.players.findIndex(
-        p => p.sid == sid || p.uid == player.id);
-      const color = ["w","b"][colorIdx];
-      const movesCount = this.game.moves.length;
-      const yourTurn =
-        (color == "w" && movesCount % 2 == 0) ||
-        (color == "b" && movesCount % 2 == 1);
-      this.send("turnchange", { target: sid, yourTurn: yourTurn });
+    // Notify something after a new move (to opponent and me on MyGames page)
+    notifyMyGames: function(thing, data) {
+      this.send(
+        "notify" + thing,
+        {
+          data: data,
+          targets: this.game.players.map(p => {
+            return { sid: p.sid, id: p.id };
+          })
+        }
+      );
     },
     showNextGame: function() {
       // Did I play in current game? If not, add it to nextIds list
@@ -462,22 +469,6 @@ export default {
         case "disconnect":
           this.$delete(this.people, data.from);
           break;
-        case "mconnect": {
-          // TODO: from MyGames page : send mconnect message with the list of gid (live and corr)
-          // Either me (another tab) or opponent
-          const sid = data.from;
-          if (!this.onMygames.some(s => s == sid))
-          {
-            this.onMygames.push(sid);
-            this.notifyTurn(sid); //TODO: this may require server ID (so, notify after receiving identity)
-          }
-          break;
-          if (!this.people[sid])
-            this.send("askidentity", { target: sid });
-        }
-        case "mdisconnect":
-          ArrayFun.remove(this.onMygames, sid => sid == data.from);
-          break;
         case "getfocus": {
           let player = this.people[data.from];
           if (!!player) {
@@ -702,7 +693,7 @@ export default {
             this.addAndGotoLiveGame(gameInfo);
           } else if (
             gameType == "corr" &&
-            gameInfo.players.some(p => p.uid == this.st.user.id)
+            gameInfo.players.some(p => p.id == this.st.user.id)
           ) {
             this.$router.push("/game/" + gameInfo.id);
           } else {
@@ -716,14 +707,7 @@ export default {
               });
               urlRid += onlineSid[Math.floor(Math.random() * onlineSid.length)];
             }
-            this.infoMessage =
-              this.st.tr["Rematch in progress:"] +
-              " <a href='#/game/" +
-              gameInfo.id + urlRid +
-              "'>" +
-              "#/game/" +
-              gameInfo.id + urlRid +
-              "</a>";
+            this.rematchId = gameInfo.id + urlRid;
             document.getElementById("modalInfo").checked = true;
           }
           break;
@@ -773,7 +757,7 @@ export default {
           drawSent: this.drawOffer == "sent",
           rematchSent: this.rematchOffer == "sent",
           score: this.game.score,
-          score: this.game.scoreMsg,
+          scoreMsg: this.game.scoreMsg,
           movesCount: L,
           initime: this.game.initime[1 - myIdx] //relevant only if I played
         };
@@ -848,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);
         }
       });
@@ -867,6 +851,8 @@ export default {
         const notifyNewGame = () => {
           let oppsid = this.getOppsid(); //may be null
           this.send("rnewgame", { data: gameInfo, oppsid: oppsid });
+          // Also to MyGames page:
+          this.notifyMyGames("newgame", gameInfo);
         };
         if (this.game.type == "live")
           this.addAndGotoLiveGame(gameInfo, notifyNewGame);
@@ -932,7 +918,7 @@ export default {
         const gtype = this.getGameType(game);
         const tc = extractTime(game.cadence);
         const myIdx = game.players.findIndex(p => {
-          return p.sid == this.st.user.sid || p.uid == this.st.user.id;
+          return p.sid == this.st.user.sid || p.id == this.st.user.id;
         });
         const mycolor = [undefined, "w", "b"][myIdx + 1]; //undefined for observers
         if (!game.chats) game.chats = []; //live games don't have chat history
@@ -951,14 +937,9 @@ export default {
           if (game.score == "*") {
             // Set clocks + initime
             game.initime = [0, 0];
-            if (L >= 1) {
-              const gameLastupdate = game.moves[L-1].played;
-              game.initime[L % 2] = gameLastupdate;
-              if (L >= 2) {
-                game.clocks[L % 2] =
-                  tc.mainTime - (Date.now() - gameLastupdate) / 1000;
-              }
-            }
+            if (L >= 1) game.initime[L % 2] = game.moves[L-1].played;
+            // NOTE: game.clocks shouldn't be computed right now:
+            // job will be done in re_setClocks() called soon below.
           }
           // Sort chat messages from newest to oldest
           game.chats.sort((c1, c2) => {
@@ -1050,15 +1031,12 @@ export default {
             // opponent sid not strictly required (or available), but easier
             // at least oppsid or oppid is available anyway:
             oppsid: myIdx < 0 ? undefined : game.players[1 - myIdx].sid,
-            oppid: myIdx < 0 ? undefined : game.players[1 - myIdx].uid
+            oppid: myIdx < 0 ? undefined : game.players[1 - myIdx].id
           },
           game,
         );
-        if (this.gameIsLoading)
-          // Re-load game because we missed some moves:
-          // artificially reset BaseGame (required if moves arrived in wrong order)
-          this.$refs["basegame"].re_setVariables();
-        else {
+        this.$refs["basegame"].re_setVariables(this.game);
+        if (!this.gameIsLoading) {
           // Initial loading:
           this.gotMoveIdx = game.moves.length - 1;
           // If we arrive here after 'nextGame' action, the board might be hidden
@@ -1107,6 +1085,9 @@ export default {
                 g.moves.forEach(m => {
                   m.squares = JSON.parse(m.squares);
                 });
+                g.players = [{ id: g.white }, { id: g.black }];
+                delete g["white"];
+                delete g["black"];
                 afterRetrieval(g);
               }
             }
@@ -1185,7 +1166,6 @@ export default {
           const score = this.vr.getCurrentScore();
           if (score != "*") this.gameOver(score);
         }
-// TODO: notifyTurn: "changeturn" message
         this.game.moves.push(move);
         this.game.fen = this.vr.getFen();
         if (this.game.type == "live") {
@@ -1216,6 +1196,16 @@ export default {
           // NOTE: 'var' to see that variable outside this block
           var filtered_move = getFilteredMove(move);
         }
+        if (moveCol == this.game.mycolor && !data.receiveMyMove) {
+          // Notify turn on MyGames page:
+          this.notifyMyGames(
+            "turn",
+            {
+              gid: this.gameRef.id,
+              turn: this.vr.turn
+            }
+          );
+        }
         // Since corr games are stored at only one location, update should be
         // done only by one player for each move:
         if (
@@ -1379,7 +1369,7 @@ export default {
       this.game.scoreMsg = scoreMsg;
       this.$set(this.game, "scoreMsg", scoreMsg);
       const myIdx = this.game.players.findIndex(p => {
-        return p.sid == this.st.user.sid || p.uid == this.st.user.id;
+        return p.sid == this.st.user.sid || p.id == this.st.user.id;
       });
       if (myIdx >= 0) {
         // OK, I play in this game
@@ -1394,6 +1384,14 @@ export default {
         else this.updateCorrGame(scoreObj, callback);
         // Notify the score to main Hall. TODO: only one player (currently double send)
         this.send("result", { gid: this.game.id, score: score });
+        // Also to MyGames page (TODO: doubled as well...)
+        this.notifyMyGames(
+          "score",
+          {
+            gid: this.gameRef.id,
+            score: score
+          }
+        );
       }
       else if (!!callback) callback();
     }