<template lang="pug">
-div
- div
+.row
+ .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
+ // TODO: Chat modal sur petit écran, dans la page pour grand écran
.card.smallpad
h4 Chat
- p(v-for="chat in chats" :class={
- "my-chatmsg": "chat.uid==user.id",
- "opp-chatmsg": "opponents.any(o => o.id == chat.uid)"}
- v-html="chat.msg")
- input#inputChat(type="text" placeholder="st.tr['Type here']"
+ p(v-for="chat in chats" :class="classObject(chat)" v-html="chat.msg")
+ input#inputChat(type="text" :placeholder="st.tr['Type here']"
@keyup.enter="sendChat")
button#sendChatBtn(@click="sendChat") {{ st.tr["Send"] }}
</template>
<script>
-// TODO: myname, opponents (optional, different style), people
-// --> also show messages like "X offers draw" ?
+import { store } from "@/store";
+
export default {
name: "my-chat",
- props: ["opponents","people"],
+ props: ["players"],
data: function() {
return {
+ st: store.state,
chats: [], //chat messages after human game
};
},
-// // TODO: Chat modal sur petit écran, dans la page pour grand écran
-// created: function() {
-// const socketMessageListener = msg => {
-// const data = JSON.parse(msg.data);
-// switch (data.code)
-// {
-// case "newchat":
-// // TODO: new chat just arrived: data contain all informations
-// // (uid, name, message; no need for timestamp, we can use local time here)
-// this.chats.push({msg:data.msg, author:this.oppid});
-// break;
-// // TODO: distinguish these (dis)connect events from their analogs in game.js
-// // TODO: implement and harmonize: opponents and people are arrays, not objects ?!
-// case "connect":
-// this.players.push({name:data.name, id:data.uid});
-// break;
-// case "disconnect":
-// const pIdx = this.players.findIndex(p => p.id == data.uid);
-// this.players.splice(pIdx);
-// break;
-// }
-// };
-// const socketCloseListener = () => {
-// this.conn.addEventListener('message', socketMessageListener);
-// this.conn.addEventListener('close', socketCloseListener);
-// };
-// this.conn.onmessage = socketMessageListener;
-// this.conn.onclose = socketCloseListener;
-// },
-// methods: {
-// // TODO: complete this component
-// sendChat: function() {
-// let chatInput = document.getElementById("input-chat");
-// const chatTxt = chatInput.value;
-// chatInput.value = "";
-// this.chats.push({msg:chatTxt, author:this.myid});
-// this.conn.send(JSON.stringify({
-// code:"newchat", oppid: this.oppid, msg: chatTxt}));
-// },
-//// startChat: function(e) {
-//// document.getElementById("modal-chat").checked = true;
-//// },
+ created: function() {
+ const socketMessageListener = msg => {
+ const data = JSON.parse(msg.data);
+ if (data.code == "newchat") //only event at this level
+ {
+ this.chats.push({msg:data.msg,
+ name:data.name || "@nonymous", sid:data.sid});
+ }
+ };
+ const socketCloseListener = () => {
+ store.socketCloseListener(); //reinitialize connexion (in store.js)
+ this.st.conn.addEventListener('message', socketMessageListener);
+ this.st.conn.addEventListener('close', socketCloseListener);
+ };
+ this.st.conn.onmessage = socketMessageListener;
+ this.st.conn.onclose = socketCloseListener;
},
-});
+ methods: {
+ classObject: function(chat) {
+ return {
+ "my-chatmsg": chat.sid == this.st.user.sid,
+ "opp-chatmsg": this.players.some(
+ p => p.sid == chat.sid && p.sid != this.st.user.sid)
+ };
+ },
+ sendChat: function() {
+ let chatInput = document.getElementById("inputChat");
+ const chatTxt = chatInput.value;
+ chatInput.value = "";
+ const chat = {msg:chatTxt, name: this.st.user.name || "@nonymous",
+ sid:this.st.user.sid};
+ this.chats.push(chat);
+ this.st.conn.send(JSON.stringify({
+ code:"newchat", msg:chatTxt, name:chat.name}));
+ },
+ },
+};
+</script>
+
+<style lang="sass">
+.my-chatmsg
+ color: grey
+.opp-chatmsg
+ color: black
+</style>
button(@click="() => abortGame()") Abort
button(@click="resign") Resign
textarea(v-if="game.score=='*'" v-model="corrMsg")
- Chat(
+ Chat(:players="game.players")
</template>
<!--
// ==> après, implémenter/vérifier les passages de challenges + parties en cours
// observer,
-// when send to chat (or a move), reach only this group (send gid along)
-->
<script>
name: 'my-game',
components: {
BaseGame,
+ Chat,
},
// gameRef: to find the game in (potentially remote) storage
data: function() {
}
},
"ajv": {
- "version": "6.10.2",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
- "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz",
+ "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==",
"requires": {
- "fast-deep-equal": "^2.0.1",
+ "fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
- "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
+ "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
},
"babel-runtime": {
"version": "6.26.0",
}
},
"fast-deep-equal": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
- "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+ "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
},
"fast-json-stable-stringify": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
- "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"file-uri-to-path": {
"version": "1.0.0",
},
"get-stream": {
"version": "3.0.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
"dev": true
},
},
"got": {
"version": "6.7.1",
- "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
+ "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz",
"integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
"dev": true,
"requires": {
},
"dependencies": {
"readable-stream": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
- "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.5.0.tgz",
+ "integrity": "sha512-gSz026xs2LfxBPudDuI41V1lka8cxg64E66SGe78zJlsUofOg/yqwezdIcdfwik6B4h8LFmWPA9ef9X3FiNFLA==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
},
"is-obj": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
"dev": true
},
"nan": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
- "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
- "dev": true,
- "optional": true
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
},
"nanomatch": {
"version": "1.2.13",
}
},
"npm-bundled": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz",
- "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g=="
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
+ "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
+ "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
},
"npm-packlist": {
- "version": "1.4.6",
- "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.6.tgz",
- "integrity": "sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg==",
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.7.tgz",
+ "integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==",
"requires": {
"ignore-walk": "^3.0.1",
"npm-bundled": "^1.0.1"
"dev": true
},
"postcss": {
- "version": "7.0.23",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.23.tgz",
- "integrity": "sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ==",
+ "version": "7.0.26",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.26.tgz",
+ "integrity": "sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA==",
"requires": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
"dev": true
},
"psl": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz",
- "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw=="
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz",
+ "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ=="
},
"pstree.remy": {
"version": "1.1.7",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sanitize-html": {
- "version": "1.20.1",
- "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.20.1.tgz",
- "integrity": "sha512-txnH8TQjaQvg2Q0HY06G6CDJLVYCpbnxrdO0WN8gjCKaU5J0KbyGYhZxx5QJg3WLZ1lB7XU9kDkfrCXUozqptA==",
+ "version": "1.21.1",
+ "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.21.1.tgz",
+ "integrity": "sha512-W6enXSVphVaVbmVbzVngBthR5f5sMmhq3EfPfBlzBzp2WnX8Rnk7NGpP7KmHUc0Y3MVk9tv/+CbpdHchX9ai7g==",
"requires": {
"chalk": "^2.4.1",
"htmlparser2": "^3.10.0",
}
},
"sqlite3": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.0.tgz",
- "integrity": "sha512-RvqoKxq+8pDHsJo7aXxsFR18i+dU2Wp5o12qAJOV5LNcDt+fgJsc2QKKg3sIRfXrN9ZjzY1T7SNe/DFVqAXjaw==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz",
+ "integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==",
"requires": {
"nan": "^2.12.1",
"node-pre-gyp": "^0.11.0",
"request": "^2.87.0"
- },
- "dependencies": {
- "nan": {
- "version": "2.14.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
- "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
- }
}
},
"srcset": {
},
"strip-eof": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
"dev": true
},
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"uuid": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
- "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"v8flags": {
"version": "3.1.1",
"node-cron": "^2.0.3",
"nodemailer": "^5.1.1",
"pug": "^2.0.4",
- "sanitize-html": "^1.20.1",
+ "sanitize-html": "^1.21.1",
"serve-favicon": "~2.5.0",
- "sqlite3": "^4.1.0",
+ "sqlite3": "^4.1.1",
"ws": "^6.2.1"
},
"devDependencies": {
if (!!clients[sid])
return socket.send(JSON.stringify({code:"duplicate"}));
clients[sid] = {sock: socket, page: query["page"]};
- const notifyRoom = (page,code) => {
+ const notifyRoom = (page,code,obj) => {
Object.keys(clients).forEach(k => {
if (k != sid && clients[k].page == page)
- clients[k].sock.send(JSON.stringify({code:code,sid:sid}));
+ {
+ clients[k].sock.send(JSON.stringify(Object.assign(
+ {code:code}, obj)));
+ }
});
};
- notifyRoom(query["page"],"connect");
+ notifyRoom(query["page"],"connect",{sid:sid});
socket.on("message", objtxt => {
let obj = JSON.parse(objtxt);
if (!!obj.target && !clients[obj.target])
k != sid && clients[k].page == curPage)}));
break;
case "pagechange":
- notifyRoom(clients[sid].page, "disconnect");
+ notifyRoom(clients[sid].page, "disconnect", {sid:sid});
clients[sid].page = obj.page;
- notifyRoom(obj.page, "connect");
+ notifyRoom(obj.page, "connect", {sid:sid});
break;
case "askidentity":
clients[obj.target].sock.send(JSON.stringify(
{code:"game", game:obj.game, from:sid}));
break;
case "newchat":
- clients[obj.target].sock.send(JSON.stringify(
- {code:"newchat",msg:obj.msg}));
+ notifyRoom(query["page"], "newchat",
+ {msg:obj.msg, name:obj.name, sid:sid})
break;
// TODO: WebRTC instead in this case (most demanding?)
case "newmove":