From b03487b1b7488b1db203fd6acee610cb1b06b156 Mon Sep 17 00:00:00 2001 From: theorangeone Date: Wed, 15 Aug 2018 00:04:30 -0400 Subject: [PATCH] [chat] add initial implementation --- static/css/locus68.css | 41 ++++++++++++++++++++++++++++++++++ static/js/chat.js | 39 ++++++++++++++++++++++++++++++++ static/js/components.js | 5 +++++ static/js/conf.js | 5 +++-- static/js/locus.js | 48 ++++++++++++++++++++++++++++++++++++++++ static/room.html | 27 ++++++++++++++++++++++ static/test/test_chat.js | 9 ++++++++ 7 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 static/js/chat.js create mode 100644 static/test/test_chat.js diff --git a/static/css/locus68.css b/static/css/locus68.css index 9c10cfc..1d85c75 100644 --- a/static/css/locus68.css +++ b/static/css/locus68.css @@ -78,6 +78,7 @@ h1, h2 { border-style: solid; background-color: grey; background: rgba(187, 187, 187, 0.28); + vertical-align: middle; } .untracked { @@ -384,3 +385,43 @@ https://purecss.io/grids/ color: #E9B872; } +#chat { + display: inline-block; + margin-right: 1em; + vertical-align: middle; +} + +#chat-content { + width: 100%; + font-size: 1.2em; +} + +#chat-toggle { + font-size: 3.0em; +} + +#chat-overlay { + position: fixed; + display: none; + width: 90%; + height: 80%; + top: 0; + bottom: 0; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: #fdf6e3; + z-index: 100000; +} + +#msg-wrapper { + width: 100%; + text-align: center; + position: absolute; + bottom: 0; +} + +.chat-avatar { + width: 1em; + height: 1em; +} diff --git a/static/js/chat.js b/static/js/chat.js new file mode 100644 index 0000000..6668f2b --- /dev/null +++ b/static/js/chat.js @@ -0,0 +1,39 @@ + + +function Chat(opts) { + opts = opts || {}; + this.onAdd = opts.onAdd || function (user, message) {} + + this.messages = []; + + var self = this; + + + // add a new message to the chat + this.add = function(user, message) { + message.ts = message.ts || Date.now(); + self.messages.push({ + img: user.img, + ts: message.ts, + text: message.text + }); + + this.onAdd(user, message); + }; + + this.serialize = function() { + }; + + this.init = function() { + }; + + this.init(); +}; + +Chat.deserialize = function(serChat) { +}; + + +if (typeof window === 'undefined') { + module.exports = Chat; +} diff --git a/static/js/components.js b/static/js/components.js index 6b94983..8af48e3 100644 --- a/static/js/components.js +++ b/static/js/components.js @@ -7,3 +7,8 @@ Vue.component('btn-room', { props: ['text'], template: '' }); + +Vue.component('chat-msg', { + props: ['text'], + template: '' +}); diff --git a/static/js/conf.js b/static/js/conf.js index 4fe5fd0..6fd4c4d 100644 --- a/static/js/conf.js +++ b/static/js/conf.js @@ -40,9 +40,10 @@ function Configuration() { * } */ this.MSG_TYPE = { - USER_UPDATE: 'userup', // general update for a user + USER_UPDATE: 'userup', // general update for a user USER_CONNECT: 'userco', // user connected - USER_DISCONNECT: 'userdc' // user disconnected + USER_DISCONNECT: 'userdc', // user disconnected + USER_MSG: 'usermg' // user disconnected }; var self = this; diff --git a/static/js/locus.js b/static/js/locus.js index 38362d8..9ee51e5 100644 --- a/static/js/locus.js +++ b/static/js/locus.js @@ -4,6 +4,7 @@ if (typeof window === 'undefined') { MsgUser = require('./user.js').MsgUser, User = require('./user.js').User, Users = require('./users.js'), + Chat = require('./chat.js'), Crypt = require('./crypto.js'), Socket = require('./socket.js'), Map = require('./map.js') @@ -34,6 +35,7 @@ function Locus(opts) { this.Map = opts.Map || null; this.WebSocket = opts.WebSocket || null; this.Geolocation = opts.Geolocation || null; + this.Chat = opts.Chat || Chat; this.MSG_HANDLER = {}; // used to look up msg handlers @@ -76,6 +78,10 @@ function Locus(opts) { } }; + this.sendChatMsg = function(msg) { + self.sendMsg(MSG_TYPE.USER_MSG, msg); + }; + // returns a url to the websocket to use for this room and user this.getWSURL = function() { var base = self.host + '/ws/'; @@ -131,6 +137,12 @@ function Locus(opts) { }; this.registerMsgHandler(MSG_TYPE.USER_DISCONNECT, this.onDCMsg); + this.onChatMsg = function(userId, data) { + var otheruser = self.otherUsers.getUser(userId); + self.chat.add(otheruser, data); + }; + this.registerMsgHandler(MSG_TYPE.USER_MSG, this.onChatMsg); + // handle an incoming message this.onMsg = function(msg) { console.assert('user' in msg); @@ -177,6 +189,12 @@ function Locus(opts) { return self.socket.isReady(); }; + this.onChatAdd = function(user, msg) { + if (user.id === self.user.id) { + self.sendChatMsg(msg); + } + }; + this.initComponents = function() { self.settingsVue = new Vue({ el: '#settings-overlay', @@ -221,6 +239,26 @@ function Locus(opts) { } } }); + + self.chatVue = new Vue({ + el: '#chat', + data: { + visible: false, + chat: self.chat + }, + methods: { + toggleVisible: function(e) { + this.visible = !this.visible; + }, + onEnter: function(e) { + if (e.target.value) { + var text = e.target.value; + self.chat.add(self.user, { text: text }); + e.target.value = ''; + } + } + } + }); }; this.initUser = function(lat, lng) { @@ -277,6 +315,12 @@ function Locus(opts) { self.initSocket(WebSocket); }; + this.initChat = function() { + self.chat = new self.Chat({ + onAdd: self.onChatAdd + }); + }; + /** * Once all other initialization has been done, then * it up by generating the map and view components. @@ -290,6 +334,10 @@ function Locus(opts) { * send out our first update to notify other clients. */ this.initFinalize = function() { + + self.initOtherUsers(); + self.initChat(); + if (self.uiEnabled) { self.initMap(); self.initComponents(); diff --git a/static/room.html b/static/room.html index b8a157b..ba4723d 100644 --- a/static/room.html +++ b/static/room.html @@ -183,6 +183,32 @@

> +
+
+ +
+
+
+
+

+ + {{ msg.text }} +

+
+
+ +
+
+
+
@@ -194,6 +220,7 @@

+