removed management of chatview from room

This commit is contained in:
Connor Turland 2016-12-20 12:08:32 -05:00
parent 34a44dccd6
commit 13f8557f80
9 changed files with 134 additions and 207 deletions

View file

@ -174,8 +174,6 @@ let Realtime = {
self.room = new Views.Room({ self.room = new Views.Room({
webrtc: self.webrtc, webrtc: self.webrtc,
socket: self.socket, socket: self.socket,
username: Active.Mapper ? Active.Mapper.get('name') : '',
image: Active.Mapper ? Active.Mapper.get('image') : '',
room: 'global', room: 'global',
$video: self.localVideo.$video, $video: self.localVideo.$video,
myVideoView: self.localVideo.view, myVideoView: self.localVideo.view,
@ -187,26 +185,26 @@ let Realtime = {
addJuntoListeners: function() { addJuntoListeners: function() {
var self = Realtime var self = Realtime
$(document).on(Views.ChatView.events.openTray, function() { $(document).on(ChatView.events.openTray, function() {
$('.main').addClass('compressed') $('.main').addClass('compressed')
self.chatOpen = true self.chatOpen = true
self.positionPeerIcons() self.positionPeerIcons()
}) })
$(document).on(Views.ChatView.events.closeTray, function() { $(document).on(ChatView.events.closeTray, function() {
$('.main').removeClass('compressed') $('.main').removeClass('compressed')
self.chatOpen = false self.chatOpen = false
self.positionPeerIcons() self.positionPeerIcons()
}) })
$(document).on(Views.ChatView.events.videosOn, function() { $(document).on(ChatView.events.videosOn, function() {
$('#wrapper').removeClass('hideVideos') $('#wrapper').removeClass('hideVideos')
}) })
$(document).on(Views.ChatView.events.videosOff, function() { $(document).on(ChatView.events.videosOff, function() {
$('#wrapper').addClass('hideVideos') $('#wrapper').addClass('hideVideos')
}) })
$(document).on(Views.ChatView.events.cursorsOn, function() { $(document).on(ChatView.events.cursorsOn, function() {
$('#wrapper').removeClass('hideCursors') $('#wrapper').removeClass('hideCursors')
}) })
$(document).on(Views.ChatView.events.cursorsOff, function() { $(document).on(ChatView.events.cursorsOff, function() {
$('#wrapper').addClass('hideCursors') $('#wrapper').addClass('hideCursors')
}) })
}, },
@ -218,7 +216,7 @@ let Realtime = {
self.setupSocket() self.setupSocket()
self.setupLocalSendables() self.setupLocalSendables()
} }
self.room.addMessages(new DataModel.MessageCollection(DataModel.Messages), true) self.setupChat() // chat can happen on public maps too
} }
}, },
endActiveMap: function() { endActiveMap: function() {
@ -228,16 +226,14 @@ let Realtime = {
if (self.inConversation) self.leaveCall() if (self.inConversation) self.leaveCall()
self.leaveMap() self.leaveMap()
$('.collabCompass').remove() $('.collabCompass').remove()
if (self.room) { if (self.room) self.room.leave()
self.room.leave()
ChatView.hide() ChatView.hide()
ChatView.close() ChatView.close()
} ChatView.reset()
}, },
turnOn: function(notify) { turnOn: function(notify) {
var self = Realtime var self = Realtime
$('.collabCompass').show() $('.collabCompass').show()
ChatView.show()
self.room.room = 'map-' + Active.Map.id self.room.room = 'map-' + Active.Map.id
self.activeMapper = { self.activeMapper = {
id: Active.Mapper.id, id: Active.Mapper.id,
@ -250,7 +246,13 @@ let Realtime = {
self.localVideo.view.$container.find('.video-cutoff').css({ self.localVideo.view.$container.find('.video-cutoff').css({
border: '4px solid ' + self.activeMapper.color border: '4px solid ' + self.activeMapper.color
}) })
},
setupChat: function() {
const self = Realtime
ChatView.setNewMap(self.room.room)
ChatView.addParticipant(self.activeMapper) ChatView.addParticipant(self.activeMapper)
ChatView.addMessages(new DataModel.MessageCollection(DataModel.Messages), true)
ChatView.show()
}, },
setupSocket: function() { setupSocket: function() {
var self = Realtime var self = Realtime
@ -324,7 +326,7 @@ let Realtime = {
var createMessage = function(event, data) { var createMessage = function(event, data) {
self.createMessage(data) self.createMessage(data)
} }
$(document).on(Views.Room.events.newMessage + '.map', createMessage) $(document).on(ChatView.events.newMessage + '.map', createMessage)
}, },
countOthersInConversation: function() { countOthersInConversation: function() {
var self = Realtime var self = Realtime
@ -395,7 +397,7 @@ let Realtime = {
callEnded: function() { callEnded: function() {
var self = Realtime var self = Realtime
self.room.conversationEnding() ChatView.conversationEnded()
self.room.leaveVideoOnly() self.room.leaveVideoOnly()
self.inConversation = false self.inConversation = false
self.localVideo.view.$container.hide().css({ self.localVideo.view.$container.hide().css({

View file

@ -9,6 +9,7 @@ import { indexOf } from 'lodash'
import { JUNTO_UPDATED } from './events' import { JUNTO_UPDATED } from './events'
import Active from '../Active' import Active from '../Active'
import { ChatView } from '../Views'
import DataModel from '../DataModel' import DataModel from '../DataModel'
import GlobalUI from '../GlobalUI' import GlobalUI from '../GlobalUI'
import Control from '../Control' import Control from '../Control'
@ -152,7 +153,7 @@ export const topicCreated = self => data => {
} }
export const messageCreated = self => data => { export const messageCreated = self => data => {
self.room.addMessages(new DataModel.MessageCollection(data)) ChatView.addMessages(new DataModel.MessageCollection(data))
} }
export const mapUpdated = self => data => { export const mapUpdated = self => data => {
@ -230,10 +231,10 @@ export const lostMapper = self => data => {
// data.userid // data.userid
// data.username // data.username
delete self.mappersOnMap[data.userid] delete self.mappersOnMap[data.userid]
self.room.chat.sound.play('leavemap') ChatView.sound.play('leavemap')
// $('#mapper' + data.userid).remove() // $('#mapper' + data.userid).remove()
$('#compass' + data.userid).remove() $('#compass' + data.userid).remove()
self.room.chat.removeParticipant(data.username) ChatView.removeParticipant(data.username)
GlobalUI.notifyUser(data.username + ' just left the map') GlobalUI.notifyUser(data.username + ' just left the map')
@ -262,8 +263,8 @@ export const mapperListUpdated = self => data => {
} }
if (data.userid !== Active.Mapper.id) { if (data.userid !== Active.Mapper.id) {
self.room.chat.addParticipant(self.mappersOnMap[data.userid]) ChatView.addParticipant(self.mappersOnMap[data.userid])
if (data.userinconversation) self.room.chat.mapperJoinedCall(data.userid) if (data.userinconversation) ChatView.mapperJoinedCall(data.userid)
// create a div for the collaborators compass // create a div for the collaborators compass
self.createCompass(data.username, data.userid, data.avatar, self.mappersOnMap[data.userid].color) self.createCompass(data.username, data.userid, data.avatar, self.mappersOnMap[data.userid].color)
@ -291,8 +292,8 @@ export const newMapper = self => data => {
// create an item for them in the realtime box // create an item for them in the realtime box
if (data.userid !== Active.Mapper.id) { if (data.userid !== Active.Mapper.id) {
self.room.chat.sound.play('joinmap') ChatView.sound.play('joinmap')
self.room.chat.addParticipant(self.mappersOnMap[data.userid]) ChatView.addParticipant(self.mappersOnMap[data.userid])
// create a div for the collaborators compass // create a div for the collaborators compass
self.createCompass(data.username, data.userid, data.avatar, self.mappersOnMap[data.userid].color) self.createCompass(data.username, data.userid, data.avatar, self.mappersOnMap[data.userid].color)
@ -311,24 +312,24 @@ export const callAccepted = self => userid => {
// const username = self.mappersOnMap[userid].name // const username = self.mappersOnMap[userid].name
GlobalUI.notifyUser('Conversation starting...') GlobalUI.notifyUser('Conversation starting...')
self.joinCall() self.joinCall()
self.room.chat.invitationAnswered(userid) ChatView.invitationAnswered(userid)
} }
export const callDenied = self => userid => { export const callDenied = self => userid => {
var username = self.mappersOnMap[userid].name var username = self.mappersOnMap[userid].name
GlobalUI.notifyUser(username + " didn't accept your invitation") GlobalUI.notifyUser(username + " didn't accept your invitation")
self.room.chat.invitationAnswered(userid) ChatView.invitationAnswered(userid)
} }
export const inviteDenied = self => userid => { export const inviteDenied = self => userid => {
var username = self.mappersOnMap[userid].name var username = self.mappersOnMap[userid].name
GlobalUI.notifyUser(username + " didn't accept your invitation") GlobalUI.notifyUser(username + " didn't accept your invitation")
self.room.chat.invitationAnswered(userid) ChatView.invitationAnswered(userid)
} }
export const invitedToCall = self => inviter => { export const invitedToCall = self => inviter => {
self.room.chat.sound.stop(self.soundId) ChatView.sound.stop(self.soundId)
self.soundId = self.room.chat.sound.play('sessioninvite') self.soundId = ChatView.sound.play('sessioninvite')
var username = self.mappersOnMap[inviter].name var username = self.mappersOnMap[inviter].name
var notifyText = '<img src="' + self['junto_spinner_darkgrey.gif'] + '" style="display: inline-block; margin-top: -12px; margin-bottom: -6px; vertical-align: top;" />' var notifyText = '<img src="' + self['junto_spinner_darkgrey.gif'] + '" style="display: inline-block; margin-top: -12px; margin-bottom: -6px; vertical-align: top;" />'
@ -341,8 +342,8 @@ export const invitedToCall = self => inviter => {
} }
export const invitedToJoin = self => inviter => { export const invitedToJoin = self => inviter => {
self.room.chat.sound.stop(self.soundId) ChatView.sound.stop(self.soundId)
self.soundId = self.room.chat.sound.play('sessioninvite') self.soundId = ChatView.sound.play('sessioninvite')
var username = self.mappersOnMap[inviter].name var username = self.mappersOnMap[inviter].name
var notifyText = username + ' is inviting you to the conversation. Join?' var notifyText = username + ' is inviting you to the conversation. Join?'
@ -355,16 +356,14 @@ export const invitedToJoin = self => inviter => {
export const mapperJoinedCall = self => id => { export const mapperJoinedCall = self => id => {
var mapper = self.mappersOnMap[id] var mapper = self.mappersOnMap[id]
if (mapper) { if (mapper) {
if (self.inConversation) { if (self.inConversation) {
var username = mapper.name var username = mapper.name
var notifyText = username + ' joined the call' var notifyText = username + ' joined the call'
GlobalUI.notifyUser(notifyText) GlobalUI.notifyUser(notifyText)
} }
mapper.inConversation = true mapper.inConversation = true
self.room.chat.mapperJoinedCall(id) ChatView.mapperJoinedCall(id)
} }
} }
@ -377,7 +376,7 @@ export const mapperLeftCall = self => id => {
GlobalUI.notifyUser(notifyText) GlobalUI.notifyUser(notifyText)
} }
mapper.inConversation = false mapper.inConversation = false
self.room.chat.mapperLeftCall(id) ChatView.mapperLeftCall(id)
if ((self.inConversation && self.countOthersInConversation() === 0) || if ((self.inConversation && self.countOthersInConversation() === 0) ||
(!self.inConversation && self.countOthersInConversation() === 1)) { (!self.inConversation && self.countOthersInConversation() === 1)) {
self.callEnded() self.callEnded()
@ -392,8 +391,7 @@ export const callInProgress = self => () => {
GlobalUI.notifyUser(notifyText, true) GlobalUI.notifyUser(notifyText, true)
$('#toast button.yes').click(e => self.joinCall()) $('#toast button.yes').click(e => self.joinCall())
$('#toast button.no').click(e => GlobalUI.clearNotify()) $('#toast button.no').click(e => GlobalUI.clearNotify())
ChatView.conversationInProgress()
self.room.conversationInProgress()
} }
export const callStarted = self => () => { export const callStarted = self => () => {
@ -404,7 +402,6 @@ export const callStarted = self => () => {
GlobalUI.notifyUser(notifyText, true) GlobalUI.notifyUser(notifyText, true)
$('#toast button.yes').click(e => self.joinCall()) $('#toast button.yes').click(e => self.joinCall())
$('#toast button.no').click(e => GlobalUI.clearNotify()) $('#toast button.no').click(e => GlobalUI.clearNotify())
ChatView.conversationInProgress()
self.room.conversationInProgress()
} }

View file

@ -1,6 +1,7 @@
/* global $ */ /* global $ */
import Active from '../Active' import Active from '../Active'
import { ChatView } from '../Views'
import GlobalUI from '../GlobalUI' import GlobalUI from '../GlobalUI'
import { import {
@ -72,6 +73,7 @@ export const joinCall = self => () => {
$('#wrapper').append(self.localVideo.view.$container) $('#wrapper').append(self.localVideo.view.$container)
} }
self.room.join() self.room.join()
ChatView.conversationInProgress(true)
}) })
self.inConversation = true self.inConversation = true
self.socket.emit(JOIN_CALL, { self.socket.emit(JOIN_CALL, {
@ -80,7 +82,7 @@ export const joinCall = self => () => {
}) })
self.webrtc.startLocalVideo() self.webrtc.startLocalVideo()
GlobalUI.clearNotify() GlobalUI.clearNotify()
self.room.chat.mapperJoinedCall(Active.Mapper.id) ChatView.mapperJoinedCall(Active.Mapper.id)
} }
export const leaveCall = self => () => { export const leaveCall = self => () => {
@ -89,7 +91,8 @@ export const leaveCall = self => () => {
id: Active.Mapper.id id: Active.Mapper.id
}) })
self.room.chat.mapperLeftCall(Active.Mapper.id) ChatView.mapperLeftCall(Active.Mapper.id)
ChatView.leaveConversation() // the conversation will carry on without you
self.room.leaveVideoOnly() self.room.leaveVideoOnly()
self.inConversation = false self.inConversation = false
self.localVideo.view.$container.hide() self.localVideo.view.$container.hide()
@ -102,7 +105,7 @@ export const leaveCall = self => () => {
} }
export const acceptCall = self => userid => { export const acceptCall = self => userid => {
self.room.chat.sound.stop(self.soundId) ChatView.sound.stop(self.soundId)
self.socket.emit(ACCEPT_CALL, { self.socket.emit(ACCEPT_CALL, {
mapid: Active.Map.id, mapid: Active.Map.id,
invited: Active.Mapper.id, invited: Active.Mapper.id,
@ -114,7 +117,7 @@ export const acceptCall = self => userid => {
} }
export const denyCall = self => userid => { export const denyCall = self => userid => {
self.room.chat.sound.stop(self.soundId) ChatView.sound.stop(self.soundId)
self.socket.emit(DENY_CALL, { self.socket.emit(DENY_CALL, {
mapid: Active.Map.id, mapid: Active.Map.id,
invited: Active.Mapper.id, invited: Active.Mapper.id,
@ -124,7 +127,7 @@ export const denyCall = self => userid => {
} }
export const denyInvite = self => userid => { export const denyInvite = self => userid => {
self.room.chat.sound.stop(self.soundId) ChatView.sound.stop(self.soundId)
self.socket.emit(DENY_INVITE, { self.socket.emit(DENY_INVITE, {
mapid: Active.Map.id, mapid: Active.Map.id,
invited: Active.Mapper.id, invited: Active.Mapper.id,
@ -139,7 +142,7 @@ export const inviteACall = self => userid => {
inviter: Active.Mapper.id, inviter: Active.Mapper.id,
invited: userid invited: userid
}) })
self.room.chat.invitationPending(userid) ChatView.invitationPending(userid)
GlobalUI.clearNotify() GlobalUI.clearNotify()
} }
@ -149,7 +152,7 @@ export const inviteToJoin = self => userid => {
inviter: Active.Mapper.id, inviter: Active.Mapper.id,
invited: userid invited: userid
}) })
self.room.chat.invitationPending(userid) ChatView.invitationPending(userid)
} }
export const sendCoords = self => coords => { export const sendCoords = self => coords => {

View file

@ -2,22 +2,19 @@
import Backbone from 'backbone' import Backbone from 'backbone'
import { Howl } from 'howler' import { Howl } from 'howler'
import Autolinker from 'autolinker'
import { clone, template as lodashTemplate } from 'lodash'
import outdent from 'outdent'
import React from 'react' import React from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
// TODO is this line good or bad // TODO is this line good or bad
// Backbone.$ = window.$ // Backbone.$ = window.$
import Active from '../Active' import Active from '../Active'
import DataModel from '../DataModel'
import Realtime from '../Realtime' import Realtime from '../Realtime'
import MapChat from '../../components/MapChat' import MapChat from '../../components/MapChat'
const linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false })
const ChatView = { const ChatView = {
isOpen: false, isOpen: false,
messages: new Backbone.Collection(),
conversationLive: false, conversationLive: false,
isParticipating: false, isParticipating: false,
mapChat: null, mapChat: null,
@ -35,11 +32,9 @@ const ChatView = {
} }
}) })
}, },
setNewMap: function(messages, mapper, room) { setNewMap: function(room) {
const self = ChatView const self = ChatView
self.room = room self.room = room
self.mapper = mapper
self.messages = messages // is a backbone collection
self.conversationLive = false self.conversationLive = false
self.isParticipating = false self.isParticipating = false
self.alertSound = true // whether to play sounds on arrival of new messages or not self.alertSound = true // whether to play sounds on arrival of new messages or not
@ -88,67 +83,26 @@ const ChatView = {
ChatView.participants.remove(participant) ChatView.participants.remove(participant)
ChatView.render() ChatView.render()
}, },
addMessage: (message, isInitial, wasMe) => {
const self = ChatView
if (!isInitial) self.mapChat.newMessage()
function addZero(i) {
if (i < 10) {
i = '0' + i
}
return i
}
var m = clone(message.attributes)
m.timestamp = new Date(m.created_at)
var date = (m.timestamp.getMonth() + 1) + '/' + m.timestamp.getDate()
date += ' ' + addZero(m.timestamp.getHours()) + ':' + addZero(m.timestamp.getMinutes())
m.timestamp = date
m.image = m.user_image
m.message = linker.link(m.message)
self.messages.push(m)
// TODO what is scrollMessages?
// scrollMessages scrolls to the bottom of the div when there's new messages“
// if (!isInitial) self.scrollMessages(200)
self.render()
if (!wasMe && !isInitial && self.alertSound) self.sound.play('receivechat')
},
handleInputMessage: text => {
$(document).trigger(ChatView.events.message + '-' + self.room, [{ message: text }])
},
leaveConversation: () => { leaveConversation: () => {
// TODO refactor
// this.$participants.removeClass('is-participating')
ChatView.isParticipating = false ChatView.isParticipating = false
ChatView.render() ChatView.render()
}, },
mapperJoinedCall: id => { mapperJoinedCall: id => {
// TODO refactor
// this.$participants.find('.participant-' + id).addClass('active')
const mapper = ChatView.participants.findWhere({id}) const mapper = ChatView.participants.findWhere({id})
mapper && mapper.set('isParticipating', true) mapper && mapper.set('isParticipating', true)
ChatView.render() ChatView.render()
}, },
mapperLeftCall: () => { mapperLeftCall: () => {
// TODO refactor
// this.$participants.find('.participant-' + id).removeClass('active')
const mapper = ChatView.participants.findWhere({id}) const mapper = ChatView.participants.findWhere({id})
mapper && mapper.set('isParticipating', false) mapper && mapper.set('isParticipating', false)
ChatView.render() ChatView.render()
}, },
invitationPending: id => { invitationPending: id => {
// TODO refactor
// this.$participants.find('.participant-' + id).addClass('pending')
const mapper = ChatView.participants.findWhere({id}) const mapper = ChatView.participants.findWhere({id})
mapper && mapper.set('isPending', true) mapper && mapper.set('isPending', true)
ChatView.render() ChatView.render()
}, },
invitationAnswered: id => { invitationAnswered: id => {
// TODO refactor
// this.$participants.find('.participant-' + id).removeClass('pending')
const mapper = ChatView.participants.findWhere({id}) const mapper = ChatView.participants.findWhere({id})
mapper && mapper.set('isPending', false) mapper && mapper.set('isPending', false)
ChatView.render() ChatView.render()
@ -161,11 +115,7 @@ const ChatView = {
conversationEnded: () => { conversationEnded: () => {
ChatView.conversationLive = false ChatView.conversationLive = false
ChatView.isParticipating = false ChatView.isParticipating = false
// go through and remove isParticipating from all other participants too ChatView.participants.forEach(p => p.set({isParticipating: false, isPending: false}))
ChatView.render()
},
removeParticipants: () => {
ChatView.participants.remove(ChatView.participants.models)
ChatView.render() ChatView.render()
}, },
close: () => { close: () => {
@ -196,30 +146,51 @@ const ChatView = {
}, },
inputBlur: () => { inputBlur: () => {
$(document).trigger(ChatView.events.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)
// TODO what is scrollMessages?
// scrollMessages scrolls to the bottom of the div when there's new messages“
// if (!isInitial) self.scrollMessages(200)
self.render()
},
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)
$(document).trigger(ChatView.events.newMessage, [model])
},
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.reset()
ChatView.participants.reset()
ChatView.messages.reset()
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')
// }
// ChatView.prototype.conversationEnded = function() {
// this.$conversationInProgress.hide()
// this.$participants.removeClass('is-live')
// this.$participants.removeClass('is-participating')
// this.$button.removeClass('active')
// this.$participants.find('.participant').removeClass('active')
// this.$participants.find('.participant').removeClass('pending')
// }
// ChatView.prototype.addMessage = function(message, isInitial, wasMe) {
// this.messages.add(message)
// Private.addMessage.call(this, message, isInitial, wasMe)
// }
//
// ChatView.prototype.scrollMessages = function(duration) { // ChatView.prototype.scrollMessages = function(duration) {
// duration = duration || 0 // duration = duration || 0
@ -228,18 +199,12 @@ const ChatView = {
// }, duration) // }, duration)
// } // }
// ChatView.prototype.clearMessages = function() {
// this.unreadMessages = 0
// this.$unread.hide()
// this.$messages.empty()
// }
/** /**
* @class * @class
* @static * @static
*/ */
ChatView.events = { ChatView.events = {
message: 'ChatView:message', newMessage: 'ChatView:newMessage',
openTray: 'ChatView:openTray', openTray: 'ChatView:openTray',
closeTray: 'ChatView:closeTray', closeTray: 'ChatView:closeTray',
inputFocus: 'ChatView:inputFocus', inputFocus: 'ChatView:inputFocus',

View file

@ -9,8 +9,6 @@ import attachMediaStream from 'attachmediastream'
import Active from '../Active' import Active from '../Active'
import DataModel from '../DataModel' import DataModel from '../DataModel'
import Realtime from '../Realtime' import Realtime from '../Realtime'
import ChatView from './ChatView'
import VideoView from './VideoView' import VideoView from './VideoView'
const Room = function(opts = {}) { const Room = function(opts = {}) {
@ -19,36 +17,18 @@ const Room = function(opts = {}) {
this.webrtc = opts.webrtc this.webrtc = opts.webrtc
this.room = opts.room this.room = opts.room
this.config = opts.config this.config = opts.config
this.peopleCount = 0
this.$myVideo = opts.$video this.$myVideo = opts.$video
this.myVideo = opts.myVideoView this.myVideo = opts.myVideoView
this.messages = new Backbone.Collection()
this.currentMapper = new Backbone.Model({ name: opts.username, image: opts.image })
ChatView.setNewMap(this.messages, this.currentMapper, this.room)
this.videos = {} this.videos = {}
this.init() this.init()
} }
Room.prototype.join = function(cb) { Room.prototype.join = function(cb) {
this.isActiveRoom = true this.isActiveRoom = true
this.webrtc.joinRoom(this.room, cb) this.webrtc.joinRoom(this.room, cb)
ChatView.conversationInProgress(true) // true indicates participation
}
Room.prototype.conversationInProgress = function() {
ChatView.conversationInProgress(false) // false indicates not participating
}
Room.prototype.conversationEnding = function() {
ChatView.conversationEnded()
} }
Room.prototype.leaveVideoOnly = function() { Room.prototype.leaveVideoOnly = function() {
ChatView.leaveConversation() // the conversation will carry on without you
for (var id in this.videos) { for (var id in this.videos) {
this.removeVideo(id) this.removeVideo(id)
} }
@ -64,14 +44,6 @@ Room.prototype.leave = function() {
this.isActiveRoom = false this.isActiveRoom = false
this.webrtc.leaveRoom() this.webrtc.leaveRoom()
this.webrtc.stopLocalVideo() this.webrtc.stopLocalVideo()
ChatView.conversationEnded()
ChatView.removeParticipants()
ChatView.clearMessages()
this.messages.reset()
}
Room.prototype.setPeopleCount = function(count) {
this.peopleCount = count
} }
Room.prototype.init = function() { Room.prototype.init = function() {
@ -127,11 +99,6 @@ Room.prototype.init = function() {
} }
v.$container.show() v.$container.show()
}) })
var sendChatMessage = function(event, data) {
self.sendChatMessage(data)
}
$(document).on(ChatView.events.message + '-' + this.room, sendChatMessage)
} }
Room.prototype.videoAdded = function(callback) { Room.prototype.videoAdded = function(callback) {
@ -156,41 +123,4 @@ Room.prototype.removeVideo = function(peer) {
} }
} }
Room.prototype.sendChatMessage = function(data) {
var self = this
if (ChatView.alertSound) ChatView.sound.play('sendchat')
var m = new DataModel.Message({
message: data.message,
resource_id: Active.Map.id,
resource_type: 'Map'
})
m.save(null, {
success: function(model, response) {
self.addMessages(new DataModel.MessageCollection(model), false, true)
$(document).trigger(Room.events.newMessage, [model])
},
error: function(model, response) {
console.log('error!', response)
}
})
}
// they should be instantiated as backbone models before they get
// passed to this function
Room.prototype.addMessages = function(messages, isInitial, wasMe) {
var self = this
messages.models.forEach(function(message) {
ChatView.addMessage(message, isInitial, wasMe)
})
}
/**
* @class
* @static
*/
Room.events = {
newMessage: 'Room:newMessage'
}
export default Room export default Room

View file

@ -1,14 +1,31 @@
import React from 'react' import React from 'react'
import Autolinker from 'autolinker'
const linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false })
function addZero(i) {
if (i < 10) {
i = '0' + i
}
return i
}
function formatDate(created_at) {
let date = new Date(created_at)
let formatted = (date.getMonth() + 1) + '/' + date.getDate()
formatted += ' ' + addZero(date.getHours()) + ':' + addZero(date.getMinutes())
return formatted
}
const Message = props => { const Message = props => {
const { user_image, user_name, message, timestamp } = props const { user_image, user_name, message, created_at } = props
return ( return (
<div className="chat-message"> <div className="chat-message">
<div className="chat-message-user"> <div className="chat-message-user">
<img src={user_image} title={user_name} /> <img src={user_image} title={user_name} />
</div> </div>
<div className="chat-message-text">{message}</div> <div className="chat-message-text">{linker.link(message)}</div>
<div className="chat-message-time">{timestamp}</div> <div className="chat-message-time">{formatDate(created_at)}</div>
<div className="clearfloat"></div> <div className="clearfloat"></div>
</div> </div>
) )

View file

@ -11,11 +11,11 @@ class Participant extends Component {
<div className="chat-participant-name"> <div className="chat-participant-name">
{username} {self ? '(me)' : ''} {username} {self ? '(me)' : ''}
</div> </div>
{!conversationLive && <button {!self && !conversationLive && <button
className='button chat-participant-invite-call' className='button chat-participant-invite-call'
onClick={this.props.inviteACall} // Realtime.inviteACall(id) onClick={this.props.inviteACall} // Realtime.inviteACall(id)
/>} />}
{mapperIsLive && !isParticipating && <button {!self && mapperIsLive && !isParticipating && <button
className="button chat-participant-invite-join" className="button chat-participant-invite-join"
onClick={this.props.inviteToJoin} // Realtime.inviteToJoin(id) onClick={this.props.inviteToJoin} // Realtime.inviteToJoin(id)
/>} />}

View file

@ -17,6 +17,17 @@ class MapChat extends Component {
} }
} }
reset = () => {
this.setState({
unreadMessages: 0,
open: false,
messageText: '',
alertSound: true, // whether to play sounds on arrival of new messages or not
cursorsShowing: true,
videosShowing: true
})
}
close = () => { close = () => {
this.setState({open: false}) this.setState({open: false})
this.props.onClose() this.props.onClose()
@ -68,7 +79,7 @@ class MapChat extends Component {
render = () => { render = () => {
const rightOffset = this.state.open ? '0' : '-300px' const rightOffset = this.state.open ? '0' : '-300px'
const { conversationLive } = this.props const { conversationLive, isParticipating, participants, messages } = this.props
const { videosShowing, cursorsShowing, alertSound, unreadMessages } = this.state const { videosShowing, cursorsShowing, alertSound, unreadMessages } = this.state
return ( return (
<div className="chat-box" <div className="chat-box"
@ -100,7 +111,7 @@ class MapChat extends Component {
CHAT CHAT
<div onClick={this.toggleAlertSound} className={`sound-toggle ${alertSound ? '' : 'active'}`}></div> <div onClick={this.toggleAlertSound} className={`sound-toggle ${alertSound ? '' : 'active'}`}></div>
</div> </div>
<div className="chat-button" onClick={this.toggleDrawer}> <div className={`chat-button ${conversationLive ? 'active' : ''}`} onClick={this.toggleDrawer}>
<div className="tooltips">Chat</div> <div className="tooltips">Chat</div>
<Unread count={unreadMessages} /> <Unread count={unreadMessages} />
</div> </div>
@ -136,7 +147,8 @@ MapChat.propTypes = {
image: PropTypes.string, // image url image: PropTypes.string, // image url
self: PropTypes.bool, self: PropTypes.bool,
username: PropTypes.string, username: PropTypes.string,
isParticipating: PropTypes.bool isParticipating: PropTypes.bool,
isPending: PropTypes.bool
})) }))
} }

View file

@ -16,3 +16,4 @@ junto(io, store)
map(io, store) map(io, store)
io.listen(parseInt(process.env.NODE_REALTIME_PORT) || 5000) io.listen(parseInt(process.env.NODE_REALTIME_PORT) || 5000)
console.log('booting up', process.env.NODE_REALTIME_PORT || 5000)