|
|
|
@ -73,16 +73,23 @@ $.ajax({ |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Define a few functions
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// Popup with the URL to share
|
|
|
|
|
function inviteUrlPopup(){ |
|
|
|
|
window.prompt(locale.TO_INVITE_SHARE_THIS_URL, window.location.href); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Add a new email address to be notified whn someone joins
|
|
|
|
|
// Add a new email address to be notified when someone joins
|
|
|
|
|
// This only add the email address on the interface
|
|
|
|
|
function addNotifiedEmail(email){ |
|
|
|
|
var id = email.replace(/['"]/g, '_'); |
|
|
|
|
$('<li></li>').html(email + ' <a href="javascript:void(0);" onclick="removeNotifiedEmail(\'' + email.replace('\'', '\\\'') + '\');" title="' + locale.REMOVE_THIS_ADDRESS + '">' + |
|
|
|
|
$('<li></li>').html(email + |
|
|
|
|
' <a href="javascript:void(0);" onclick="removeNotifiedEmail(\'' + email.replace('\'', '\\\'') + '\');"' + |
|
|
|
|
' title="' + locale.REMOVE_THIS_ADDRESS + '">' + |
|
|
|
|
' <span class="glyphicon glyphicon-remove-circle"></span>' + |
|
|
|
|
' </a>') |
|
|
|
|
.attr('id', 'emailNotification_' + id) |
|
|
|
@ -90,6 +97,8 @@ function addNotifiedEmail(email){ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Remove the address from the list
|
|
|
|
|
// Remove it from the interface and request the frontend to remove it from
|
|
|
|
|
// the database too
|
|
|
|
|
function removeNotifiedEmail(email){ |
|
|
|
|
var id = escapeJqSelector(email.replace(/['"]/, '_').replace('\\\'', '\'')); |
|
|
|
|
$.ajax({ |
|
|
|
@ -115,12 +124,13 @@ function removeNotifiedEmail(email){ |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Escape a string to be used as a jQuerry selector
|
|
|
|
|
// Taken from http://totaldev.com/content/escaping-characters-get-valid-jquery-id
|
|
|
|
|
function escapeJqSelector(string){ |
|
|
|
|
return string.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Escape entities
|
|
|
|
|
// Escape entities to prevent XSS
|
|
|
|
|
function stringEscape(string){ |
|
|
|
|
string = string.replace(/[\u00A0-\u99999<>\&]/gim, function(i) { |
|
|
|
|
return '&#' + i.charCodeAt(0) + ';'; |
|
|
|
@ -209,8 +219,11 @@ function maxHeight(){ |
|
|
|
|
return $(window).height()-$('#toolbar').height()-25; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This is the main function called when you join a room
|
|
|
|
|
function initVroom(room) { |
|
|
|
|
|
|
|
|
|
// This object will be used to record all
|
|
|
|
|
// the peers and their info. Init with our own info
|
|
|
|
|
var peers = { |
|
|
|
|
local: { |
|
|
|
|
screenShared: false, |
|
|
|
@ -246,7 +259,7 @@ function initVroom(room) { |
|
|
|
|
$('#noWebrtcSupport').modal('show'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Update our role
|
|
|
|
|
// Get our role and other room settings from the server
|
|
|
|
|
function getRoomInfo(){ |
|
|
|
|
$.ajax({ |
|
|
|
|
data: { |
|
|
|
@ -274,7 +287,9 @@ function initVroom(room) { |
|
|
|
|
addNotifiedEmail(val); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
// We're are not owner of the room
|
|
|
|
|
else{ |
|
|
|
|
// Hide owner reserved elements
|
|
|
|
|
$('.ownerEl').hide(500); |
|
|
|
|
if (data.owner_auth == 'yes'){ |
|
|
|
|
$('.unauthEl').show(500); |
|
|
|
@ -310,7 +325,9 @@ function initVroom(room) { |
|
|
|
|
if (peers[id]){ |
|
|
|
|
peers[id].role = data.role; |
|
|
|
|
if (data.role == 'owner'){ |
|
|
|
|
$('#overlay_' + id).append('<div id="owner_' + id + '" class="owner"></div>'); |
|
|
|
|
// If this peer is a owner, we add the mark on its preview
|
|
|
|
|
$('#overlay_' + id).append($('<div></div>').attr('id', 'owner_' + id).addClass('owner')); |
|
|
|
|
// And we disable owner's action for him
|
|
|
|
|
$('#ownerActions_' + id).remove(); |
|
|
|
|
} |
|
|
|
|
else{ |
|
|
|
@ -321,21 +338,22 @@ function initVroom(room) { |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Put a video on the mainVideo div
|
|
|
|
|
// Put a video on the mainVideo div, called when you click on a video preview
|
|
|
|
|
function handlePreviewClick(el, id){ |
|
|
|
|
var wait = 1; |
|
|
|
|
// There's already a main video, let's hide it
|
|
|
|
|
// and delay the new one so the fade out as time to complete
|
|
|
|
|
if ($('#mainVideo').html() != ''){ |
|
|
|
|
$('#mainVideo').hide(300); |
|
|
|
|
wait = 300; |
|
|
|
|
} |
|
|
|
|
setTimeout(function(){ |
|
|
|
|
$('#mainVideo').html(''); |
|
|
|
|
// If this video is already the main one, remove the main
|
|
|
|
|
if (el.hasClass('selected')){ |
|
|
|
|
el.removeClass('selected'); |
|
|
|
|
} |
|
|
|
|
// Else, update the main video to use this one
|
|
|
|
|
else{ |
|
|
|
|
// Clone this new preview into the main div
|
|
|
|
|
$('#mainVideo').html(el.clone().dblclick(function() { |
|
|
|
|
fullScreen(this); |
|
|
|
|
}) |
|
|
|
@ -361,11 +379,11 @@ function initVroom(room) { |
|
|
|
|
// including our own local screen
|
|
|
|
|
function addVideo(video,peer){ |
|
|
|
|
playSound('join.mp3'); |
|
|
|
|
// The main div of this new video
|
|
|
|
|
// will contain the video plus all other info like displayName, overlay and volume bar
|
|
|
|
|
// The div continer of this new video
|
|
|
|
|
// will contain the video preview plus all other info like displayName, overlay and volume bar
|
|
|
|
|
var div = $('<div></div>').addClass('col-xs-6 col-sm-12 col-lg-6 previewContainer').append(video).appendTo('#webRTCVideo'); |
|
|
|
|
// Peer isn't defined ? it's our own local screen
|
|
|
|
|
var id; |
|
|
|
|
// Peer isn't defined ? it's our own local screen
|
|
|
|
|
if (!peer){ |
|
|
|
|
id = 'local'; |
|
|
|
|
$('<div></div>').addClass('displayName').attr('id', 'name_local_screen').appendTo(div); |
|
|
|
@ -387,6 +405,8 @@ function initVroom(room) { |
|
|
|
|
$('<div></div>').addClass('volumeBar').attr('id', 'volume_' + id).appendTo(div); |
|
|
|
|
$('<div></div>').addClass('displayName').attr('id', 'name_' + id).appendTo(div); |
|
|
|
|
$('<div></div>').attr('id', 'overlay_' + id).appendTo(div); |
|
|
|
|
// Will contains per peer action menu (mute/pause/kick), but will only be displayed
|
|
|
|
|
// on owners screen
|
|
|
|
|
$('<div></div>').addClass('ownerActions').attr('id', 'ownerActions_' + id).appendTo(div) |
|
|
|
|
.append($('<div></div>',{ |
|
|
|
|
class: 'btn-group' |
|
|
|
@ -406,6 +426,8 @@ function initVroom(room) { |
|
|
|
|
id: 'actionKick_' + id, |
|
|
|
|
click: function() { kickPeer(id) }, |
|
|
|
|
}).prop('title', locale.KICK_PEER))); |
|
|
|
|
// Display the menu now if we're a owner, but add some delay
|
|
|
|
|
// as those actions won't work until all the channels are ready
|
|
|
|
|
setTimeout (function(){ |
|
|
|
|
$(div).hover( |
|
|
|
|
function(){ |
|
|
|
@ -418,9 +440,10 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
}, 3500); |
|
|
|
|
// Create a new dataChannel
|
|
|
|
|
// will be used for text chat and displayName
|
|
|
|
|
// Choose a random color. If everything is OK
|
|
|
|
|
// this peer will send us its owne color in a few seconds
|
|
|
|
|
var color = chooseColor(); |
|
|
|
|
// Now store this new peer in our object
|
|
|
|
|
peers[peer.id] = { |
|
|
|
|
displayName: peer.id, |
|
|
|
|
color: color, |
|
|
|
@ -430,12 +453,14 @@ function initVroom(room) { |
|
|
|
|
obj: peer |
|
|
|
|
}; |
|
|
|
|
// Send our info to this peer (displayName/color)
|
|
|
|
|
// but wait a bit so the "vroom" dataChannel acreated earlier is fully setup (or have more chances to be)
|
|
|
|
|
// but wait a bit so the "vroom" dataChannel created earlier is fully setup (or have more chances to be)
|
|
|
|
|
// before we send
|
|
|
|
|
setTimeout(function(){ |
|
|
|
|
if ($('#displayName').val() !== '') { |
|
|
|
|
// displayName is private data, lets send it through dataChannel
|
|
|
|
|
if ($('#displayName').val() !== ''){ |
|
|
|
|
peer.sendDirectly('vroom','setDisplayName', $('#displayName').val()); |
|
|
|
|
} |
|
|
|
|
// color can be sent through the signaling channel
|
|
|
|
|
peer.send('peer_color', {color: peers.local.color}); |
|
|
|
|
// We don't have chat history yet ? Lets ask to this new peer
|
|
|
|
|
if(!peers.local.hasHistory && chatIndex == 0){ |
|
|
|
@ -443,8 +468,8 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
// Get the role of this peer
|
|
|
|
|
getPeerRole(peer.id); |
|
|
|
|
}, 3500); |
|
|
|
|
// Stop moh
|
|
|
|
|
}, 3000); |
|
|
|
|
// Stop moh, we're not alone anymore
|
|
|
|
|
$('#mohPlayer')[0].pause(); |
|
|
|
|
$('.aloneEl').hide(300); |
|
|
|
|
moh = false; |
|
|
|
@ -468,14 +493,15 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Update volume of the corresponding peer
|
|
|
|
|
// Taken from SimpleWebRTC demo
|
|
|
|
|
function showVolume(el, volume) { |
|
|
|
|
if (!el){ |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (volume < -45) { // vary between -45 and -20
|
|
|
|
|
if (volume < -45){ // vary between -45 and -20
|
|
|
|
|
el.css('height', '0px'); |
|
|
|
|
} |
|
|
|
|
else if (volume > -20) { |
|
|
|
|
else if (volume > -20){ |
|
|
|
|
el.css('height', '100%'); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
@ -485,11 +511,14 @@ function initVroom(room) { |
|
|
|
|
|
|
|
|
|
// Add a new message to the chat history
|
|
|
|
|
function newChatMessage(from,message,time,color){ |
|
|
|
|
// displayName has already been escaped
|
|
|
|
|
var cl = (from === 'local') ? 'chatMsgSelf':'chatMsgOthers'; |
|
|
|
|
// We need to check time format as it can be sent from another
|
|
|
|
|
// peer if we asked for its history. If it's not define or doesn't look
|
|
|
|
|
// correct, we'll get time locally
|
|
|
|
|
if (!time || !time.match(/^\d{1,2}:\d{1,2}:\d{1,2}$/)){ |
|
|
|
|
time = getTime(); |
|
|
|
|
} |
|
|
|
|
// It's a message sent from a connected peer, we should have its info
|
|
|
|
|
if (peers[from] && peers[from].color){ |
|
|
|
|
var color = peers[from].color; |
|
|
|
|
var displayName = peers[from].displayName; |
|
|
|
@ -497,11 +526,14 @@ function initVroom(room) { |
|
|
|
|
// this peer might not be defined if we're importing chat history
|
|
|
|
|
// So just use the from as the displayName and the provided color
|
|
|
|
|
else{ |
|
|
|
|
var color = (color && color.match(/#[\da-f]{6}/i)) ? color:chooseColor(); |
|
|
|
|
var color = (color && color.match(/#[\da-f]{6}/i)) ? color : chooseColor(); |
|
|
|
|
var displayName = from; |
|
|
|
|
} |
|
|
|
|
// Create the new msg
|
|
|
|
|
var newmsg = $('<div class="chatMsg ' + cl + '">' + time + ' ' + stringEscape(displayName) + '<p>' + linkify(stringEscape(message)) + '</p></div>').css('background-color', color); |
|
|
|
|
// Add it in the history
|
|
|
|
|
$('<div class="row chatMsgContainer"></div>').append(newmsg).appendTo('#chatHistory'); |
|
|
|
|
// Move the scroller down
|
|
|
|
|
$('#chatHistory').scrollTop($('#chatHistory').prop('scrollHeight')); |
|
|
|
|
// Record this message in the history object
|
|
|
|
|
// so we can send it to other peers asking for it
|
|
|
|
@ -533,9 +565,11 @@ function initVroom(room) { |
|
|
|
|
if (peers[id].micMuted){ |
|
|
|
|
msg = locale.YOU_HAVE_UNMUTED_s |
|
|
|
|
} |
|
|
|
|
// notify everyone that we have muted this peer
|
|
|
|
|
webrtc.sendToAll('owner_toggle_mute', {peer: id}); |
|
|
|
|
$.notify(sprintf(msg, peers[id].displayName), 'info'); |
|
|
|
|
} |
|
|
|
|
// We cannot mute another owner
|
|
|
|
|
else{ |
|
|
|
|
$.notify(locale.CANT_MUTE_OWNER, 'error'); |
|
|
|
|
} |
|
|
|
@ -605,13 +639,15 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// An owner is muting/unmuting ourself
|
|
|
|
|
// An owner is muting/unmuting someone
|
|
|
|
|
webrtc.on('owner_toggle_mute', function(data){ |
|
|
|
|
// Ignore this if the remote peer isn't the owner of the room
|
|
|
|
|
// or if the peer receiving it is our local screen
|
|
|
|
|
// or if the peer receiving it is our local screen sharing
|
|
|
|
|
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){ |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// We are the one being (un)muted, and we're not owner
|
|
|
|
|
// Be nice and obey
|
|
|
|
|
if (data.payload.peer && data.payload.peer == peers.local.id && peers.local.role != 'owner'){ |
|
|
|
|
if (!peers.local.micMuted){ |
|
|
|
|
muteMic(); |
|
|
|
@ -626,7 +662,8 @@ function initVroom(room) { |
|
|
|
|
$.notify(sprintf(locale.s_IS_UNMUTING_YOU, peers[data.id].displayName), 'info'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else if (data.payload.peer != peers.local.id){ |
|
|
|
|
// It's another peer of the room
|
|
|
|
|
else if (data.payload.peer != peers.local.id && peers[data.payload.peer]){ |
|
|
|
|
if (peers[data.payload.peer].micMuted){ |
|
|
|
|
$.notify(sprintf(locale.s_IS_UNMUTING_s, peers[data.id].displayName, peers[data.payload.peer].displayName), 'info'); |
|
|
|
|
} |
|
|
|
@ -635,7 +672,8 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
// An owner is pausing/resuming our webcam
|
|
|
|
|
// An owner is pausing/resuming a webcam.
|
|
|
|
|
// More or less the same dance than mute/unmute. Both fonctions should be merged
|
|
|
|
|
webrtc.on('owner_toggle_pause', function(data){ |
|
|
|
|
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){ |
|
|
|
|
return; |
|
|
|
@ -654,7 +692,7 @@ function initVroom(room) { |
|
|
|
|
$.notify(sprintf(locale.s_IS_RESUMING_YOU, peers[data.id].displayName), 'info'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else if (data.payload.peer != peers.local.id){ |
|
|
|
|
else if (data.payload.peer != peers.local.id && peers[data.payload.peer]){ |
|
|
|
|
if (peers[data.payload.peer].videoPaused){ |
|
|
|
|
$.notify(sprintf(locale.s_IS_RESUMING_s, peers[data.id].displayName, peers[data.payload.peer].displayName), 'info'); |
|
|
|
|
} |
|
|
|
@ -663,7 +701,7 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
// An owner is kicking us from the room
|
|
|
|
|
// An owner is kicking someone out of the room
|
|
|
|
|
webrtc.on('owner_kick', function(data){ |
|
|
|
|
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){ |
|
|
|
|
return; |
|
|
|
@ -685,10 +723,12 @@ function initVroom(room) { |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Handle volume changes from our own mic
|
|
|
|
|
webrtc.on('volumeChange', function (volume, treshold) { |
|
|
|
|
webrtc.on('volumeChange', function (volume, treshold){ |
|
|
|
|
// Record the highest level (used for the "no sound" detection)
|
|
|
|
|
if (volume > maxVol){ |
|
|
|
|
maxVol = volume; |
|
|
|
|
} |
|
|
|
|
// Do nothing if we're muted
|
|
|
|
|
if (peers.local.micMuted) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -701,13 +741,14 @@ function initVroom(room) { |
|
|
|
|
if (data.type == 'volume'){ |
|
|
|
|
showVolume($('#volume_' + peer.id), data.volume); |
|
|
|
|
} |
|
|
|
|
// We only want to act on data receive from the vroom channel
|
|
|
|
|
// We only want to act on data received from the vroom channel
|
|
|
|
|
if (label !== 'vroom'){ |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// The peer sets a displayName, record this in our peers struct
|
|
|
|
|
// The peer sets a displayName, record this in our peers object
|
|
|
|
|
else if (data.type == 'setDisplayName'){ |
|
|
|
|
var name = data.payload; |
|
|
|
|
// Ignore it if it's too long
|
|
|
|
|
if (name.length > 50){ |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -726,7 +767,7 @@ function initVroom(room) { |
|
|
|
|
else if (data.type == 'getHistory'){ |
|
|
|
|
peer.sendDirectly('vroom', 'chatHistory', JSON.stringify(chatHistory)); |
|
|
|
|
} |
|
|
|
|
// This peer is sending our chat history (and we don't have it yet)
|
|
|
|
|
// This peer is sending its chat history (and we don't have it yet)
|
|
|
|
|
else if (data.type == 'chatHistory' && !peers.local.hasHistory){ |
|
|
|
|
peers.local.hasHistory = true; |
|
|
|
|
var history = JSON.parse(data.payload); |
|
|
|
@ -736,6 +777,7 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
// One peer just sent a text chat message
|
|
|
|
|
else if (data.type == 'textChat'){ |
|
|
|
|
// Notify if the chat menu is collapsed
|
|
|
|
|
if ($('#chatDropdown').hasClass('collapsed')){ |
|
|
|
|
$('#chatDropdown').addClass('btn-danger'); |
|
|
|
|
playSound('newmsg.mp3'); |
|
|
|
@ -745,6 +787,7 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// A peer is sending its color
|
|
|
|
|
webrtc.on('peer_color', function(data){ |
|
|
|
|
var color = data.payload.color; |
|
|
|
|
if (!color.match(/#[\da-f]{6}/i)){ |
|
|
|
@ -761,13 +804,16 @@ function initVroom(room) { |
|
|
|
|
|
|
|
|
|
// Received when a peer mute his mic, or pause the video
|
|
|
|
|
webrtc.on('mute', function(data){ |
|
|
|
|
// Muting
|
|
|
|
|
if (data.name === 'audio'){ |
|
|
|
|
// put the volume bar at the minimum
|
|
|
|
|
showVolume($('#volume_' + data.id), -46); |
|
|
|
|
var div = 'mute_' + data.id, |
|
|
|
|
cl = 'muted'; |
|
|
|
|
peers[data.id].micMuted = true; |
|
|
|
|
$('#actionMute_' + data.id).addClass('btn-danger'); |
|
|
|
|
} |
|
|
|
|
// Pausing webcam
|
|
|
|
|
else if (data.name === 'video'){ |
|
|
|
|
var div = 'pause_' + data.id, |
|
|
|
|
cl = 'paused'; |
|
|
|
@ -807,7 +853,8 @@ function initVroom(room) { |
|
|
|
|
getPeerRole(data.id); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// A new notified email has been added
|
|
|
|
|
// A new notified email has been added or removed
|
|
|
|
|
// We need to refresh the whole list
|
|
|
|
|
webrtc.on('notif_change', function(data){ |
|
|
|
|
if (peers.local.role != 'owner' || data.roomType == 'screen' || peers[data.id].role != 'owner'){ |
|
|
|
|
return; |
|
|
|
@ -880,6 +927,7 @@ function initVroom(room) { |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Handle the readyToCall event: join the room
|
|
|
|
|
// Or prompt for a name first
|
|
|
|
|
webrtc.once('readyToCall', function () { |
|
|
|
|
peers.local.id = webrtc.connection.socket.sessionid; |
|
|
|
|
getRoomInfo(); |
|
|
|
@ -902,7 +950,10 @@ function initVroom(room) { |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
}, 10000); |
|
|
|
|
// Notify the frontend a new participant has joined
|
|
|
|
|
// Notify the server a new participant has joined (ourself)
|
|
|
|
|
// If we were prompted for our display name before joining
|
|
|
|
|
// we send it. Not that I like sending this kind of data to the server
|
|
|
|
|
// but it's needed for email notifications
|
|
|
|
|
$.ajax({ |
|
|
|
|
data: { |
|
|
|
|
action: 'join', |
|
|
|
@ -935,13 +986,12 @@ function initVroom(room) { |
|
|
|
|
addVideo(video); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// error opening the webcam stream
|
|
|
|
|
// error opening the webcam or mic stream
|
|
|
|
|
webrtc.on('localMediaError', function(){ |
|
|
|
|
$('#noWebcam').modal('show'); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Handle video stream removed: someone leaved the room
|
|
|
|
|
// TODO: don't trigger on local screen unshare
|
|
|
|
|
webrtc.on('videoRemoved', function(video,peer){ |
|
|
|
|
playSound('leave.mp3'); |
|
|
|
|
var id = (peer) ? peer.id : 'local'; |
|
|
|
@ -954,6 +1004,7 @@ function initVroom(room) { |
|
|
|
|
delete peers[peer.id]; |
|
|
|
|
} |
|
|
|
|
$("#peer_" + id).hide(300); |
|
|
|
|
// Remove the div, but wait for the fade out to complete
|
|
|
|
|
setTimeout(function(){ |
|
|
|
|
$("#peer_" + id).remove(); |
|
|
|
|
}, 300); |
|
|
|
@ -975,8 +1026,7 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Do not close the dropdown menu when filling the email recipient
|
|
|
|
|
// and in other dropdown menus
|
|
|
|
|
// Do not close the dropdown menus (invite/conf) when filling fields
|
|
|
|
|
$('.dropdown-menu').on('click', 'li', function(e){ |
|
|
|
|
e.stopPropagation(); |
|
|
|
|
}); |
|
|
|
@ -986,6 +1036,7 @@ function initVroom(room) { |
|
|
|
|
var rcpt = $('#recipient').val(); |
|
|
|
|
message = $('#message').val(); |
|
|
|
|
// Simple email address verification
|
|
|
|
|
// not fullproof, but email validation is a real nightmare
|
|
|
|
|
if (!rcpt.match(/\S+@\S+\.\S+/)){ |
|
|
|
|
$.notify(locale.ERROR_MAIL_INVALID, 'error'); |
|
|
|
|
return; |
|
|
|
@ -1013,7 +1064,7 @@ function initVroom(room) { |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Set your DisplayName
|
|
|
|
|
$('#displayName').on('input', function() { |
|
|
|
|
$('#displayName').on('input', function(){ |
|
|
|
|
var name = $('#displayName').val(); |
|
|
|
|
if (name.length > 50){ |
|
|
|
|
$('#displayName').parent().addClass('has-error'); |
|
|
|
@ -1025,14 +1076,12 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
// Enable chat input when you set your disaplay name
|
|
|
|
|
if (name != '' && $('#chatBox').attr('disabled')){ |
|
|
|
|
$('#chatBox').removeAttr('disabled'); |
|
|
|
|
$('#chatBox').removeAttr('placeholder'); |
|
|
|
|
$('#chatBox').removeAttr('disabled').removeAttr('placeholder'); |
|
|
|
|
peers.local.hasName = true; |
|
|
|
|
} |
|
|
|
|
// And disable it again if you remove your display name
|
|
|
|
|
else if (name == ''){ |
|
|
|
|
$('#chatBox').attr('disabled', true); |
|
|
|
|
$('#chatBox').attr('placeholder', locale.SET_YOUR_NAME_TO_CHAT); |
|
|
|
|
$('#chatBox').attr('disabled', true).attr('placeholder', locale.SET_YOUR_NAME_TO_CHAT); |
|
|
|
|
peers.local.hasName = false; |
|
|
|
|
} |
|
|
|
|
peers.local.displayName = name; |
|
|
|
@ -1067,8 +1116,7 @@ function initVroom(room) { |
|
|
|
|
peers.local.hasName = true; |
|
|
|
|
peers.local.displayName = name; |
|
|
|
|
updateDisplayName('local'); |
|
|
|
|
$('#chatBox').removeAttr('disabled'); |
|
|
|
|
$('#chatBox').removeAttr('placeholder'); |
|
|
|
|
$('#chatBox').removeAttr('disabled').removeAttr('placeholder'); |
|
|
|
|
webrtc.joinRoom(room); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
@ -1101,6 +1149,7 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
}
|
|
|
|
|
}); |
|
|
|
|
// DIsable the button for a moment so you cannot overload the server
|
|
|
|
|
suspendButton($(this)); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
@ -1144,15 +1193,22 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
if (!peers.local.screenShared && action === 'share'){ |
|
|
|
|
webrtc.shareScreen(function(err){ |
|
|
|
|
// An error occured while sharing our screen
|
|
|
|
|
if(err){ |
|
|
|
|
if (err.name == 'EXTENSION_UNAVAILABLE'){ |
|
|
|
|
var ver = 34; |
|
|
|
|
if ($.browser.linux) ver = 35; |
|
|
|
|
if ($.browser.webkit && $.browser.versionNumber >= ver) |
|
|
|
|
if ($.browser.linux){ |
|
|
|
|
ver = 35; |
|
|
|
|
} |
|
|
|
|
if ($.browser.webkit && $.browser.versionNumber >= ver){ |
|
|
|
|
$('#chromeExtMessage').modal('show'); |
|
|
|
|
else |
|
|
|
|
} |
|
|
|
|
else{ |
|
|
|
|
cantShare(locale.SCREEN_SHARING_ONLY_FOR_CHROME); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// This error usually means you have denied access (old flag way)
|
|
|
|
|
// or you cancelled screen sharing (new extension way)
|
|
|
|
|
else if (err.name == 'PERMISSION_DENIED' || err.name == 'PermissionDeniedError'){ |
|
|
|
|
cantShare(locale.SCREEN_SHARING_CANCELLED); |
|
|
|
|
} |
|
|
|
@ -1162,6 +1218,7 @@ function initVroom(room) { |
|
|
|
|
$('#shareScreenLabel').removeClass('active'); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// Screen sharing worked, warn that everyone can see it
|
|
|
|
|
else{ |
|
|
|
|
$("#shareScreenLabel").addClass('btn-danger'); |
|
|
|
|
peers.local.screenShared = true; |
|
|
|
@ -1207,7 +1264,7 @@ function initVroom(room) { |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Handle auth
|
|
|
|
|
// Handle auth to become room owner
|
|
|
|
|
$('#authPass').on('input', function() { |
|
|
|
|
if ($('#authPass').val() == ''){ |
|
|
|
|
$('#authPassButton').addClass('disabled'); |
|
|
|
@ -1243,6 +1300,7 @@ function initVroom(room) { |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Enable the submit button when the corresponding input is filled
|
|
|
|
|
$('#joinPass').on('input', function() { |
|
|
|
|
if ($('#joinPass').val() == ''){ |
|
|
|
|
$('#setJoinPassButton').addClass('disabled'); |
|
|
|
@ -1378,7 +1436,7 @@ function initVroom(room) { |
|
|
|
|
$('#newEmailNotificationButton').removeClass('disabled'); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
// Then send this new address to the frontend
|
|
|
|
|
// Then send this new address to the server
|
|
|
|
|
$('#newEmailNotificationForm').submit(function(event){ |
|
|
|
|
event.preventDefault(); |
|
|
|
|
$.ajax({ |
|
|
|
@ -1439,6 +1497,7 @@ function initVroom(room) { |
|
|
|
|
$('#webRTCVideoLocal').dblclick(function() { |
|
|
|
|
fullScreen(this); |
|
|
|
|
}); |
|
|
|
|
// And put it in the main div on simple click
|
|
|
|
|
$('#webRTCVideoLocal').click(function() { |
|
|
|
|
handlePreviewClick($(this), 'self'); |
|
|
|
|
}); |
|
|
|
|