Merge pull request #98 from fouksf/message-handler

Adds a message handler.
This commit is contained in:
hristoterezov 2014-09-16 17:51:32 +03:00
commit aaf444bae4
9 changed files with 405 additions and 282 deletions

183
app.js
View File

@ -12,6 +12,7 @@ var roomUrl = null;
var roomName = null; var roomName = null;
var ssrc2jid = {}; var ssrc2jid = {};
var mediaStreams = []; var mediaStreams = [];
var bridgeIsDown = false;
/** /**
* The stats collector that process stats data and triggers updates to app.js. * The stats collector that process stats data and triggers updates to app.js.
@ -41,7 +42,6 @@ var mutedAudios = {};
var localVideoSrc = null; var localVideoSrc = null;
var flipXLocalVideo = true; var flipXLocalVideo = true;
var isFullScreen = false; var isFullScreen = false;
var toolbarTimeout = null;
var currentVideoWidth = null; var currentVideoWidth = null;
var currentVideoHeight = null; var currentVideoHeight = null;
/** /**
@ -171,6 +171,9 @@ function obtainAudioAndVideoPermissions(callback) {
media: error.media || 'video', media: error.media || 'video',
name : error.name name : error.name
}); });
messageHandler.showError("Error",
"Failed to obtain permissions to use the local microphone" +
"and/or camera.");
}, },
config.resolution || '360'); config.resolution || '360');
} }
@ -239,6 +242,8 @@ function doJoin() {
function waitForRemoteVideo(selector, ssrc, stream) { function waitForRemoteVideo(selector, ssrc, stream) {
if (selector.removed || !selector.parent().is(":visible")) { if (selector.removed || !selector.parent().is(":visible")) {
console.warn("Media removed before had started", selector); console.warn("Media removed before had started", selector);
messageHandler.showError("Warning",
"Media was removed before it had started.");
return; return;
} }
@ -255,6 +260,7 @@ function waitForRemoteVideo(selector, ssrc, stream) {
videoSrcToSsrc[selector.attr('src')] = ssrc; videoSrcToSsrc[selector.attr('src')] = ssrc;
} else { } else {
console.warn("No ssrc given for video", selector); console.warn("No ssrc given for video", selector);
messageHandler.showError('Warning', 'No ssrc was given for the video.');
} }
$(document).trigger('videoactive.jingle', [selector]); $(document).trigger('videoactive.jingle', [selector]);
@ -327,9 +333,11 @@ function waitForPresence(data, sid) {
'participant_' + Strophe.getResourceFromJid(data.peerjid)); 'participant_' + Strophe.getResourceFromJid(data.peerjid));
} else { } else {
if (data.stream.id !== 'mixedmslabel') { if (data.stream.id !== 'mixedmslabel') {
console.error( 'can not associate stream', console.error('can not associate stream',
data.stream.id, data.stream.id,
'with a participant'); 'with a participant');
messageHandler.showError('Oops',
'We could not associate the current stream with a participant.');
// We don't want to add it here since it will cause troubles // We don't want to add it here since it will cause troubles
return; return;
} }
@ -398,16 +406,19 @@ function sendKeyframe(pc) {
}, },
function (error) { function (error) {
console.log('triggerKeyframe setLocalDescription failed', error); console.log('triggerKeyframe setLocalDescription failed', error);
messageHandler.showError();
} }
); );
}, },
function (error) { function (error) {
console.log('triggerKeyframe createAnswer failed', error); console.log('triggerKeyframe createAnswer failed', error);
messageHandler.showError();
} }
); );
}, },
function (error) { function (error) {
console.log('triggerKeyframe setRemoteDescription failed', error); console.log('triggerKeyframe setRemoteDescription failed', error);
messageHandler.showError();
} }
); );
} }
@ -435,16 +446,24 @@ function muteVideo(pc, unmute) {
}, },
function (error) { function (error) {
console.log('mute SLD error'); console.log('mute SLD error');
messageHandler.showError('Error',
'Oops! Something went wrong and we failed to ' +
'mute! (SLD Failure)');
} }
); );
}, },
function (error) { function (error) {
console.log(error); console.log(error);
messageHandler.showError();
} }
); );
}, },
function (error) { function (error) {
console.log('muteVideo SRD error'); console.log('muteVideo SRD error');
messageHandler.showError('Error',
'Oops! Something went wrong and we failed to stop video!' +
'(SRD Failure)');
} }
); );
} }
@ -563,7 +582,7 @@ $(document).bind('callterminated.jingle', function (event, sid, jid, reason) {
if (connection.emuc.joined && focus == null && reason === 'kick') { if (connection.emuc.joined && focus == null && reason === 'kick') {
sessionTerminated = true; sessionTerminated = true;
connection.emuc.doLeave(); connection.emuc.doLeave();
openMessageDialog( "Session Terminated", messageHandler.openMessageDialog("Session Terminated",
"Ouch! You have been kicked out of the meet!"); "Ouch! You have been kicked out of the meet!");
} }
}); });
@ -687,7 +706,13 @@ $(document).bind('entered.muc', function (event, jid, info, pres) {
// FIXME: this should prepare the video // FIXME: this should prepare the video
if (focus.confid === null) { if (focus.confid === null) {
console.log('make new conference with', jid); console.log('make new conference with', jid);
focus.makeConference(Object.keys(connection.emuc.members)); focus.makeConference(Object.keys(connection.emuc.members),
function(error) {
bridgeIsDown = true;
connection.emuc.addBridgeIsDownToPresence();
connection.emuc.sendPresence();
}
);
Toolbar.showRecordingButton(true); Toolbar.showRecordingButton(true);
} else { } else {
console.log('invite', jid, 'into conference'); console.log('invite', jid, 'into conference');
@ -809,6 +834,14 @@ $(document).bind('presence.muc', function (event, jid, info, pres) {
if (focus !== null && info.displayName !== null) { if (focus !== null && info.displayName !== null) {
focus.setEndpointDisplayName(jid, info.displayName); focus.setEndpointDisplayName(jid, info.displayName);
} }
//check if the video bridge is available
if($(pres).find(">bridgeIsDown").length > 0 && !bridgeIsDown) {
bridgeIsDown = true;
messageHandler.showError("Error",
"The video bridge is currently unavailable.");
}
}); });
$(document).bind('presence.status.muc', function (event, jid, info, pres) { $(document).bind('presence.status.muc', function (event, jid, info, pres) {
@ -821,40 +854,36 @@ $(document).bind('presence.status.muc', function (event, jid, info, pres) {
$(document).bind('passwordrequired.muc', function (event, jid) { $(document).bind('passwordrequired.muc', function (event, jid) {
console.log('on password required', jid); console.log('on password required', jid);
$.prompt('<h2>Password required</h2>' + messageHandler.openTwoButtonDialog(null,
'<input id="lockKey" type="text" placeholder="shared key" autofocus>', { '<h2>Password required</h2>' +
persistent: true, '<input id="lockKey" type="text" placeholder="shared key" autofocus>',
buttons: { "Ok": true, "Cancel": false}, true,
defaultButton: 1, "Ok",
loaded: function (event) { function (e, v, m, f) {
document.getElementById('lockKey').focus();
},
submit: function (e, v, m, f) {
if (v) { if (v) {
var lockKey = document.getElementById('lockKey'); var lockKey = document.getElementById('lockKey');
if (lockKey.value !== null) { if (lockKey.value !== null) {
setSharedKey(lockKey.value); setSharedKey(lockKey.value);
connection.emuc.doJoin(jid, lockKey.value); connection.emuc.doJoin(jid, lockKey.value);
} }
} }
},
function (event) {
document.getElementById('lockKey').focus();
} }
}); );
}); });
$(document).bind('passwordrequired.main', function (event) { $(document).bind('passwordrequired.main', function (event) {
console.log('password is required'); console.log('password is required');
$.prompt('<h2>Password required</h2>' + messageHandler.openTwoButtonDialog(null,
'<input id="passwordrequired.username" type="text" placeholder="user@domain.net" autofocus>' + '<h2>Password required</h2>' +
'<input id="passwordrequired.password" type="password" placeholder="user password">', { '<input id="passwordrequired.username" type="text" placeholder="user@domain.net" autofocus>' +
persistent: true, '<input id="passwordrequired.password" type="password" placeholder="user password">',
buttons: { "Ok": true, "Cancel": false}, true,
defaultButton: 1, "Ok",
loaded: function (event) { function (e, v, m, f) {
document.getElementById('passwordrequired.username').focus();
},
submit: function (e, v, m, f) {
if (v) { if (v) {
var username = document.getElementById('passwordrequired.username'); var username = document.getElementById('passwordrequired.username');
var password = document.getElementById('passwordrequired.password'); var password = document.getElementById('passwordrequired.password');
@ -863,8 +892,11 @@ $(document).bind('passwordrequired.main', function (event) {
connect(username.value, password.value); connect(username.value, password.value);
} }
} }
},
function (event) {
document.getElementById('passwordrequired.username').focus();
} }
}); );
}); });
/** /**
@ -981,25 +1013,23 @@ function toggleRecording() {
if (!recordingToken) if (!recordingToken)
{ {
$.prompt('<h2>Enter recording token</h2>' + messageHandler.openTwoButtonDialog(null,
'<h2>Enter recording token</h2>' +
'<input id="recordingToken" type="text" placeholder="token" autofocus>', '<input id="recordingToken" type="text" placeholder="token" autofocus>',
{ false,
persistent: false, "Save",
buttons: { "Save": true, "Cancel": false}, function (e, v, m, f) {
defaultButton: 1, if (v) {
loaded: function (event) { var token = document.getElementById('recordingToken');
document.getElementById('recordingToken').focus();
},
submit: function (e, v, m, f) {
if (v) {
var token = document.getElementById('recordingToken');
if (token.value) { if (token.value) {
setRecordingToken(Util.escapeHtml(token.value)); setRecordingToken(Util.escapeHtml(token.value));
toggleRecording(); toggleRecording();
}
} }
} }
},
function (event) {
document.getElementById('recordingToken').focus();
} }
); );
@ -1259,6 +1289,16 @@ function dump(elem, filename) {
elem = elem.parentNode; elem = elem.parentNode;
elem.download = filename || 'meetlog.json'; elem.download = filename || 'meetlog.json';
elem.href = 'data:application/json;charset=utf-8,\n'; elem.href = 'data:application/json;charset=utf-8,\n';
var data = populateData();
elem.href += encodeURIComponent(JSON.stringify(data, null, ' '));
return false;
}
/**
* Populates the log data
*/
function populateData() {
var data = {}; var data = {};
if (connection.jingle) { if (connection.jingle) {
Object.keys(connection.jingle.sessions).forEach(function (sid) { Object.keys(connection.jingle.sessions).forEach(function (sid) {
@ -1273,7 +1313,7 @@ function dump(elem, filename) {
} }
}); });
} }
metadata = {}; var metadata = {};
metadata.time = new Date(); metadata.time = new Date();
metadata.url = window.location.href; metadata.url = window.location.href;
metadata.ua = navigator.userAgent; metadata.ua = navigator.userAgent;
@ -1281,8 +1321,7 @@ function dump(elem, filename) {
metadata.xmpp = connection.logger.log; metadata.xmpp = connection.logger.log;
} }
data.metadata = metadata; data.metadata = metadata;
elem.href += encodeURIComponent(JSON.stringify(data, null, ' ')); return data;
return false;
} }
/** /**
@ -1292,21 +1331,6 @@ function buttonClick(id, classname) {
$(id).toggleClass(classname); // add the class to the clicked element $(id).toggleClass(classname); // add the class to the clicked element
} }
/**
* Shows a message to the user.
*
* @param titleString the title of the message
* @param messageString the text of the message
*/
function openMessageDialog(titleString, messageString) {
$.prompt(messageString,
{
title: titleString,
persistent: false
}
);
}
/** /**
* Locks / unlocks the room. * Locks / unlocks the room.
*/ */
@ -1417,7 +1441,7 @@ $(document).bind('fatalError.jingle',
{ {
sessionTerminated = true; sessionTerminated = true;
connection.emuc.doLeave(); connection.emuc.doLeave();
openMessageDialog( "Sorry", messageHandler.showError( "Sorry",
"Your browser version is too old. Please update and try again..."); "Your browser version is too old. Please update and try again...");
} }
); );
@ -1440,28 +1464,23 @@ $(document).bind("selectedendpointchanged", function(event, userJid) {
function callSipButtonClicked() function callSipButtonClicked()
{ {
$.prompt('<h2>Enter SIP number</h2>' + messageHandler.openTwoButtonDialog(null,
'<input id="sipNumber" type="text" value="" autofocus>', '<h2>Enter SIP number</h2>' +
{ '<input id="sipNumber" type="text"' +
persistent: false, ' value="' + config.defaultSipNumber + '" autofocus>',
buttons: { "Dial": true, "Cancel": false}, false,
defaultButton: 2, "Dial",
loaded: function (event) function (e, v, m, f) {
{ if (v) {
document.getElementById('sipNumber').focus(); var numberInput = document.getElementById('sipNumber');
}, if (numberInput.value) {
submit: function (e, v, m, f) connection.rayo.dial(
{ numberInput.value, 'fromnumber', roomName);
if (v)
{
var numberInput = document.getElementById('sipNumber');
if (numberInput.value && numberInput.value.length)
{
connection.rayo.dial(
numberInput.value, 'fromnumber', roomName);
}
} }
} }
},
function (event) {
document.getElementById('sipNumber').focus();
} }
); );
} }

View File

@ -86,6 +86,8 @@ function isUpdateRequired(minVersion, extVersion)
catch (e) catch (e)
{ {
console.error("Failed to parse extension version", e); console.error("Failed to parse extension version", e);
messageHandler.showError('Error',
'Error when trying to detect desktopsharing extension.');
return true; return true;
} }
} }
@ -166,6 +168,8 @@ function obtainScreenFromExtension(streamCallback, failCallback) {
function (arg) { function (arg) {
console.log("Failed to install the extension", arg); console.log("Failed to install the extension", arg);
failCallback(arg); failCallback(arg);
messageHandler.showError('Error',
'Failed to install desktop sharing extension');
} }
); );
} }
@ -236,6 +240,7 @@ function initInlineInstalls()
function getSwitchStreamFailed(error) { function getSwitchStreamFailed(error) {
console.error("Failed to obtain the stream to switch to", error); console.error("Failed to obtain the stream to switch to", error);
messageHandler.showError('Error', 'Failed to get video stream');
switchInProgress = false; switchInProgress = false;
} }
@ -262,6 +267,8 @@ function newStreamCreated(stream) {
} else { } else {
// We are done immediately // We are done immediately
console.error("No conference handler"); console.error("No conference handler");
messageHandler.showError('Error',
'Unable to switch video stream.');
streamSwitchDone(); streamSwitchDone();
} }
} }

View File

@ -19,7 +19,7 @@
<script src="libs/strophe/strophe.jingle.sessionbase.js?v=1"></script> <script src="libs/strophe/strophe.jingle.sessionbase.js?v=1"></script>
<script src="libs/strophe/strophe.jingle.session.js?v=1"></script> <script src="libs/strophe/strophe.jingle.session.js?v=1"></script>
<script src="libs/strophe/strophe.util.js"></script> <script src="libs/strophe/strophe.util.js"></script>
<script src="libs/colibri/colibri.focus.js?v=8"></script><!-- colibri focus implementation --> <script src="libs/colibri/colibri.focus.js?v=9"></script><!-- colibri focus implementation -->
<script src="libs/colibri/colibri.session.js?v=1"></script> <script src="libs/colibri/colibri.session.js?v=1"></script>
<script src="libs/jquery-ui.js"></script> <script src="libs/jquery-ui.js"></script>
<script src="libs/rayo.js?v=1"></script> <script src="libs/rayo.js?v=1"></script>
@ -27,25 +27,25 @@
<script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib --> <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
<script src="config.js?v=5"></script><!-- adapt to your needs, i.e. set hosts and bosh path --> <script src="config.js?v=5"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
<script src="brand.js?v=1"></script> <script src="brand.js?v=1"></script>
<script src="muc.js?v=13"></script><!-- simple MUC library --> <script src="muc.js?v=14"></script><!-- simple MUC library -->
<script src="estos_log.js?v=2"></script><!-- simple stanza logger --> <script src="estos_log.js?v=2"></script><!-- simple stanza logger -->
<script src="desktopsharing.js?v=2"></script><!-- desktop sharing --> <script src="desktopsharing.js?v=3"></script><!-- desktop sharing -->
<script src="data_channels.js?v=3"></script><!-- data channels --> <script src="data_channels.js?v=3"></script><!-- data channels -->
<script src="app.js?v=9"></script><!-- application logic --> <script src="app.js?v=10"></script><!-- application logic -->
<script src="commands.js?v=1"></script><!-- application logic --> <script src="commands.js?v=1"></script><!-- application logic -->
<script src="chat.js?v=10"></script><!-- chat logic --> <script src="chat.js?v=10"></script><!-- chat logic -->
<script src="contact_list.js?v=2"></script><!-- contact list logic --> <script src="contact_list.js?v=2"></script><!-- contact list logic -->
<script src="util.js?v=6"></script><!-- utility functions --> <script src="util.js?v=6"></script><!-- utility functions -->
<script src="etherpad.js?v=9"></script><!-- etherpad plugin --> <script src="etherpad.js?v=9"></script><!-- etherpad plugin -->
<script src="prezi.js?v=5"></script><!-- prezi plugin --> <script src="prezi.js?v=6"></script><!-- prezi plugin -->
<script src="smileys.js?v=2"></script><!-- smiley images --> <script src="smileys.js?v=2"></script><!-- smiley images -->
<script src="replacement.js?v=6"></script><!-- link and smiley replacement --> <script src="replacement.js?v=6"></script><!-- link and smiley replacement -->
<script src="moderatemuc.js?v=3"></script><!-- moderator plugin --> <script src="moderatemuc.js?v=4"></script><!-- moderator plugin -->
<script src="analytics.js?v=1"></script><!-- google analytics plugin --> <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
<script src="rtp_sts.js?v=1"></script><!-- RTP stats processing --> <script src="rtp_sts.js?v=1"></script><!-- RTP stats processing -->
<script src="local_sts.js?v=1"></script><!-- Local stats processing --> <script src="local_sts.js?v=1"></script><!-- Local stats processing -->
<script src="videolayout.js?v=9"></script><!-- video ui --> <script src="videolayout.js?v=9"></script><!-- video ui -->
<script src="toolbar.js?v=5"></script><!-- toolbar ui --> <script src="toolbar.js?v=6"></script><!-- toolbar ui -->
<script src="toolbar_toggler.js?v=1"></script> <script src="toolbar_toggler.js?v=1"></script>
<script src="canvas_util.js?v=1"></script><!-- canvas drawing utils --> <script src="canvas_util.js?v=1"></script><!-- canvas drawing utils -->
<script src="audio_levels.js?v=1"></script><!-- audio levels plugin --> <script src="audio_levels.js?v=1"></script><!-- audio levels plugin -->
@ -54,6 +54,7 @@
<script src="roomname_generator.js?v=1"></script><!-- generator for random room names --> <script src="roomname_generator.js?v=1"></script><!-- generator for random room names -->
<script src="keyboard_shortcut.js?v=2"></script> <script src="keyboard_shortcut.js?v=2"></script>
<script src="tracking.js?v=1"></script><!-- tracking --> <script src="tracking.js?v=1"></script><!-- tracking -->
<script src="message_handler.js?v=1"></script>
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet"> <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link rel="stylesheet" href="css/font.css?v=4"/> <link rel="stylesheet" href="css/font.css?v=4"/>
<link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=23"/> <link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=23"/>

View File

@ -93,7 +93,7 @@ function ColibriFocus(connection, bridgejid) {
} }
// creates a conferences with an initial set of peers // creates a conferences with an initial set of peers
ColibriFocus.prototype.makeConference = function (peers) { ColibriFocus.prototype.makeConference = function (peers, errorCallback) {
var self = this; var self = this;
if (this.confid !== null) { if (this.confid !== null) {
console.error('makeConference called twice? Ignoring...'); console.error('makeConference called twice? Ignoring...');
@ -155,7 +155,7 @@ ColibriFocus.prototype.makeConference = function (peers) {
} }
self.sendIceCandidate(event.candidate); self.sendIceCandidate(event.candidate);
}; };
this._makeConference(); this._makeConference(errorCallback);
/* /*
this.peerconnection.createOffer( this.peerconnection.createOffer(
function (offer) { function (offer) {
@ -275,7 +275,7 @@ ColibriFocus.prototype.updateEndpoints = function() {
); );
}; };
ColibriFocus.prototype._makeConference = function () { ColibriFocus.prototype._makeConference = function (errorCallback) {
var self = this; var self = this;
var elem = $iq({ to: this.bridgejid, type: 'get' }); var elem = $iq({ to: this.bridgejid, type: 'get' });
elem.c('conference', { xmlns: 'http://jitsi.org/protocol/colibri' }); elem.c('conference', { xmlns: 'http://jitsi.org/protocol/colibri' });
@ -360,6 +360,7 @@ ColibriFocus.prototype._makeConference = function () {
}, },
function (error) { function (error) {
console.warn(error); console.warn(error);
errorCallback(error);
} }
); );
}; };

87
message_handler.js Normal file
View File

@ -0,0 +1,87 @@
var messageHandler = (function(my) {
/**
* Shows a message to the user.
*
* @param titleString the title of the message
* @param messageString the text of the message
*/
my.openMessageDialog = function(titleString, messageString) {
$.prompt(messageString,
{
title: titleString,
persistent: false
}
);
};
/**
* Shows a message to the user with two buttons: first is given as a parameter and the second is Cancel.
*
* @param titleString the title of the message
* @param msgString the text of the message
* @param persistent boolean value which determines whether the message is persistent or not
* @param leftButton the fist button's text
* @param submitFunction function to be called on submit
* @param loadedFunction function to be called after the prompt is fully loaded
*/
my.openTwoButtonDialog = function(titleString, msgString, persistent, leftButton, submitFunction, loadedFunction) {
var buttons = {};
buttons[leftButton] = true;
buttons.Cancel = false;
$.prompt(msgString, {
title: titleString,
persistent: false,
buttons: buttons,
defaultButton: 1,
loaded: loadedFunction,
submit: submitFunction
});
};
/**
* Shows a dialog with different states to the user.
*
* @param statesObject object containing all the states of the dialog
* @param loadedFunction function to be called after the prompt is fully loaded
* @param stateChangedFunction function to be called when the state of the dialog is changed
*/
my.openDialogWithStates = function(statesObject, loadedFunction, stateChangedFunction) {
var myPrompt = $.prompt(statesObject);
myPrompt.on('impromptu:loaded', loadedFunction);
myPrompt.on('impromptu:statechanged', stateChangedFunction);
};
/**
* Shows a dialog prompting the user to send an error report.
*
* @param titleString the title of the message
* @param msgString the text of the message
* @param error the error that is being reported
*/
my.openReportDialog = function(titleString, msgString, error) {
my.openMessageDialog(titleString, msgString);
console.log(error);
//FIXME send the error to the server
};
/**
* Shows an error dialog to the user.
* @param title the title of the message
* @param message the text of the messafe
*/
my.showError = function(title, message) {
if(!(title || message)) {
title = title || "Oops!";
message = message || "There was some kind of error";
}
messageHandler.openMessageDialog(title, message);
};
return my;
}(messageHandler || {}));

View File

@ -34,6 +34,9 @@ Strophe.addConnectionPlugin('moderate', {
}, },
function (error) { function (error) {
console.log('set mute error', error); console.log('set mute error', error);
messageHandler.openReportDialog(null, 'Failed to mute ' +
$("#participant_" + jid).find(".displayname").text() ||
"participant" + '.', error);
}); });
}, },
onMute: function(iq) { onMute: function(iq) {

28
muc.js
View File

@ -170,12 +170,17 @@ Strophe.addConnectionPlugin('emuc', {
// we are connected with anonymous domain and only non anonymous users can create rooms // we are connected with anonymous domain and only non anonymous users can create rooms
// we must authorize the user // we must authorize the user
$(document).trigger('passwordrequired.main'); $(document).trigger('passwordrequired.main');
} } else {
else
console.warn('onPresError ', pres); console.warn('onPresError ', pres);
messageHandler.openReportDialog(null,
'Oops! Something went wrong and we couldn`t connect to the conference.',
pres);
}
} else { } else {
console.warn('onPresError ', pres); console.warn('onPresError ', pres);
messageHandler.openReportDialog(null,
'Oops! Something went wrong and we couldn`t connect to the conference.',
pres);
} }
return true; return true;
}, },
@ -241,14 +246,23 @@ Strophe.addConnectionPlugin('emuc', {
}, },
function (err) { function (err) {
console.warn('setting password failed', err); console.warn('setting password failed', err);
messageHandler.showError('Lock failed',
'Failed to lock conference.',
err);
} }
); );
} else { } else {
console.warn('room passwords not supported'); console.warn('room passwords not supported');
messageHandler.showError('Warning',
'Room passwords are currently not supported.');
} }
}, },
function (err) { function (err) {
console.warn('setting password failed', err); console.warn('setting password failed', err);
messageHandler.showError('Lock failed',
'Failed to lock conference.',
err);
} }
); );
}, },
@ -277,6 +291,10 @@ Strophe.addConnectionPlugin('emuc', {
pres.up(); pres.up();
if(this.presMap['bridgeIsDown']) {
pres.c('bridgeIsDown').up();
}
if (this.presMap['displayName']) { if (this.presMap['displayName']) {
// XEP-0172 // XEP-0172
pres.c('nick', {xmlns: 'http://jabber.org/protocol/nick'}) pres.c('nick', {xmlns: 'http://jabber.org/protocol/nick'})
@ -324,6 +342,7 @@ Strophe.addConnectionPlugin('emuc', {
).up(); ).up();
} }
} }
pres.up(); pres.up();
connection.send(pres); connection.send(pres);
}, },
@ -381,5 +400,8 @@ Strophe.addConnectionPlugin('emuc', {
return Strophe.getResourceFromJid(jid) === resourceJid; return Strophe.getResourceFromJid(jid) === resourceJid;
}); });
return peerJid; return peerJid;
},
addBridgeIsDownToPresence: function() {
this.presMap['bridgeIsDown'] = true;
} }
}); });

142
prezi.js
View File

@ -56,104 +56,96 @@ var Prezi = (function (my) {
my.openPreziDialog = function() { my.openPreziDialog = function() {
var myprezi = connection.emuc.getPrezi(connection.emuc.myroomjid); var myprezi = connection.emuc.getPrezi(connection.emuc.myroomjid);
if (myprezi) { if (myprezi) {
$.prompt("Are you sure you would like to remove your Prezi?", messageHandler.openTwoButtonDialog("Remove Prezi",
{ "Are you sure you would like to remove your Prezi?",
title: "Remove Prezi", false,
buttons: { "Remove": true, "Cancel": false}, "Remove",
defaultButton: 1, function(e,v,m,f) {
submit: function(e,v,m,f){ if(v) {
if(v)
{
connection.emuc.removePreziFromPresence(); connection.emuc.removePreziFromPresence();
connection.emuc.sendPresence(); connection.emuc.sendPresence();
} }
} }
}); );
} }
else if (preziPlayer != null) { else if (preziPlayer != null) {
$.prompt("Another participant is already sharing a Prezi." + messageHandler.openTwoButtonDialog("Share a Prezi",
"Another participant is already sharing a Prezi." +
"This conference allows only one Prezi at a time.", "This conference allows only one Prezi at a time.",
{ false,
title: "Share a Prezi", "Ok",
buttons: { "Ok": true}, function(e,v,m,f) {
defaultButton: 0, $.prompt.close();
submit: function(e,v,m,f){ }
$.prompt.close(); );
}
});
} }
else { else {
var openPreziState = { var openPreziState = {
state0: { state0: {
html: '<h2>Share a Prezi</h2>' + html: '<h2>Share a Prezi</h2>' +
'<input id="preziUrl" type="text" ' + '<input id="preziUrl" type="text" ' +
'placeholder="e.g. ' + 'placeholder="e.g. ' +
'http://prezi.com/wz7vhjycl7e6/my-prezi" autofocus>', 'http://prezi.com/wz7vhjycl7e6/my-prezi" autofocus>',
persistent: false, persistent: false,
buttons: { "Share": true , "Cancel": false}, buttons: { "Share": true , "Cancel": false},
defaultButton: 1, defaultButton: 1,
submit: function(e,v,m,f){ submit: function(e,v,m,f){
e.preventDefault(); e.preventDefault();
if(v) if(v)
{
var preziUrl = document.getElementById('preziUrl');
if (preziUrl.value)
{ {
var urlValue var preziUrl = document.getElementById('preziUrl');
= encodeURI(Util.escapeHtml(preziUrl.value));
if (urlValue.indexOf('http://prezi.com/') != 0 if (preziUrl.value)
&& urlValue.indexOf('https://prezi.com/') != 0)
{ {
$.prompt.goToState('state1'); var urlValue
return false; = encodeURI(Util.escapeHtml(preziUrl.value));
}
else { if (urlValue.indexOf('http://prezi.com/') != 0
var presIdTmp = urlValue.substring( && urlValue.indexOf('https://prezi.com/') != 0)
urlValue.indexOf("prezi.com/") + 10); {
if (!isAlphanumeric(presIdTmp)
|| presIdTmp.indexOf('/') < 2) {
$.prompt.goToState('state1'); $.prompt.goToState('state1');
return false; return false;
} }
else { else {
connection.emuc var presIdTmp = urlValue.substring(
.addPreziToPresence(urlValue, 0); urlValue.indexOf("prezi.com/") + 10);
connection.emuc.sendPresence(); if (!isAlphanumeric(presIdTmp)
$.prompt.close(); || presIdTmp.indexOf('/') < 2) {
$.prompt.goToState('state1');
return false;
}
else {
connection.emuc
.addPreziToPresence(urlValue, 0);
connection.emuc.sendPresence();
$.prompt.close();
}
} }
} }
} }
else
$.prompt.close();
}
},
state1: {
html: '<h2>Share a Prezi</h2>' +
'Please provide a correct prezi link.',
persistent: false,
buttons: { "Back": true, "Cancel": false },
defaultButton: 1,
submit:function(e,v,m,f) {
e.preventDefault();
if(v==0)
$.prompt.close();
else
$.prompt.goToState('state0');
} }
else
$.prompt.close();
} }
},
state1: {
html: '<h2>Share a Prezi</h2>' +
'Please provide a correct prezi link.',
persistent: false,
buttons: { "Back": true, "Cancel": false },
defaultButton: 1,
submit:function(e,v,m,f) {
e.preventDefault();
if(v==0)
$.prompt.close();
else
$.prompt.goToState('state0');
}
}
}; };
var focusPreziUrl = function(e) {
var myPrompt = jQuery.prompt(openPreziState); document.getElementById('preziUrl').focus();
};
myPrompt.on('impromptu:loaded', function(e) { messageHandler.openDialogWithStates(openPreziState, focusPreziUrl, focusPreziUrl);
document.getElementById('preziUrl').focus();
});
myPrompt.on('impromptu:statechanged', function(e) {
document.getElementById('preziUrl').focus();
});
} }
}; };

View File

@ -6,59 +6,51 @@ var Toolbar = (function (my) {
my.openLockDialog = function () { my.openLockDialog = function () {
// Only the focus is able to set a shared key. // Only the focus is able to set a shared key.
if (focus === null) { if (focus === null) {
if (sharedKey) if (sharedKey) {
$.prompt("This conversation is currently protected by" messageHandler.openMessageDialog(null,
+ " a shared secret key.", "This conversation is currently protected by" +
{ " a shared secret key.",
title: "Secret key", false,
persistent: false "Secret key");
} } else {
); messageHandler.openMessageDialog(null,
else "This conversation isn't currently protected by" +
$.prompt("This conversation isn't currently protected by" " a secret key. Only the owner of the conference" +
+ " a secret key. Only the owner of the conference" " could set a shared key.",
+ " could set a shared key.", false,
{ "Secret key");
title: "Secret key", }
persistent: false
}
);
} else { } else {
if (sharedKey) { if (sharedKey) {
$.prompt("Are you sure you would like to remove your secret key?", messageHandler.openTwoButtonDialog(null,
{ "Are you sure you would like to remove your secret key?",
title: "Remove secret key", false,
persistent: false, "Remove",
buttons: { "Remove": true, "Cancel": false}, function (e, v) {
defaultButton: 1, if (v) {
submit: function (e, v, m, f) { setSharedKey('');
if (v) { lockRoom(false);
setSharedKey('');
lockRoom(false);
}
} }
} });
);
} else { } else {
$.prompt('<h2>Set a secret key to lock your room</h2>' + messageHandler.openTwoButtonDialog(null,
'<input id="lockKey" type="text" placeholder="your shared key" autofocus>', '<h2>Set a secret key to lock your room</h2>' +
{ '<input id="lockKey" type="text"' +
persistent: false, 'placeholder="your shared key" autofocus>',
buttons: { "Save": true, "Cancel": false}, false,
defaultButton: 1, "Save",
loaded: function (event) { function (e, v) {
document.getElementById('lockKey').focus(); if (v) {
}, var lockKey = document.getElementById('lockKey');
submit: function (e, v, m, f) {
if (v) { if (lockKey.value) {
var lockKey = document.getElementById('lockKey'); setSharedKey(Util.escapeHtml(lockKey.value));
lockRoom(true);
if (lockKey.value) {
setSharedKey(Util.escapeHtml(lockKey.value));
lockRoom(true);
}
} }
} }
},
function () {
document.getElementById('lockKey').focus();
} }
); );
} }
@ -70,34 +62,33 @@ var Toolbar = (function (my) {
*/ */
my.openLinkDialog = function () { my.openLinkDialog = function () {
var inviteLink; var inviteLink;
if (roomUrl == null) if (roomUrl == null) {
inviteLink = "Your conference is currently being created..."; inviteLink = "Your conference is currently being created...";
else } else {
inviteLink = encodeURI(roomUrl); inviteLink = encodeURI(roomUrl);
}
$.prompt('<input id="inviteLinkRef" type="text" value="' + messageHandler.openTwoButtonDialog(
"Share this link with everyone you want to invite",
'<input id="inviteLinkRef" type="text" value="' +
inviteLink + '" onclick="this.select();" readonly>', inviteLink + '" onclick="this.select();" readonly>',
{ false,
title: "Share this link with everyone you want to invite", "Invite",
persistent: false, function (e, v) {
buttons: { "Invite": true, "Cancel": false}, if (v) {
defaultButton: 1, if (roomUrl) {
loaded: function (event) { inviteParticipants();
if (roomUrl)
document.getElementById('inviteLinkRef').select();
else
document.getElementById('jqi_state0_buttonInvite')
.disabled = true;
},
submit: function (e, v, m, f) {
if (v) {
if (roomUrl) {
inviteParticipants();
}
}
} }
} }
); },
function () {
if (roomUrl) {
document.getElementById('inviteLinkRef').select();
} else {
document.getElementById('jqi_state0_buttonInvite')
.disabled = true;
}
}
);
}; };
/** /**
@ -108,11 +99,12 @@ var Toolbar = (function (my) {
return; return;
var sharedKeyText = ""; var sharedKeyText = "";
if (sharedKey && sharedKey.length > 0) if (sharedKey && sharedKey.length > 0) {
sharedKeyText sharedKeyText =
= "This conference is password protected. Please use the " "This conference is password protected. Please use the " +
+ "following pin when joining:%0D%0A%0D%0A" "following pin when joining:%0D%0A%0D%0A" +
+ sharedKey + "%0D%0A%0D%0A"; sharedKey + "%0D%0A%0D%0A";
}
var conferenceName = roomUrl.substring(roomUrl.lastIndexOf('/') + 1); var conferenceName = roomUrl.substring(roomUrl.lastIndexOf('/') + 1);
var subject = "Invitation to a Jitsi Meet (" + conferenceName + ")"; var subject = "Invitation to a Jitsi Meet (" + conferenceName + ")";
@ -128,8 +120,9 @@ var Toolbar = (function (my) {
" to be using one of these browsers.%0D%0A%0D%0A" + " to be using one of these browsers.%0D%0A%0D%0A" +
"Talk to you in a sec!"; "Talk to you in a sec!";
if (window.localStorage.displayname) if (window.localStorage.displayname) {
body += "%0D%0A%0D%0A" + window.localStorage.displayname; body += "%0D%0A%0D%0A" + window.localStorage.displayname;
}
window.open("mailto:?subject=" + subject + "&body=" + body, '_blank'); window.open("mailto:?subject=" + subject + "&body=" + body, '_blank');
} }
@ -138,36 +131,38 @@ var Toolbar = (function (my) {
* Opens the settings dialog. * Opens the settings dialog.
*/ */
my.openSettingsDialog = function () { my.openSettingsDialog = function () {
$.prompt('<h2>Configure your conference</h2>' + messageHandler.openTwoButtonDialog(
'<input type="checkbox" id="initMuted"> Participants join muted<br/>' + '<h2>Configure your conference</h2>' +
'<input type="checkbox" id="requireNicknames"> Require nicknames<br/><br/>' + '<input type="checkbox" id="initMuted">' +
'Set a secret key to lock your room: <input id="lockKey" type="text" placeholder="your shared key" autofocus>', 'Participants join muted<br/>' +
{ '<input type="checkbox" id="requireNicknames">' +
persistent: false, 'Require nicknames<br/><br/>' +
buttons: { "Save": true, "Cancel": false}, 'Set a secret key to lock your room:' +
defaultButton: 1, '<input id="lockKey" type="text" placeholder="your shared key"' +
loaded: function (event) { 'autofocus>',
document.getElementById('lockKey').focus(); null,
}, false,
submit: function (e, v, m, f) { "Save",
if (v) { function () {
if ($('#initMuted').is(":checked")) { document.getElementById('lockKey').focus();
// it is checked },
} function (e, v) {
if (v) {
if ($('#requireNicknames').is(":checked")) { if ($('#initMuted').is(":checked")) {
// it is checked // it is checked
}
/*
var lockKey = document.getElementById('lockKey');
if (lockKey.value)
{
setSharedKey(lockKey.value);
lockRoom(true);
}
*/
} }
if ($('#requireNicknames').is(":checked")) {
// it is checked
}
/*
var lockKey = document.getElementById('lockKey');
if (lockKey.value) {
setSharedKey(lockKey.value);
lockRoom(true);
}
*/
} }
} }
); );
@ -224,14 +219,10 @@ var Toolbar = (function (my) {
}; };
// Shows or hides SIP calls button // Shows or hides SIP calls button
my.showSipCallButton = function (show) my.showSipCallButton = function(show){
{ if (config.hosts.call_control && show) {
if (config.hosts.call_control && show)
{
$('#sipCallButton').css({display: "inline"}); $('#sipCallButton').css({display: "inline"});
} } else {
else
{
$('#sipCallButton').css({display: "none"}); $('#sipCallButton').css({display: "none"});
} }
}; };