metamaps--metamaps/frontend/src/Metamaps/Views/ChatView.js
Connor Turland 3868910dde Stream map related events from rails server via actioncable instead of nodejs (#1010)
* actioncable needs puma not webrick

* add framework

* remove the old way

* send events from server to client

* get all events working

* clean up receivable

* map is polymorphic on message

* add the moved event

* make todo comments clear

* verify before streaming from map channel

* rubocop fixes

* wasn't set up correctly for nodejs realtime
2017-01-03 16:12:58 -05:00

210 lines
6.1 KiB
JavaScript

/* global $ */
import Backbone from 'backbone'
import { Howl } from 'howler'
import React from 'react'
import ReactDOM from 'react-dom'
// TODO is this line good or bad
// Backbone.$ = window.$
import Active from '../Active'
import DataModel from '../DataModel'
import Realtime from '../Realtime'
import MapChat from '../../components/MapChat'
const ChatView = {
isOpen: false,
messages: new Backbone.Collection(),
conversationLive: false,
isParticipating: false,
mapChat: null,
domId: 'chat-box-wrapper',
init: function(urls) {
const self = ChatView
self.sound = new Howl({
src: urls,
sprite: {
joinmap: [0, 561],
leavemap: [1000, 592],
receivechat: [2000, 318],
sendchat: [3000, 296],
sessioninvite: [4000, 5393, true]
}
})
},
setNewMap: function() {
const self = ChatView
self.conversationLive = false
self.isParticipating = false
self.alertSound = true // whether to play sounds on arrival of new messages or not
self.cursorsShowing = true
self.videosShowing = true
self.participants = new Backbone.Collection()
self.render()
},
show: () => {
$('#' + ChatView.domId).show()
},
hide: () => {
$('#' + ChatView.domId).hide()
},
render: () => {
if (!Active.Map) return
const self = ChatView
self.mapChat = ReactDOM.render(React.createElement(MapChat, {
conversationLive: self.conversationLive,
isParticipating: self.isParticipating,
onOpen: self.onOpen,
onClose: self.onClose,
leaveCall: Realtime.leaveCall,
joinCall: Realtime.joinCall,
inviteACall: Realtime.inviteACall,
inviteToJoin: Realtime.inviteToJoin,
participants: self.participants.models.map(p => p.attributes),
messages: self.messages.models.map(m => m.attributes),
videoToggleClick: self.videoToggleClick,
cursorToggleClick: self.cursorToggleClick,
soundToggleClick: self.soundToggleClick,
inputBlur: self.inputBlur,
inputFocus: self.inputFocus,
handleInputMessage: self.handleInputMessage
}), document.getElementById(ChatView.domId))
},
onOpen: () => {
$(document).trigger(ChatView.events.openTray)
},
onClose: () => {
$(document).trigger(ChatView.events.closeTray)
},
addParticipant: participant => {
ChatView.participants.add(participant)
ChatView.render()
},
removeParticipant: participant => {
ChatView.participants.remove(participant)
ChatView.render()
},
leaveConversation: () => {
ChatView.isParticipating = false
ChatView.render()
},
mapperJoinedCall: id => {
const mapper = ChatView.participants.findWhere({id})
mapper && mapper.set('isParticipating', true)
ChatView.render()
},
mapperLeftCall: id => {
const mapper = ChatView.participants.findWhere({id})
mapper && mapper.set('isParticipating', false)
ChatView.render()
},
invitationPending: id => {
const mapper = ChatView.participants.findWhere({id})
mapper && mapper.set('isPending', true)
ChatView.render()
},
invitationAnswered: id => {
const mapper = ChatView.participants.findWhere({id})
mapper && mapper.set('isPending', false)
ChatView.render()
},
conversationInProgress: participating => {
ChatView.conversationLive = true
ChatView.isParticipating = participating
ChatView.render()
},
conversationEnded: () => {
ChatView.conversationLive = false
ChatView.isParticipating = false
ChatView.participants.forEach(p => p.set({isParticipating: false, isPending: false}))
ChatView.render()
},
close: () => {
ChatView.mapChat && ChatView.mapChat.close()
},
open: () => {
ChatView.mapChat && ChatView.mapChat.open()
},
videoToggleClick: function() {
ChatView.videosShowing = !ChatView.videosShowing
$(document).trigger(ChatView.videosShowing ? ChatView.events.videosOn : ChatView.events.videosOff)
},
cursorToggleClick: function() {
ChatView.cursorsShowing = !ChatView.cursorsShowing
$(document).trigger(ChatView.cursorsShowing ? ChatView.events.cursorsOn : ChatView.events.cursorsOff)
},
soundToggleClick: function() {
ChatView.alertSound = !ChatView.alertSound
},
inputFocus: () => {
$(document).trigger(ChatView.events.inputFocus)
},
inputBlur: () => {
$(document).trigger(ChatView.events.inputBlur)
},
addMessage: (message, isInitial, wasMe) => {
const self = ChatView
if (!isInitial) self.mapChat.newMessage()
if (!wasMe && !isInitial && self.alertSound) self.sound.play('receivechat')
self.messages.add(message)
self.render()
if (!isInitial) self.mapChat.scroll()
},
sendChatMessage: message => {
var self = ChatView
if (ChatView.alertSound) ChatView.sound.play('sendchat')
var m = new DataModel.Message({
message: message.message,
resource_id: Active.Map.id,
resource_type: 'Map'
})
m.save(null, {
success: function(model, response) {
self.addMessages(new DataModel.MessageCollection(model), false, true)
},
error: function(model, response) {
console.log('error!', response)
}
})
},
handleInputMessage: text => {
ChatView.sendChatMessage({message: text})
},
// they should be instantiated as backbone models before they get
// passed to this function
addMessages: (messages, isInitial, wasMe) => {
messages.models.forEach(m => ChatView.addMessage(m, isInitial, wasMe))
},
reset: () => {
ChatView.mapChat && ChatView.mapChat.reset()
ChatView.participants && ChatView.participants.reset()
ChatView.messages && ChatView.messages.reset()
ChatView.render()
}
}
// ChatView.prototype.scrollMessages = function(duration) {
// duration = duration || 0
// this.$messages.animate({
// scrollTop: this.$messages[0].scrollHeight
// }, duration)
// }
/**
* @class
* @static
*/
ChatView.events = {
openTray: 'ChatView:openTray',
closeTray: 'ChatView:closeTray',
inputFocus: 'ChatView:inputFocus',
inputBlur: 'ChatView:inputBlur',
cursorsOff: 'ChatView:cursorsOff',
cursorsOn: 'ChatView:cursorsOn',
videosOff: 'ChatView:videosOff',
videosOn: 'ChatView:videosOn'
}
export default ChatView