From 8b090be0b31b0df2d804d68e35bc8cb672a1d0f0 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sat, 12 Dec 2015 19:00:51 -0500 Subject: [PATCH] convert to something more 'call' style --- app/assets/javascripts/src/Metamaps.js.erb | 196 +++++++++++++----- .../javascripts/src/views/chatView.js.erb | 4 +- app/assets/javascripts/src/views/room.js | 18 +- app/assets/javascripts/src/views/videoView.js | 8 +- app/assets/stylesheets/application.css.erb | 59 +++--- app/assets/stylesheets/junto.css.erb | 1 + app/views/layouts/_upperelements.html.erb | 3 +- realtime/realtime-server.js | 23 +- realtime/signal.js | 13 +- 9 files changed, 214 insertions(+), 111 deletions(-) diff --git a/app/assets/javascripts/src/Metamaps.js.erb b/app/assets/javascripts/src/Metamaps.js.erb index 5871a88e..59e701f4 100644 --- a/app/assets/javascripts/src/Metamaps.js.erb +++ b/app/assets/javascripts/src/Metamaps.js.erb @@ -1948,7 +1948,9 @@ Metamaps.Realtime = { console.log('connected'); self.startActiveMap(); }); - self.webrtc = new SimpleWebRTC({ + + if (Metamaps.Active.Mapper) { + self.webrtc = new SimpleWebRTC({ connection: self.socket, localVideoEl: self.videoId, remoteVideosEl: '', @@ -1965,45 +1967,45 @@ Metamaps.Realtime = { audio: true }, nick: Metamaps.Active.Mapper.id - }); - self.webrtc.on('readyToCall', function () { - console.log('readyToCall'); - self.videoInitialized = true; - self.readyToCall = true; - if (self.localVideo && self.status) { - $('#wrapper').append(self.localVideo.view.$container); - } - self.socket.emit('videoAdded'); - self.webrtc.webrtc.peers.forEach(function (p) { - p.pc.addStream(self.webrtc.webrtc.localStream); - p.start(); }); - }); - var - $video = $('').attr('id', self.videoId); - self.localVideo = { - $video: $video, - view: new Metamaps.Views.videoView($video[0], $('body'), 'me', true, { - DOUBLE_CLICK_TOLERANCE: 200, - avatar: Metamaps.Active.Mapper ? Metamaps.Active.Mapper.get('image') : '' - }), - }; + var + $video = $('').attr('id', self.videoId); + self.localVideo = { + $video: $video, + view: new Metamaps.Views.videoView($video[0], $('body'), 'me', true, { + DOUBLE_CLICK_TOLERANCE: 200, + avatar: Metamaps.Active.Mapper ? Metamaps.Active.Mapper.get('image') : '' + }) + }; - self.room = new Metamaps.Views.room({ - webrtc: self.webrtc, - socket: self.socket, - username: Metamaps.Active.Mapper ? Metamaps.Active.Mapper.get('name') : '', - image: Metamaps.Active.Mapper ? Metamaps.Active.Mapper.get('image') : '', - room: 'global', - $video: self.localVideo.$video, - myVideoView: self.localVideo.view, - config: { DOUBLE_CLICK_TOLERANCE: 200 } - }); - if (Metamaps.Messages) self.room.messages.add(Metamaps.Messages); + self.room = new Metamaps.Views.room({ + webrtc: self.webrtc, + socket: self.socket, + username: Metamaps.Active.Mapper ? Metamaps.Active.Mapper.get('name') : '', + image: Metamaps.Active.Mapper ? Metamaps.Active.Mapper.get('image') : '', + room: 'global', + $video: self.localVideo.$video, + myVideoView: self.localVideo.view, + config: { DOUBLE_CLICK_TOLERANCE: 200 } + }); + if (Metamaps.Messages) self.room.messages.add(Metamaps.Messages); + self.room.videoAdded(self.handleVideoAdded); - self.createChat(); - //self.webrtc.startLocalVideo(); + self.createChat(); + } // if Metamaps.Active.Mapper + }, + handleVideoAdded: function (v) { + // random position for now + var top = Math.floor((Math.random() * ($('#wrapper').height() - 100)) + 1); + var left = Math.floor((Math.random() * ($('#wrapper').width() - 100)) + 1); + //var right = Math.floor((Math.random() * (468 - 100)) + 1); + v.setParent($('#wrapper')); + $('#wrapper').append(v.$container); + v.$container.css({ + top: top + 'px', + left: left + 'px' + }); }, startActiveMap: function () { var self = Metamaps.Realtime; @@ -2053,30 +2055,86 @@ Metamaps.Realtime = { self.status = true; //$(".sidebarCollaborateIcon").addClass("blue"); $(".collabCompass").show(); - self.localVideo.view.$container.show(); self.room.room = 'map-' + Metamaps.Active.Map.id; - self.room.join(function (err, roomDesc) { - //attachMediaStream(self.webrtc.webrtc.localStream, self.localVideo.$video[0]); + self.checkForACallToJoin(); + }, + checkForACallToJoin: function () { + var self = Metamaps.Realtime; + self.socket.emit('checkForCall', { room: self.room.room, mapid: Metamaps.Active.Map.id }); + }, + promptToJoin: function (data) { + var self = Metamaps.Realtime; - function addVideo(v) { - // random position for now - var top = Math.floor((Math.random() * ($('#wrapper').height() - 100)) + 1); - var left = Math.floor((Math.random() * ($('#wrapper').width() - 100)) + 1); - //var right = Math.floor((Math.random() * (468 - 100)) + 1); - v.setParent($('#wrapper')); - $('#wrapper').append(v.$container); - v.$container.css({ - top: top + 'px', - left: left + 'px' - }); - } + console.log(data); + var notifyText = 'There\'s a conversation happening, want to join?'; + notifyText += ' '; + notifyText += ' '; + Metamaps.GlobalUI.notifyUser(notifyText); + }, + invitedToCall: function (inviter) { + var self = Metamaps.Realtime; - self.room.videoAdded(addVideo); + var username = self.mappersOnMap[inviter].name; + var notifyText = username + ' is suggesting a video call. What do you think?'; + notifyText += ' '; + notifyText += ' '; + Metamaps.GlobalUI.notifyUser(notifyText); + }, + acceptCall: function (userid) { + var self = Metamaps.Realtime; + self.socket.emit('callAccepted', { + mapid: Metamaps.Active.Map.id, + invited: Metamaps.Active.Mapper.id, + inviter: userid + }); + self.joinCall(); + Metamaps.GlobalUI.clearNotify(); + }, + denyCall: function (userid) { + var self = Metamaps.Realtime; + self.socket.emit('callDenied', { + mapid: Metamaps.Active.Map.id, + invited: Metamaps.Active.Mapper.id, + inviter: userid + }); + Metamaps.GlobalUI.clearNotify(); + }, + inviteACall: function (userid) { + var self = Metamaps.Realtime; + self.socket.emit('inviteACall', { + mapid: Metamaps.Active.Map.id, + inviter: Metamaps.Active.Mapper.id, + invited: userid + }); + }, + callAccepted: function (userid) { + var self = Metamaps.Realtime; - for (peer in self.room.videos) { - addVideo(self.room.videos[peer]); - } - }); + var username = self.mappersOnMap[userid].name; + Metamaps.GlobalUI.notifyUser(username + ' liked your suggestion! Video call starting...'); + self.joinCall(); + }, + callDenied: function (userid) { + var self = Metamaps.Realtime; + + var username = self.mappersOnMap[userid].name; + Metamaps.GlobalUI.notifyUser(username + ' isn\'t feeling it right now...'); + }, + joinCall: function () { + var self = Metamaps.Realtime; + + self.webrtc.off('readyToCall'); + self.webrtc.on('readyToCall', function () { + self.videoInitialized = true; + self.readyToCall = true; + self.localVideo.view.$container.show(); + if (self.localVideo && self.status) { + $('#wrapper').append(self.localVideo.view.$container); + } + self.room.join(); + }); + self.webrtc.startLocalVideo(); + Metamaps.GlobalUI.clearNotify(); }, startVideo: function() { var @@ -2134,6 +2192,13 @@ Metamaps.Realtime = { mapid: Metamaps.Active.Map.id }); + socket.on(myId + '-' + Metamaps.Active.Map.id + '-invitedToCall', self.invitedToCall); + socket.on(myId + '-' + Metamaps.Active.Map.id + '-callAccepted', self.callAccepted); + socket.on(myId + '-' + Metamaps.Active.Map.id + '-callDenied', self.callDenied); + + // receive word that there's a conversation in progress + socket.on('maps-' + Metamaps.Active.Map.id + '-callInProgress', self.promptToJoin); + // if you're the 'new guy' update your list with who's already online socket.on(myId + '-' + Metamaps.Active.Map.id + '-UpdateMapperList', self.updateMapperList); @@ -2244,6 +2309,16 @@ Metamaps.Realtime = { }; $(document).on(Metamaps.Views.room.events.newMessage, sendNewMessage); + $(document).on(Metamaps.Views.room.events.callEnded, function () { + Metamaps.GlobalUI.notifyUser('Conversation has ended.'); + self.localVideo.view.$container.hide(); + self.webrtc.webrtc.localStreams.forEach(function (stream) { + stream.getTracks().forEach(function (track) { + track.stop(); + }); + }); + }); + }, attachMapListener: function(){ var self = Metamaps.Realtime; @@ -2291,6 +2366,7 @@ Metamaps.Realtime = { // data.userrealtime self.mappersOnMap[data.userid] = { + id: data.userid, name: data.username, username: data.username, image: data.userimage, @@ -2330,8 +2406,10 @@ Metamaps.Realtime = { // data.username // data.userimage // data.coords + var firstOtherPerson = Object.keys(self.mappersOnMap).length === 0; self.mappersOnMap[data.userid] = { + id: data.userid, name: data.username, username: data.username, image: data.userimage, @@ -2357,7 +2435,11 @@ Metamaps.Realtime = { // create a div for the collaborators compass self.createCompass(data.username, data.userid, data.userimage, self.mappersOnMap[data.userid].color, !self.status); - Metamaps.GlobalUI.notifyUser(data.username + ' just joined the map'); + var notifyMessage = data.username + ' just joined the map'; + if (firstOtherPerson) { + notifyMessage += ' '; + } + Metamaps.GlobalUI.notifyUser(notifyMessage); // send this new mapper back your details, and the awareness that you've loaded the map var update = { diff --git a/app/assets/javascripts/src/views/chatView.js.erb b/app/assets/javascripts/src/views/chatView.js.erb index 94b46fde..1179d29e 100644 --- a/app/assets/javascripts/src/views/chatView.js.erb +++ b/app/assets/javascripts/src/views/chatView.js.erb @@ -12,7 +12,7 @@ Metamaps.Views.chatView = (function () { "
{{ timestamp }}
" + "
" + "", - participantHTML: "
" + + participantHTML: "
" + "
" + "
{{ username }}
" + "
" + @@ -151,7 +151,7 @@ Metamaps.Views.chatView = (function () { this.$participants.append(html); }, removeParticipant: function(participant) { - this.$container.find('.participant-' + participant.get('username')).remove(); + this.$container.find('.participant-' + participant.get('id')).remove(); } }; diff --git a/app/assets/javascripts/src/views/room.js b/app/assets/javascripts/src/views/room.js index acb0b250..53acd099 100644 --- a/app/assets/javascripts/src/views/room.js +++ b/app/assets/javascripts/src/views/room.js @@ -33,6 +33,11 @@ Metamaps.Views.room = (function () { this.webrtc.joinRoom(this.room, cb); } + room.prototype.leaveVideoOnly = function() { + this.isActiveRoom = false; + this.webrtc.leaveRoom(); + } + room.prototype.leave = function() { for (var id in this.videos) { this.removeVideo(id); @@ -51,10 +56,6 @@ Metamaps.Views.room = (function () { room.prototype.init = function () { var self = this; - /*this.roomRef.child('messages').on('child_added', function (snap) { - self.messages.add(snap.val()); - });*/ - $(document).on(VideoView.events.audioControlClick, function (event, videoView) { if (!videoView.audioStatus) self.webrtc.mute(); else if (videoView.audioStatus) self.webrtc.unmute(); @@ -70,7 +71,6 @@ Metamaps.Views.room = (function () { var mapper = Metamaps.Realtime.mappersOnMap[peer.nick]; peer.avatar = mapper.image; peer.username = mapper.name; - console.log(peer); if (self.isActiveRoom) { self.addVideo(peer); } @@ -148,7 +148,6 @@ Metamaps.Views.room = (function () { id = this.webrtc.getDomId(peer), video = attachMediaStream(peer.stream); - $(video).prop('muted', true); // until the viewer accepts the viewing var v = new VideoView(video, null, id, false, { DOUBLE_CLICK_TOLERANCE: 200, avatar: peer.avatar, username: peer.username }); @@ -162,6 +161,10 @@ Metamaps.Views.room = (function () { if (this.videos[id]) { this.videos[id].remove(); delete this.videos[id]; + if (Object.keys(this.videos).length === 0) { + this.leaveVideoOnly(); + $(document).trigger(room.events.callEnded); + } } } @@ -190,7 +193,8 @@ Metamaps.Views.room = (function () { * @static */ room.events = { - newMessage: "Room:newMessage" + newMessage: "Room:newMessage", + callEnded: "Room:callEnded" }; return room; diff --git a/app/assets/javascripts/src/views/videoView.js b/app/assets/javascripts/src/views/videoView.js index 25229cf6..eb234ece 100644 --- a/app/assets/javascripts/src/views/videoView.js +++ b/app/assets/javascripts/src/views/videoView.js @@ -98,14 +98,14 @@ Metamaps.Views.videoView = (function () { this.videoStatus = !this.videoStatus; $(document).trigger(videoView.events.videoControlClick, [this]); }, - yesReceiveClick: function () { + /*yesReceiveClick: function () { this.$receiveContainer.hide(); this.$avatar.hide(); $(this.video).prop('muted', false); }, noReceiveClick: function () { this.$container.hide(); - } + }*/ }; var videoView = function(video, $parent, id, isMyself, config) { @@ -135,6 +135,7 @@ Metamaps.Views.videoView = (function () { $vidContainer.addClass('video-cutoff'); $vidContainer.append(this.video); + /* if (!isMyself) { this.$receiveContainer = $('
' + config.username + ' is sharing their audio and video. Do you wish to receive it?
'); this.$container.append(this.$receiveContainer); @@ -144,7 +145,7 @@ Metamaps.Views.videoView = (function () { this.$container.find('.btn-no').on('click', function (event) { Handlers.noReceiveClick.call(self, event); }); - } + }*/ this.avatar = config.avatar; this.$avatar = $(''); @@ -157,7 +158,6 @@ Metamaps.Views.videoView = (function () { }); if (isMyself) { - this.$avatar.hide(); Private.addControls.call(this); } diff --git a/app/assets/stylesheets/application.css.erb b/app/assets/stylesheets/application.css.erb index e3f97ec9..210c29b1 100644 --- a/app/assets/stylesheets/application.css.erb +++ b/app/assets/stylesheets/application.css.erb @@ -76,7 +76,7 @@ body, html { -} +} body { background: #d8d9da url(<%= asset_data_uri('shattered_@2X.png') %>); font-family: 'din-medium', helvetica, sans-serif; @@ -132,6 +132,17 @@ a.button:active, input[type="submit"]:active { background: #429B46; } + +button.button.btn-no { + background-color: #c04f4f; +} +button.button.btn-no:hover { + background-color: #A54242; +} +.toast .toast-button { + margin-top: -10px; + margin-left: 10px; +} /* * Utility */ @@ -717,7 +728,7 @@ label { text-transform: uppercase; text-align: left; font-size: 14px; - line-height: 14px; + line-height: 14px; position:relative; } .accountInnerArrow { @@ -1026,7 +1037,7 @@ h3.filterBox { text-align: center; } .sidebarFilterBox li:hover { - + } #filter_by_mapper li img { width: 40px; @@ -1071,13 +1082,13 @@ h3.filterBox { margin-top:8px; } #filter_by_metacode { - + } #filter_by_mapper { - + } #filter_by_synapse { - + } /* end filter by metacode */ @@ -1115,7 +1126,7 @@ h3.filterBox { padding: 0; } .rightclickmenu > ul { - + } .rightclickmenu li { list-style: none; @@ -1192,7 +1203,7 @@ h3.filterBox { .rc-metacode li img { display: inline-block; } -.rightclickmenu .rc-permission ul, +.rightclickmenu .rc-permission ul, .rightclickmenu .rc-metacode ul, .rightclickmenu .rc-siblings ul { display: none; @@ -1205,7 +1216,7 @@ h3.filterBox { border-top-right-radius: 2px; box-shadow: 0px 3px 3px rgba(0,0,0,0.12), 0 3px 3px rgba(0,0,0,0.24); } -.rightclickmenu .rc-permission:hover > ul, +.rightclickmenu .rc-permission:hover > ul, .rightclickmenu .rc-metacode:hover > ul, .rightclickmenu .rc-siblings:hover > ul { display: block; @@ -1214,7 +1225,7 @@ h3.filterBox { padding: 7px; } .rightclickmenu li.changeP { - + } .rightclickmenu li.changeP .rc-perm-icon { position: absolute; @@ -1276,13 +1287,13 @@ h3.filterBox { top: -7px; } -.moveMenusUp .rc-metacode ul, +.moveMenusUp .rc-metacode ul, .moveMenusUp .rc-permission ul, .moveMenusUp .rc-siblings ul { top: auto; bottom: 0; } -.moveMenusToLeft .rc-metacode ul, +.moveMenusToLeft .rc-metacode ul, .moveMenusToLeft .rc-permission ul, .moveMenusToLeft .rc-siblings ul { left: auto; @@ -1305,7 +1316,7 @@ h3.filterBox { #new_synapse .tt-suggestion.tt-cursor { background: #E0E0E0; } -#new_topic .tt-suggestion, +#new_topic .tt-suggestion, #new_synapse .tt-dataset h3, #new_synapse .tt-suggestion { background: #F5F5F5; @@ -1329,7 +1340,7 @@ h3.filterBox { font-size: 14px; padding: 9px 0 9px 4px; } -#new_synapse .synapseDesc, +#new_synapse .synapseDesc, #new_synapse .genericSynapseDesc { width: 190px; line-height: 14px; @@ -1967,7 +1978,7 @@ and it won't be important on password protected instances */ } #svi1 > p, #svi2 > p { - width: 150px; + width: 150px; } .lightboxContent { font-family: 'din-regular'; @@ -2046,7 +2057,7 @@ and it won't be important on password protected instances */ display: none !important; } .ui-tabs-vertical { - + } .ui-tabs-vertical .ui-tabs-nav { float: left; @@ -2220,7 +2231,7 @@ and it won't be important on password protected instances */ #colophon a { color: #c04f4f; - text-decoration: underline; + text-decoration: underline; } #colophonCols { @@ -2291,15 +2302,15 @@ and it won't be important on password protected instances */ background: url(<%= asset_data_uri 'browser_icons.png' %>) no-repeat -220px 0; } -#chromeIcon:hover{ +#chromeIcon:hover{ opacity: 1; } -#fireFoxIcon:hover{ +#fireFoxIcon:hover{ opacity: 1; } -#safariIcon:hover{ +#safariIcon:hover{ opacity: 1; } @@ -2519,7 +2530,7 @@ and it won't be important on password protected instances */ margin: 5px 0; font-size: 14px; line-height: 18px; - font-family: 'din-regular'; + font-family: 'din-regular'; } #cheatSheet .csItem a { @@ -2719,7 +2730,7 @@ and it won't be important on password protected instances */ word-wrap: break-word; } .blackBox td.iconColor { - + } .blackBox .field { margin: 15px 0 5px; @@ -2845,7 +2856,7 @@ and it won't be important on password protected instances */ display: none; background-color: #4fb5c0; color: #FFFFFF; - padding: 2px 8px 2px 8px; + padding: 2px 8px 2px 8px; position: absolute; top: 7px; left:28px; @@ -2878,7 +2889,7 @@ and it won't be important on password protected instances */ background-position: 16px 8px; -webkit-transform-origin: left center; transform-origin: left center; -} +} .blockchain-btn { display: inline; float: right; diff --git a/app/assets/stylesheets/junto.css.erb b/app/assets/stylesheets/junto.css.erb index 8fab5e06..a1f1a13d 100644 --- a/app/assets/stylesheets/junto.css.erb +++ b/app/assets/stylesheets/junto.css.erb @@ -54,6 +54,7 @@ -o-user-select: none; user-select: none; -webkit-user-drag: none; + display: none; } .collaborator-video .video-audio { position: absolute; diff --git a/app/views/layouts/_upperelements.html.erb b/app/views/layouts/_upperelements.html.erb index 55a619cc..8328cb84 100644 --- a/app/views/layouts/_upperelements.html.erb +++ b/app/views/layouts/_upperelements.html.erb @@ -20,7 +20,6 @@
SUPPORT US!
-
start my video
Filter
@@ -37,7 +36,7 @@ <% end %>
-
+
<% if authenticated? %> diff --git a/realtime/realtime-server.js b/realtime/realtime-server.js index f352480b..cb7b637c 100644 --- a/realtime/realtime-server.js +++ b/realtime/realtime-server.js @@ -22,6 +22,23 @@ function start() { socket.broadcast.emit(data.userToNotify + '-' + data.mapid + '-UpdateMapperList', existingUser); }); + // as a new mapper check whether there's a call in progress to join + socket.on('checkForCall', function (data) { + var socketsInRoom = io.sockets.clients(data.room); + if (socketsInRoom.length) socket.emit('maps-' + data.mapid + '-callInProgress', socketsInRoom.length); + }); + // send the invitation to start a call + socket.on('inviteACall', function (data) { + socket.broadcast.emit(data.invited + '-' + data.mapid + '-invitedToCall', data.inviter); + }); + // send response back to the inviter + socket.on('callAccepted', function (data) { + socket.broadcast.emit(data.inviter + '-' + data.mapid + '-callAccepted', data.invited); + }); + socket.on('callDenied', function (data) { + socket.broadcast.emit(data.inviter + '-' + data.mapid + '-callDenied', data.invited); + }); + // this will ping everyone on a map that there's a person just joined the map socket.on('newMapperNotify', function (data) { socket.set('mapid', data.mapid); @@ -56,7 +73,7 @@ function start() { // this will ping everyone on a map that there's a person just left the map socket.on('disconnect', end); socket.on('endMapperNotify', end); - + // this will ping everyone on a map that someone just turned on realtime socket.on('notifyStartRealtime', function (data) { var newUser = { @@ -66,7 +83,7 @@ function start() { socket.broadcast.emit('maps-' + data.mapid + '-newrealtime', newUser); }); - + // this will ping everyone on a map that someone just turned on realtime socket.on('notifyStopRealtime', function (data) { var newUser = { @@ -151,4 +168,4 @@ function start() { }); } -start(); \ No newline at end of file +start(); diff --git a/realtime/signal.js b/realtime/signal.js index 5d9a63f7..9b22197a 100644 --- a/realtime/signal.js +++ b/realtime/signal.js @@ -29,7 +29,7 @@ module.exports = function(io, stunservers) { client.resources = { screen: false, - video: false, + video: true, audio: false }; @@ -54,17 +54,6 @@ module.exports = function(io, stunservers) { }); client.on('join', join); - client.on('videoAdded', videoAdded); - - function videoAdded(data) { - var socketsInRoom = io.sockets.clients(client.room); - client.resources.video = true; - socketsInRoom.forEach(function(socket) { - if (socket.id !== client.id) { - socket.emit('addVideo', { id: client.id }); - } - }); - } function removeFeed(type) { if (client.room) {