UserBio: a few fixes, but still doesn't work as expected
[vchess.git] / client / src / views / Game.vue
index 8f40dea..171dc6c 100644 (file)
@@ -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(
@@ -120,8 +120,11 @@ main
         img(src="/images/icons/rematch.svg")
       #playersInfo
         div(v-if="isLargeScreen()")
-          span.name(:class="{connected: isConnected(0)}")
-            | {{ game.players[0].name || "@nonymous" }}
+          UserBio.user-bio(
+            :class="{connected: isConnected(0)}"
+            :uid="game.players[0].id"
+            :uname="game.players[0].name"
+          )
           span.time(
             v-if="game.score=='*'"
             :class="{yourturn: !!vr && vr.turn == 'w'}"
@@ -131,8 +134,11 @@ main
             span.time-right(v-if="!!virtualClocks[0][1]")
               | {{ virtualClocks[0][1] }}
           span.split-names -
-          span.name(:class="{connected: isConnected(1)}")
-            | {{ game.players[1].name || "@nonymous" }}
+          UserBio.user-bio(
+            :class="{connected: isConnected(1)}"
+            :uid="game.players[1].id"
+            :uname="game.players[1].name"
+          )
           span.time(
             v-if="game.score=='*'"
             :class="{yourturn: !!vr && vr.turn == 'b'}"
@@ -142,11 +148,17 @@ main
             span.time-right(v-if="!!virtualClocks[1][1]")
               | {{ virtualClocks[1][1] }}
         div(v-else)
-          span.name(:class="{connected: isConnected(0)}")
-            | {{ game.players[0].name || "@nonymous" }}
+          UserBio.user-bio(
+            :class="{connected: isConnected(0)}"
+            :uid="game.players[0].id"
+            :uname="game.players[0].name"
+          )
           span.split-names -
-          span.name(:class="{connected: isConnected(1)}")
-            | {{ game.players[1].name || "@nonymous" }}
+          UserBio.user-bio(
+            :class="{connected: isConnected(1)}"
+            :uid="game.players[1].id"
+            :uname="game.players[1].name"
+          )
           div(v-if="game.score=='*'")
             span.time(:class="{yourturn: !!vr && vr.turn == 'w'}")
               span.time-left {{ virtualClocks[0][0] }}
@@ -168,6 +180,7 @@ main
 
 <script>
 import BaseGame from "@/components/BaseGame.vue";
+import UserBio from "@/components/UserBio.vue";
 import Chat from "@/components/Chat.vue";
 import { store } from "@/store";
 import { GameStorage } from "@/utils/gameStorage";
@@ -188,7 +201,8 @@ export default {
   name: "my-game",
   components: {
     BaseGame,
-    Chat
+    Chat,
+    UserBio
   },
   data: function() {
     return {
@@ -212,9 +226,6 @@ export default {
       curDiag: "", //for corr moves confirmation
       conn: null,
       roomInitialized: false,
-      // If newmove has wrong index: ask fullgame again:
-      askGameTime: 0,
-      gameIsLoading: false,
       // If asklastate got no reply, ask again:
       gotLastate: false,
       gotMoveIdx: -1, //last move index received
@@ -310,9 +321,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;
     },
@@ -360,8 +368,6 @@ export default {
       this.rematchOffer = "";
       this.lastate = undefined;
       this.roomInitialized = false;
-      this.askGameTime = 0;
-      this.gameIsLoading = false;
       this.gotLastate = false;
       this.gotMoveIdx = -1;
       this.opponentGotMove = false;
@@ -429,10 +435,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 (
         (
@@ -446,7 +456,7 @@ export default {
         )
         ||
         (
-          !!player.id &&
+          player.id > 0 &&
           Object.values(this.people).some(p => {
             return (
               p.id == player.id &&
@@ -535,27 +545,6 @@ export default {
       this.$router.push(
         "/game/" + nextGid + "/?next=" + JSON.stringify(this.nextIds));
     },
-    askGameAgain: function() {
-      this.gameIsLoading = true;
-      const currentUrl = document.location.href;
-      const doAskGame = () => {
-        if (document.location.href != currentUrl) return; //page change
-        this.fetchGame((game) => {
-          if (!!game)
-            // This is my game: just reload.
-            this.loadGame(game);
-          else
-            // Just ask fullgame again (once!), this is much simpler.
-            // If this fails, the user could just reload page :/
-            this.send("askfullgame");
-        });
-      };
-      // Delay of at least 2s between two game requests
-      const now = Date.now();
-      const delay = Math.max(2000 - (now - this.askGameTime), 0);
-      this.askGameTime = now;
-      setTimeout(doAskGame, delay);
-    },
     socketMessageListener: function(msg) {
       if (!this.conn) return;
       const data = JSON.parse(msg.data);
@@ -745,10 +734,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 - 1 > this.gotMoveIdx)
+            this.gotMoveIdx = this.lastate.movesCount - 1;
           if (this.game.rendered)
             // Game is rendered (Board component)
             this.processLastate();
@@ -756,63 +750,77 @@ 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) {
-            // This can only happen if I'm an observer and missed a move.
-            if (this.gotMoveIdx < movePlus.index)
-              this.gotMoveIdx = movePlus.index;
-            if (!this.gameIsLoading) this.askGameAgain();
+          if (
+            movePlus.index < movesCount ||
+            this.gotMoveIdx >= movePlus.index
+          ) {
+            // Opponent re-send but we already have the move:
+            // (maybe he didn't receive our pingback...)
+            this.send("gotmove", {data: movePlus.index, target: data.from});
           }
           else {
-            if (
-              movePlus.index < movesCount ||
-              this.gotMoveIdx >= movePlus.index
-            ) {
-              // Opponent re-send but we already have the move:
-              // (maybe he didn't receive our pingback...)
-              this.send("gotmove", {data: movePlus.index, target: data.from});
-            } else {
-              this.gotMoveIdx = movePlus.index;
-              const receiveMyMove = (movePlus.color == this.game.mycolor);
-              const moveColIdx = ["w", "b"].indexOf(movePlus.color);
-              if (!receiveMyMove && !!this.game.mycolor) {
-                // Notify opponent that I got the move:
-                this.send(
-                  "gotmove",
-                  { data: movePlus.index, target: data.from }
+            this.gotMoveIdx = movePlus.index;
+            const receiveMyMove = (movePlus.color == this.game.mycolor);
+            const moveColIdx = ["w", "b"].indexOf(movePlus.color);
+            if (!receiveMyMove && !!this.game.mycolor) {
+              // Notify opponent that I got the move:
+              this.send(
+                "gotmove",
+                { data: movePlus.index, target: data.from }
+              );
+              // And myself if I'm elsewhere:
+              if (!this.focus) {
+                notify(
+                  "New move",
+                  {
+                    body:
+                      (this.game.players[moveColIdx].name || "@nonymous") +
+                      " just played."
+                  }
                 );
-                // And myself if I'm elsewhere:
-                if (!this.focus) {
-                  notify(
-                    "New move",
-                    {
-                      body:
-                        (this.game.players[moveColIdx].name || "@nonymous") +
-                        " just played."
-                    }
-                  );
-                }
               }
-              if (movePlus.cancelDrawOffer) {
-                // Opponent refuses draw
-                this.drawOffer = "";
-                // NOTE for corr games: drawOffer reset by player in turn
-                if (
-                  this.game.type == "live" &&
-                  !!this.game.mycolor &&
-                  !receiveMyMove
-                ) {
-                  GameStorage.update(this.gameRef, { drawOffer: "" });
-                }
+            }
+            if (movePlus.cancelDrawOffer) {
+              // Opponent refuses draw
+              this.drawOffer = "";
+              // NOTE for corr games: drawOffer reset by player in turn
+              if (
+                this.game.type == "live" &&
+                !!this.game.mycolor &&
+                !receiveMyMove
+              ) {
+                GameStorage.update(this.gameRef, { drawOffer: "" });
               }
-              this.$refs["basegame"].play(movePlus.move, "received");
-              this.game.clocks[moveColIdx] = movePlus.clock;
-              this.processMove(
-                movePlus.move,
-                { receiveMyMove: receiveMyMove }
-              );
             }
+            this.$refs["basegame"].play(movePlus.move, "received");
+            // 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
+            );
           }
           break;
         }
@@ -868,6 +876,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);
@@ -1014,6 +1023,7 @@ export default {
           // Game state (including FEN): will be updated
           moves: [],
           clocks: [-1, -1], //-1 = unstarted
+          chats: [],
           score: "*"
         }
       );
@@ -1034,7 +1044,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
         };
@@ -1104,7 +1114,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 (
@@ -1230,30 +1243,22 @@ export default {
         game
       );
       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
-        let boardDiv = document.querySelector(".game");
-        if (!!boardDiv && boardDiv.style.visibility == "hidden")
-          boardDiv.style.visibility = "visible";
-      }
+      // Initial loading:
+      this.gotMoveIdx = game.moves.length - 1;
+      // If we arrive here after 'nextGame' action, the board might be hidden
+      let boardDiv = document.querySelector(".game");
+      if (!!boardDiv && boardDiv.style.visibility == "hidden")
+        boardDiv.style.visibility = "visible";
       this.re_setClocks();
       this.$nextTick(() => {
         this.game.rendered = true;
         // Did lastate arrive before game was rendered?
-        if (this.lastate) this.processLastate();
+        if (!!this.lastate) this.processLastate();
       });
       if (this.lastateAsked) {
         this.lastateAsked = false;
         this.sendLastate(game.oppsid);
       }
-      if (this.gameIsLoading) {
-        this.gameIsLoading = false;
-        if (this.gotMoveIdx >= game.moves.length)
-          // Some moves arrived meanwhile...
-          this.askGameAgain();
-      }
       if (!!callback) callback();
     },
     loadVariantThenGame: async function(game, callback) {
@@ -1481,7 +1486,7 @@ export default {
           this.opponentGotMove = false;
           this.send("newmove", {data: sendMove});
           // If the opponent doesn't reply gotmove soon enough, re-send move:
-          // Do this at most 2 times, because mpore would mean network issues,
+          // Do this at most 2 times, because more would mean network issues,
           // opponent would then be expected to disconnect/reconnect.
           let counter = 1;
           const currentUrl = document.location.href;
@@ -1513,6 +1518,7 @@ export default {
       };
       if (
         this.game.type == "corr" &&
+        V.CorrConfirm &&
         moveCol == this.game.mycolor &&
         !data.receiveMyMove
       ) {
@@ -1556,7 +1562,8 @@ export default {
           });
           document.querySelector("#confirmDiv > .card").style.width =
             boardDiv.offsetWidth + "px";
-        } else {
+        }
+        else {
           // Incomplete information: just ask confirmation
           // Hide the board, because otherwise it could reveal infos
           boardDiv.style.visibility = "hidden";
@@ -1588,7 +1595,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
@@ -1682,6 +1692,13 @@ button
 #aboveBoard
   text-align: center
 
+.user-bio
+  display: inline
+  font-size: 1.5rem
+  @media screen and (max-width: 767px)
+    font-size: 1.2rem
+  padding: 0 3px
+
 .variant-cadence
   padding-right: 10px
 
@@ -1701,12 +1718,6 @@ span.separator
   padding: 0
   width: 10px
 
-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)
@@ -1746,19 +1757,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
@@ -1775,11 +1786,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))
 </style>
 
 <style lang="sass">