From 88419294f1ea7dedcd9a5b5ba5a3c5388c2af339 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 18 Dec 2016 23:24:57 -0500 Subject: [PATCH] in theory this should compile --- frontend/src/Metamaps/Views/ChatView.js | 286 +++++------------- .../src/components/MapChat/Participant.js | 4 +- frontend/src/components/MapChat/index.js | 6 +- 3 files changed, 87 insertions(+), 209 deletions(-) diff --git a/frontend/src/Metamaps/Views/ChatView.js b/frontend/src/Metamaps/Views/ChatView.js index ef6c9e95..f8baf54a 100644 --- a/frontend/src/Metamaps/Views/ChatView.js +++ b/frontend/src/Metamaps/Views/ChatView.js @@ -5,6 +5,8 @@ import { Howl } from 'howler' import Autolinker from 'autolinker' import { clone, template as lodashTemplate } from 'lodash' import outdent from 'outdent' +import React from 'react' +import ReactDOM from 'react-dom' // TODO is this line good or bad // Backbone.$ = window.$ @@ -12,120 +14,22 @@ import MapChat from '../../components/MapChat' const linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false }) -var Private = { - messageHTML: outdent` -
-
-
{{ message }}
-
{{ timestamp }}
-
-
`, - participantHTML: outdent` -
-
- -
-
- {{ username }} {{ selfName }} -
- - - -
-
-
-
`, - templates: function() { - const templateSettings = { - interpolate: /\{\{(.+?)\}\}/g - } +const ChatView = { + init: function(messages, mapper, room, opts = {}) { + const self = ChatView + self.room = room + self.mapper = mapper + self.messages = messages.models.map(m => m.attributes) - this.messageTemplate = lodashTemplate(Private.messageHTML, templateSettings) + self.isOpen = false + self.alertSound = true // whether to play sounds on arrival of new messages or not + self.cursorsShowing = true + self.videosShowing = true + self.unreadMessages = 0 + self.participants = [] - this.participantTemplate = lodashTemplate(Private.participantHTML, templateSettings) - }, - createElements: function() { - this.$unread = $('
') - this.$button = $('
Chat
') - this.$messageInput = $('') - this.$juntoHeader = $('
PARTICIPANTS
') - this.$videoToggle = $('
') - this.$cursorToggle = $('
') - this.$participants = $('
') - this.$conversationInProgress = $(outdent` -
- LIVE - - LEAVE - - - JOIN - -
`) - this.$chatHeader = $('
CHAT
') - this.$soundToggle = $('
') - this.$messages = $('
') - this.$container = $('
') - }, - attachElements: function() { - this.$button.append(this.$unread) - - this.$juntoHeader.append(this.$videoToggle) - this.$juntoHeader.append(this.$cursorToggle) - - this.$chatHeader.append(this.$soundToggle) - - this.$participants.append(this.$conversationInProgress) - - this.$container.append(this.$juntoHeader) - this.$container.append(this.$participants) - this.$container.append(this.$chatHeader) - this.$container.append(this.$button) - this.$container.append(this.$messages) - this.$container.append(this.$messageInput) - }, - addEventListeners: function() { - var self = this - - this.participants.on('add', function(participant) { - Private.addParticipant.call(self, participant) - }) - - this.participants.on('remove', function(participant) { - Private.removeParticipant.call(self, participant) - }) - - this.$button.on('click', function() { - Handlers.buttonClick.call(self) - }) - this.$videoToggle.on('click', function() { - Handlers.videoToggleClick.call(self) - }) - this.$cursorToggle.on('click', function() { - Handlers.cursorToggleClick.call(self) - }) - this.$soundToggle.on('click', function() { - Handlers.soundToggleClick.call(self) - }) - this.$messageInput.on('keyup', function(event) { - Handlers.keyUp.call(self, event) - }) - this.$messageInput.on('focus', function() { - Handlers.inputFocus.call(self) - }) - this.$messageInput.on('blur', function() { - Handlers.inputBlur.call(self) - }) - }, - initializeSounds: function(soundUrls) { - this.sound = new Howl({ - src: soundUrls, + self.sound = new Howl({ + src: opts.soundUrls, sprite: { joinmap: [0, 561], leavemap: [1000, 592], @@ -134,14 +38,67 @@ var Private = { sessioninvite: [4000, 5393, true] } }) + + // TODO move these event handlers into react + // this.$button.on('click', function() { + // Handlers.buttonClick.call(self) + // }) + // this.$videoToggle.on('click', function() { + // Handlers.videoToggleClick.call(self) + // }) + // this.$cursorToggle.on('click', function() { + // Handlers.cursorToggleClick.call(self) + // }) + // this.$soundToggle.on('click', function() { + // Handlers.soundToggleClick.call(self) + // }) + // this.$messageInput.on('keyup', function(event) { + // Handlers.keyUp.call(self, event) + // }) + // this.$messageInput.on('focus', function() { + // Handlers.inputFocus.call(self) + // }) + // this.$messageInput.on('blur', function() { + // Handlers.inputBlur.call(self) + // }) }, - incrementUnread: function() { - this.unreadMessages++ - this.$unread.html(this.unreadMessages) - this.$unread.show() + addWrapper: () => { + $('body').prepend('
') }, - addMessage: function(message, isInitial, wasMe) { - if (!this.isOpen && !isInitial) Private.incrementUnread.call(this) + render: () => { + const self = ChatView + ReactDOM.render(React.createElement(MapChat, { + show: self.show, + leaveCall: Realtime.leaveCall(), + joinCall: Realtime.joinCall(), + participants: self.participants, + unreadMessages: self.unreadMessages + })) + }, + show: () => { + ChatView.show = true + ChatView.render() + }, + hide: () => { + ChatView.show = false + ChatView.render() + }, + addParticipant: participant => { + const p = clone(participant.attributes) + ChatView.participants.push(p) + ChatView.render() + }, + removeParticipant: participant => { + const remove_id = participant.get('id') + ChatView.participants = ChatView.participants.filter(p => p.id !== remove_id) + ChatView.render() + }, + incrementUnread: (render = false) => { + ChatView.unreadMessages += 1 + if (render) ChatView.render() + }, + addMessage: (message, isInitial, wasMe) => { + if (!self.isOpen && !isInitial) ChatView.incrementUnread(false) // TODO don't need to render, right? function addZero(i) { if (i < 10) { @@ -158,40 +115,18 @@ var Private = { m.timestamp = date m.image = m.user_image m.message = linker.link(m.message) - var $html = $(this.messageTemplate(m)) - this.$messages.append($html) + + self.messages.push(m) + // TODO what is scrollMessages? if (!isInitial) this.scrollMessages(200) + self.render() if (!wasMe && !isInitial && this.alertSound) this.sound.play('receivechat') }, - initialMessages: function() { - var messages = this.messages.models - for (var i = 0; i < messages.length; i++) { - Private.addMessage.call(this, messages[i], true) - } + handleInputMessage: text => { + // TODO set textarea to be empty in react + $(document).trigger(ChatView.events.message + '-' + this.room, [{ message: text }]) }, - handleInputMessage: function() { - var message = { - message: this.$messageInput.val() - } - this.$messageInput.val('') - $(document).trigger(ChatView.events.message + '-' + this.room, [message]) - }, - addParticipant: function(participant) { - var p = clone(participant.attributes) - if (p.self) { - p.selfClass = 'is-self' - p.selfName = '(me)' - } else { - p.selfClass = '' - p.selfName = '' - } - var html = this.participantTemplate(p) - this.$participants.append(html) - }, - removeParticipant: function(participant) { - this.$container.find('.participant-' + participant.get('id')).remove() - } } var Handlers = { @@ -228,68 +163,11 @@ var Handlers = { } } -const ChatView = { - init: function(messages, mapper, room, opts = {}) { - const self = ChatView - self.room = room - self.mapper = mapper - self.messages = messages // backbone collection - - self.isOpen = false - self.alertSound = true // whether to play sounds on arrival of new messages or not - self.cursorsShowing = true - self.videosShowing = true - self.unreadMessages = 0 - self.participants = [] - - // TODO reimplement - //Private.addEventListeners.call(this) - //Private.initialMessages.call(this) - //Private.initializeSounds.call(this, opts.soundUrls) - //this.$container.css({ - // right: '-300px' - //}) - }, - addWrapper: () => { - $('body').prepend('
') - }, - render: () => { - const self = ChatView - ReactDOM.render(React.createElement(MapChat, { - show: self.show, - leaveCall: Realtime.leaveCall(), - joinCall: Realtime.joinCall(), - participants: self.participants - })) - } - show: () => { - ChatView.show = true - ChatView.render() - }, - hide: () => { - ChatView.show = false - ChatView.render() - }, - addParticipant: participant => { - const p = clone(participant.attributes) - ChatView.participants.push(p) - ChatView.render() - }, - removeParticipant: participant => { - const remove_id = participant.get('id') - ChatView.participants = ChatView.participants.filter(p => p.id !== remove_id) - ChatView.render() - } -} - - ChatView.prototype.conversationInProgress = function(participating) { this.$conversationInProgress.show() this.$participants.addClass('is-live') if (participating) this.$participants.addClass('is-participating') this.$button.addClass('active') - -// hide invite to call buttons } ChatView.prototype.conversationEnded = function() { diff --git a/frontend/src/components/MapChat/Participant.js b/frontend/src/components/MapChat/Participant.js index b6f28617..cff5f5b9 100644 --- a/frontend/src/components/MapChat/Participant.js +++ b/frontend/src/components/MapChat/Participant.js @@ -29,11 +29,11 @@ class Participant extends Component { } ChatView.propTypes = { - color: PropTypes.string // css color + color: PropTypes.string, // css color id: PropTypes.number, image: PropTypes.string, // image url self: PropTypes.bool, - username: PropTypes.string, + username: PropTypes.string } export default ChatView diff --git a/frontend/src/components/MapChat/index.js b/frontend/src/components/MapChat/index.js index 5f282f84..aa341252 100644 --- a/frontend/src/components/MapChat/index.js +++ b/frontend/src/components/MapChat/index.js @@ -29,7 +29,7 @@ class MapChat extends Component {
Chat
-
+