Record chat history in live games as well
[vchess.git] / client / src / views / Game.vue
index 13eab11..6ef161f 100644 (file)
@@ -176,6 +176,7 @@ export default {
       // If newmove got no pingback, send again:
       opponentGotMove: false,
       connexionString: "",
+      socketCloseListener: 0,
       // Incomplete info games: show move played
       moveNotation: "",
       // Intervals from setInterval():
@@ -226,12 +227,12 @@ export default {
   },
   methods: {
     cleanBeforeDestroy: function() {
+      clearInterval(this.socketCloseListener);
       document.removeEventListener('visibilitychange', this.visibilityChange);
       if (!!this.askLastate) clearInterval(this.askLastate);
       if (!!this.retrySendmove) clearInterval(this.retrySendmove);
       if (!!this.clockUpdate) clearInterval(this.clockUpdate);
       this.conn.removeEventListener("message", this.socketMessageListener);
-      this.conn.removeEventListener("close", this.socketCloseListener);
       this.send("disconnect");
       this.conn = null;
     },
@@ -308,7 +309,16 @@ export default {
         encodeURIComponent(this.$route.path.match(/\/game\/[a-zA-Z0-9]+/)[0]);
       this.conn = new WebSocket(this.connexionString);
       this.conn.addEventListener("message", this.socketMessageListener);
-      this.conn.addEventListener("close", this.socketCloseListener);
+      this.socketCloseListener = setInterval(
+        () => {
+          if (this.conn.readyState == 3) {
+            this.conn.removeEventListener("message", this.socketMessageListener);
+            this.conn = new WebSocket(this.connexionString);
+            this.conn.addEventListener("message", this.socketMessageListener);
+          }
+        },
+        1000
+      );
       // Socket init required before loading remote game:
       const socketInit = callback => {
         if (this.conn.readyState == 1)
@@ -398,16 +408,22 @@ export default {
       // NOTE: anonymous chats in corr games are not stored on server (TODO?)
       if (this.game.type == "corr" && this.st.user.id > 0)
         this.updateCorrGame({ chat: chat });
+      else if (this.game.type == "live") {
+        chat.added = Date.now();
+        GameStorage.update(this.gameRef, { chat: chat });
+      }
     },
     clearChat: function() {
-      // Nothing more to do if game is live (chats not recorded)
-      if (this.game.type == "corr") {
-        if (!!this.game.mycolor) {
+      if (!!this.game.mycolor) {
+        if (this.game.type == "corr") {
           ajax(
             "/chats",
             "DELETE",
             { data: { gid: this.game.id } }
           );
+        } else {
+          // Live game
+          GameStorage.update(this.gameRef, { delchat: true });
         }
         this.$set(this.game, "chats", []);
       }
@@ -464,10 +480,12 @@ export default {
           // TODO: shuffling and random filtering on server,
           // if the room is really crowded.
           Object.keys(data.sockIds).forEach(sid => {
-            // TODO: test sid != user.sid was already done on server
             if (sid != this.st.user.sid) {
-              this.people[sid] = { tmpIds: data.sockIds[sid] };
               this.send("askidentity", { target: sid });
+              this.people[sid] = { tmpIds: data.sockIds[sid] };
+            } else {
+              // Complete my tmpIds:
+              Object.assign(this.people[sid].tmpIds, data.sockIds[sid]);
             }
           });
           break;
@@ -617,8 +635,13 @@ export default {
           this.send("fullgame", { data: gameToSend, target: data.from });
           break;
         case "fullgame":
-          // Callback "roomInit" to poll clients only after game is loaded
-          this.loadVariantThenGame(data.data, this.roomInit);
+          if (!!data.data.empty) {
+            alert(this.st.tr["The game should be in another tab"]);
+            this.$router.go(-1);
+          }
+          else
+            // Callback "roomInit" to poll clients only after game is loaded
+            this.loadVariantThenGame(data.data, this.roomInit);
           break;
         case "asklastate":
           // Sending informative last state if I played a move or score != "*"
@@ -744,18 +767,19 @@ export default {
           }
           break;
         }
-        case "newchat":
-          this.$refs["chatcomp"].newChat(data.data);
+        case "newchat": {
+          let chat = data.data;
+          this.$refs["chatcomp"].newChat(chat);
+          if (this.game.type == "live") {
+            chat.added = Date.now();
+            GameStorage.update(this.gameRef, { chat: chat });
+          }
           if (!document.getElementById("modalChat").checked)
             document.getElementById("chatBtn").classList.add("somethingnew");
           break;
+        }
       }
     },
-    socketCloseListener: function() {
-      this.conn = new WebSocket(this.connexionString);
-      this.conn.addEventListener("message", this.socketMessageListener);
-      this.conn.addEventListener("close", this.socketCloseListener);
-    },
     updateCorrGame: function(obj, callback) {
       ajax(
         "/games",
@@ -946,7 +970,10 @@ export default {
         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
+      // Live games before 26/03/2020 don't have chat history. TODO: remove next line
+      if (!game.chats) game.chats = [];
+      // Sort chat messages from newest to oldest
+      game.chats.sort((c1, c2) => c2.added - c1.added);
       if (gtype == "corr") {
         // NOTE: clocks in seconds
         game.moves.sort((m1, m2) => m1.idx - m2.idx); //in case of
@@ -959,10 +986,6 @@ export default {
               (Date.now() - game.moves[L-1].played) / 1000;
           }
         }
-        // Sort chat messages from newest to oldest
-        game.chats.sort((c1, c2) => {
-          return c2.added - c1.added;
-        });
         if (myIdx >= 0 && game.score == "*" && game.chats.length > 0) {
           // Did a chat message arrive after my last move?
           let dtLastMove = 0;
@@ -984,6 +1007,12 @@ export default {
         game.moves = game.moves.map(m => m.squares);
       }
       if (gtype == "live") {
+        if (
+          game.chats.length > 0 &&
+          (!game.initime || game.initime < game.chats[0].added)
+        ) {
+          document.getElementById("chatBtn").classList.add("somethingnew");
+        }
         if (game.clocks[0] < 0) {
           // Game is unstarted. clock is ignored until move 2
           game.clocks = [tc.mainTime, tc.mainTime];