Merge pull request #421 from isymchych/use-API

Use JS API in jitsi-meet
This commit is contained in:
hristoterezov 2015-12-03 16:21:03 -06:00
commit 98f0de258b
25 changed files with 23448 additions and 847 deletions

10
.editorconfig Normal file
View File

@ -0,0 +1,10 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
max_line_length = 80
trim_trailing_whitespace = true

View File

@ -2,6 +2,7 @@ node_modules
libs libs
debian debian
analytics.js analytics.js
lib-jitsi-meet.js
modules/xmpp/strophe.emuc.js modules/xmpp/strophe.emuc.js
modules/UI/prezi/Prezi.js modules/UI/prezi/Prezi.js

View File

@ -8,10 +8,13 @@ DEPLOY_DIR = libs
BROWSERIFY_FLAGS = -d BROWSERIFY_FLAGS = -d
OUTPUT_DIR = . OUTPUT_DIR = .
all: compile uglify deploy clean all: update-deps compile uglify deploy clean
update-deps:
$(NPM) update
compile: compile:
$(NPM) update && $(BROWSERIFY) $(BROWSERIFY_FLAGS) -e app.js -s APP | $(EXORCIST) $(OUTPUT_DIR)/app.bundle.js.map > $(OUTPUT_DIR)/app.bundle.js $(BROWSERIFY) $(BROWSERIFY_FLAGS) -e app.js -s APP | $(EXORCIST) $(OUTPUT_DIR)/app.bundle.js.map > $(OUTPUT_DIR)/app.bundle.js
clean: clean:
rm -f $(OUTPUT_DIR)/app.bundle.* rm -f $(OUTPUT_DIR)/app.bundle.*

307
app.js
View File

@ -1,4 +1,4 @@
/* jshint -W117 */ /* global $, JitsiMeetJS, config, Promise */
/* application specific logic */ /* application specific logic */
require("jquery"); require("jquery");
@ -12,37 +12,314 @@ window.toastr = require("toastr");
require("jQuery-Impromptu"); require("jQuery-Impromptu");
require("autosize"); require("autosize");
var APP = var CQEvents = require('./service/connectionquality/CQEvents');
{ var UIEvents = require('./service/UI/UIEvents');
var Commands = {
CONNECTION_QUALITY: "connectionQuality",
EMAIL: "email"
};
var APP = {
init: function () { init: function () {
JitsiMeetJS.init();
JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.TRACE);
this.conference = {
localId: undefined,
isModerator: false,
membersCount: 0,
audioMuted: false,
videoMuted: false,
isLocalId: function (id) {
return this.localId === id;
},
muteAudio: function (mute) {
APP.UI.eventEmitter.emit(UIEvents.AUDIO_MUTED, mute);
},
toggleAudioMuted: function () {
this.muteAudio(!this.audioMuted);
},
muteVideo: function (mute) {
APP.UI.eventEmitter.emit(UIEvents.VIDEO_MUTED, mute);
},
toggleVideoMuted: function () {
this.muteVideo(!this.videoMuted);
}
};
this.UI = require("./modules/UI/UI"); this.UI = require("./modules/UI/UI");
this.API = require("./modules/API/API"); this.API = require("./modules/API/API");
this.connectionquality = this.connectionquality =
require("./modules/connectionquality/connectionquality"); require("./modules/connectionquality/connectionquality");
this.statistics = require("./modules/statistics/statistics"); this.statistics = require("./modules/statistics/statistics");
this.RTC = require("./modules/RTC/RTC");
this.desktopsharing = this.desktopsharing =
require("./modules/desktopsharing/desktopsharing"); require("./modules/desktopsharing/desktopsharing");
this.xmpp = require("./modules/xmpp/xmpp");
this.keyboardshortcut = this.keyboardshortcut =
require("./modules/keyboardshortcut/keyboardshortcut"); require("./modules/keyboardshortcut/keyboardshortcut");
this.translation = require("./modules/translation/translation"); this.translation = require("./modules/translation/translation");
this.settings = require("./modules/settings/Settings"); this.settings = require("./modules/settings/Settings");
//this.DTMF = require("./modules/DTMF/DTMF");
this.members = require("./modules/members/MemberList");
this.configFetch = require("./modules/config/HttpConfigFetch"); this.configFetch = require("./modules/config/HttpConfigFetch");
} }
}; };
var ConnectionEvents = JitsiMeetJS.events.connection;
var ConnectionErrors = JitsiMeetJS.errors.connection;
function connect() {
var connection = new JitsiMeetJS.JitsiConnection(null, null, {
hosts: config.hosts,
bosh: config.bosh,
clientNode: config.clientNode
});
return new Promise(function (resolve, reject) {
var handlers = {};
var unsubscribe = function () {
Object.keys(handlers).forEach(function (event) {
connection.removeEventListener(event, handlers[event]);
});
};
handlers[ConnectionEvents.CONNECTION_ESTABLISHED] = function () {
console.log('CONNECTED');
unsubscribe();
resolve(connection);
};
var listenForFailure = function (event) {
handlers[event] = function () {
// convert arguments to array
var args = Array.prototype.slice.call(arguments);
args.unshift(event);
// [event, ...params]
console.error('CONNECTION FAILED:', args);
unsubscribe();
reject(args);
};
};
listenForFailure(ConnectionEvents.CONNECTION_FAILED);
listenForFailure(ConnectionErrors.PASSWORD_REQUIRED);
listenForFailure(ConnectionErrors.CONNECTION_ERROR);
listenForFailure(ConnectionErrors.OTHER_ERRORS);
// install event listeners
Object.keys(handlers).forEach(function (event) {
connection.addEventListener(event, handlers[event]);
});
connection.connect();
}).catch(function (err) {
if (err[0] === ConnectionErrors.PASSWORD_REQUIRED) {
// FIXME ask for password and try again
return connect();
}
console.error('FAILED TO CONNECT', err);
APP.UI.notifyConnectionFailed(err[1]);
throw new Error(err[0]);
});
}
var ConferenceEvents = JitsiMeetJS.events.conference;
var ConferenceErrors = JitsiMeetJS.errors.conference;
function initConference(connection, roomName) {
var room = connection.initJitsiConference(roomName, {
openSctp: config.openSctp,
disableAudioLevels: config.disableAudioLevels
});
var users = {};
var localTracks = [];
APP.conference.localId = room.myUserId();
Object.defineProperty(APP.conference, "membersCount", {
get: function () {
return Object.keys(users).length; // FIXME maybe +1?
}
});
room.on(ConferenceEvents.USER_JOINED, function (id) {
users[id] = {
displayName: undefined,
tracks: []
};
// FIXME email???
APP.UI.addUser(id);
});
room.on(ConferenceEvents.USER_LEFT, function (id) {
delete users[id];
APP.UI.removeUser(id);
});
room.on(ConferenceEvents.TRACK_MUTE_CHANGED, function (track) {
// FIXME handle mute
});
room.on(ConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED, function (id, lvl) {
APP.UI.setAudioLevel(id, lvl);
});
APP.UI.addListener(UIEvents.AUDIO_MUTED, function (muted) {
// FIXME mute or unmute
APP.UI.setAudioMuted(muted);
APP.conference.audioMuted = muted;
});
APP.UI.addListener(UIEvents.VIDEO_MUTED, function (muted) {
// FIXME mute or unmute
APP.UI.setVideoMuted(muted);
APP.conference.videoMuted = muted;
});
room.on(ConferenceEvents.IN_LAST_N_CHANGED, function (inLastN) {
if (config.muteLocalVideoIfNotInLastN) {
// TODO mute or unmute if required
// mark video on UI
// APP.UI.markVideoMuted(true/false);
}
});
room.on(ConferenceEvents.LAST_N_ENDPOINTS_CHANGED, function (ids) {
APP.UI.handleLastNEndpoints(ids);
});
room.on(ConferenceEvents.ACTIVE_SPEAKER_CHANGED, function (id) {
APP.UI.markDominantSpiker(id);
});
room.on(ConferenceEvents.CONNECTION_INTERRUPTED, function () {
APP.UI.markVideoInterrupted(true);
});
room.on(ConferenceEvents.CONNECTION_RESTORED, function () {
APP.UI.markVideoInterrupted(false);
});
APP.connectionquality.addListener(
CQEvents.LOCALSTATS_UPDATED,
function (percent, stats) {
APP.UI.updateLocalStats(percent, stats);
// send local stats to other users
room.sendCommand(Commands.CONNECTION_QUALITY, {
value: APP.connectionquality.convertToMUCStats(stats),
attributes: {
id: room.myUserId()
}
});
}
);
APP.connectionquality.addListener(CQEvents.STOP, function () {
APP.UI.hideStats();
room.removeCommand(Commands.CONNECTION_QUALITY);
});
// listen to remote stats
room.addCommandListener(Commands.CONNECTION_QUALITY, function (data) {
APP.connectionquality.updateRemoteStats(data.attributes.id, data.value);
});
APP.connectionquality.addListener(
CQEvents.REMOTESTATS_UPDATED,
function (id, percent, stats) {
APP.UI.updateRemoteStats(id, percent, stats);
}
);
// share email with other users
function sendEmail(email) {
room.sendCommand(Commands.EMAIL, {
value: email,
attributes: {
id: room.myUserId()
}
});
}
var email = APP.settings.getEmail();
email && sendEmail(email);
APP.UI.addListener(UIEvents.EMAIL_CHANGED, function (email) {
APP.settings.setEmail(email);
APP.UI.setUserAvatar(room.myUserId(), email);
sendEmail(email);
});
room.addCommandListener(Commands.EMAIL, function (data) {
APP.UI.setUserAvatar(data.attributes.id, data.value);
});
room.on(ConferenceEvents.DISPLAY_NAME_CHANGED, function (id, displayName) {
APP.UI.changeDisplayName(id, displayName);
});
APP.UI.addListener(UIEvents.NICKNAME_CHANGED, function (nickname) {
APP.settings.setDisplayName(nickname);
room.setDisplayName(nickname);
});
APP.UI.addListener(UIEvents.MESSAGE_CREATED, function (message) {
room.sendTextMessage(message);
});
room.on(ConferenceErrors.PASSWORD_REQUIRED, function () {
// FIXME handle
});
room.on(ConferenceErrors.CONNECTION_ERROR, function () {
// FIXME handle
});
APP.UI.addListener(
UIEvents.START_MUTED_CHANGED,
function (startAudioMuted, startVideoMuted) {
// FIXME start muted
}
);
return new Promise(function (resolve, reject) {
room.on(
ConferenceEvents.CONFERENCE_JOINED,
function () {
resolve();
}
);
APP.UI.closeAuthenticationDialog();
if (config.useNicks) {
// FIXME check this
var nick = APP.UI.askForNickname();
}
room.join();
}).catch(function (err) {
if (err[0] === ConferenceErrors.PASSWORD_REQUIRED) {
// FIXME ask for password and try again
return initConference(connection, roomName);
}
// FIXME else notify that we cannot conenct to the room
throw new Error(err[0]);
});
}
function init() { function init() {
connect().then(function (connection) {
return initConference(connection, APP.UI.generateRoomName());
}).then(function () {
APP.UI.start();
APP.UI.initConference();
APP.UI.addListener(UIEvents.LANG_CHANGED, function (language) {
APP.translation.setLanguage(language);
APP.settings.setLanguage(language);
});
APP.desktopsharing.init(); APP.desktopsharing.init();
APP.RTC.start();
APP.xmpp.start();
APP.statistics.start(); APP.statistics.start();
APP.connectionquality.init(); APP.connectionquality.init();
APP.keyboardshortcut.init(); APP.keyboardshortcut.init();
APP.members.start(); });
} }
/** /**
@ -90,17 +367,17 @@ $(document).ready(function () {
APP.translation.init(); APP.translation.init();
if(APP.API.isEnabled()) if (APP.API.isEnabled()) {
APP.API.init(); APP.API.init();
}
APP.UI.start(obtainConfigAndInit); obtainConfigAndInit();
}); });
$(window).bind('beforeunload', function () { $(window).bind('beforeunload', function () {
if(APP.API.isEnabled()) if (APP.API.isEnabled()) {
APP.API.dispose(); APP.API.dispose();
}
}); });
module.exports = APP; module.exports = APP;

View File

@ -14,6 +14,7 @@
<script src="https://api.callstats.io/static/callstats.min.js"></script> <script src="https://api.callstats.io/static/callstats.min.js"></script>
<script src="config.js?v=15"></script><!-- adapt to your needs, i.e. set hosts and bosh path --> <script src="config.js?v=15"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
<script src="interface_config.js?v=6"></script> <script src="interface_config.js?v=6"></script>
<script src="lib-jitsi-meet.js?v=139"></script>
<script src="libs/app.bundle.min.js?v=139"></script> <script src="libs/app.bundle.min.js?v=139"></script>
<script src="analytics.js?v=1"></script><!-- google analytics plugin --> <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
<!-- <!--

22739
lib-jitsi-meet.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -23,8 +23,8 @@ var commands = {};
function initCommands() { function initCommands() {
commands = { commands = {
displayName: APP.UI.inputDisplayNameHandler, displayName: APP.UI.inputDisplayNameHandler,
toggleAudio: APP.UI.toggleAudio, toggleAudio: APP.conference.toggleAudioMuted,
toggleVideo: APP.UI.toggleVideo, toggleVideo: APP.conference.toggleVideoMuted,
toggleFilmStrip: APP.UI.toggleFilmStrip, toggleFilmStrip: APP.UI.toggleFilmStrip,
toggleChat: APP.UI.toggleChat, toggleChat: APP.UI.toggleChat,
toggleContactList: APP.UI.toggleContactList toggleContactList: APP.UI.toggleContactList

View File

@ -21,22 +21,16 @@ UI.messageHandler = require("./util/MessageHandler");
var messageHandler = UI.messageHandler; var messageHandler = UI.messageHandler;
var Authentication = require("./authentication/Authentication"); var Authentication = require("./authentication/Authentication");
var UIUtil = require("./util/UIUtil"); var UIUtil = require("./util/UIUtil");
var NicknameHandler = require("./util/NicknameHandler");
var JitsiPopover = require("./util/JitsiPopover"); var JitsiPopover = require("./util/JitsiPopover");
var CQEvents = require("../../service/connectionquality/CQEvents"); var CQEvents = require("../../service/connectionquality/CQEvents");
var DesktopSharingEventTypes var DesktopSharingEventTypes
= require("../../service/desktopsharing/DesktopSharingEventTypes"); = require("../../service/desktopsharing/DesktopSharingEventTypes");
var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
var RTCEvents = require("../../service/RTC/RTCEvents");
var RTCBrowserType = require("../RTC/RTCBrowserType");
var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
var StatisticsEvents = require("../../service/statistics/Events"); var StatisticsEvents = require("../../service/statistics/Events");
var UIEvents = require("../../service/UI/UIEvents"); var UIEvents = require("../../service/UI/UIEvents");
var MemberEvents = require("../../service/members/Events");
var Feedback = require("./Feedback"); var Feedback = require("./Feedback");
var eventEmitter = new EventEmitter(); var eventEmitter = new EventEmitter();
UI.eventEmitter = eventEmitter;
var roomNode = null; var roomNode = null;
var roomName = null; var roomName = null;
@ -64,7 +58,7 @@ function promptDisplayName() {
if (v == "ok") { if (v == "ok") {
var displayName = f.displayName; var displayName = f.displayName;
if (displayName) { if (displayName) {
VideoLayout.inputDisplayNameHandler(displayName); UI.inputDisplayNameHandler(displayName);
return true; return true;
} }
} }
@ -86,11 +80,6 @@ function promptDisplayName() {
); );
} }
function notifyForInitialMute() {
messageHandler.notify(null, "notify.mutedTitle", "connected",
"notify.muted", null, {timeOut: 120000});
}
function setupPrezi() { function setupPrezi() {
$("#reloadPresentationLink").click(function() { $("#reloadPresentationLink").click(function() {
Prezi.reloadPresentation(); Prezi.reloadPresentation();
@ -98,137 +87,26 @@ function setupPrezi() {
} }
function setupChat() { function setupChat() {
Chat.init(); Chat.init(eventEmitter);
$("#toggle_smileys").click(function() { $("#toggle_smileys").click(function() {
Chat.toggleSmileys(); Chat.toggleSmileys();
}); });
} }
function setupToolbars() { function setupToolbars() {
Toolbar.init(UI); Toolbar.init(eventEmitter);
Toolbar.setupButtonsFromConfig(); Toolbar.setupButtonsFromConfig();
BottomToolbar.init(eventEmitter); BottomToolbar.init(eventEmitter);
} }
function streamHandler(stream, isMuted) { UI.notifyGracefulShudown = function () {
switch (stream.type) {
case MediaStreamType.AUDIO_TYPE:
VideoLayout.changeLocalAudio(stream, isMuted);
break;
case MediaStreamType.VIDEO_TYPE:
VideoLayout.changeLocalVideo(stream, isMuted);
break;
default:
console.error("Unknown stream type: " + stream.type);
break;
}
}
function onXmppConnectionFailed(stropheErrorMsg) {
var title = APP.translation.generateTranslationHTML(
"dialog.error");
var message;
if (stropheErrorMsg) {
message = APP.translation.generateTranslationHTML(
"dialog.connectErrorWithMsg", {msg: stropheErrorMsg});
} else {
message = APP.translation.generateTranslationHTML(
"dialog.connectError");
}
messageHandler.openDialog(
title, message, true, {}, function (e, v, m, f) { return false; });
}
function onDisposeConference(unload) {
Toolbar.showAuthenticateButton(false);
}
function onDisplayNameChanged(jid, displayName) {
ContactList.onDisplayNameChange(jid, displayName);
SettingsMenu.onDisplayNameChange(jid, displayName);
VideoLayout.onDisplayNameChanged(jid, displayName);
}
function registerListeners() {
APP.RTC.addStreamListener(streamHandler,
StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
APP.RTC.addStreamListener(streamHandler,
StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED);
APP.RTC.addStreamListener(function (stream) {
VideoLayout.onRemoteStreamAdded(stream);
}, StreamEventTypes.EVENT_TYPE_REMOTE_CREATED);
APP.RTC.addListener(RTCEvents.LASTN_CHANGED, onLastNChanged);
APP.RTC.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED,
function (resourceJid) {
VideoLayout.onDominantSpeakerChanged(resourceJid);
});
APP.RTC.addListener(RTCEvents.LASTN_ENDPOINT_CHANGED,
function (lastNEndpoints, endpointsEnteringLastN, stream) {
VideoLayout.onLastNEndpointsChanged(lastNEndpoints,
endpointsEnteringLastN, stream);
});
APP.RTC.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED,
function (devices) {
VideoLayout.setDeviceAvailabilityIcons(null, devices);
});
APP.RTC.addListener(RTCEvents.VIDEO_MUTE, UI.setVideoMuteButtonsState);
APP.RTC.addListener(RTCEvents.DATA_CHANNEL_OPEN, function () {
// when the data channel becomes available, tell the bridge about video
// selections so that it can do adaptive simulcast,
// we want the notification to trigger even if userJid is undefined,
// or null.
var userResource = APP.UI.getLargeVideoResource();
eventEmitter.emit(UIEvents.SELECTED_ENDPOINT, userResource);
});
APP.statistics.addListener(StatisticsEvents.AUDIO_LEVEL,
function(jid, audioLevel) {
var resourceJid;
if(jid === APP.statistics.LOCAL_JID) {
resourceJid = AudioLevels.LOCAL_LEVEL;
if(APP.RTC.localAudio.isMuted()) {
audioLevel = 0;
}
} else {
resourceJid = Strophe.getResourceFromJid(jid);
}
AudioLevels.updateAudioLevel(resourceJid, audioLevel,
UI.getLargeVideoResource());
});
APP.desktopsharing.addListener(
DesktopSharingEventTypes.INIT,
ToolbarToggler.showToolbar);
APP.desktopsharing.addListener(
DesktopSharingEventTypes.SWITCHING_DONE,
Toolbar.changeDesktopSharingButtonState);
APP.desktopsharing.addListener(
DesktopSharingEventTypes.FIREFOX_EXTENSION_NEEDED,
function (url) {
APP.UI.messageHandler.openMessageDialog(
"dialog.extensionRequired",
null,
null,
APP.translation.generateTranslationHTML(
"dialog.firefoxExtensionPrompt", {url: url}));
});
APP.connectionquality.addListener(CQEvents.LOCALSTATS_UPDATED,
VideoLayout.updateLocalConnectionStats);
APP.connectionquality.addListener(CQEvents.REMOTESTATS_UPDATED,
VideoLayout.updateConnectionStats);
APP.connectionquality.addListener(CQEvents.STOP,
VideoLayout.onStatsStop);
APP.xmpp.addListener(XMPPEvents.CONNECTION_FAILED, onXmppConnectionFailed);
APP.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE, onDisposeConference);
APP.xmpp.addListener(XMPPEvents.GRACEFUL_SHUTDOWN, function () {
messageHandler.openMessageDialog( messageHandler.openMessageDialog(
'dialog.serviceUnavailable', 'dialog.serviceUnavailable',
'dialog.gracefulShutdown' 'dialog.gracefulShutdown'
); );
}); };
APP.xmpp.addListener(XMPPEvents.RESERVATION_ERROR, function (code, msg) {
UI.notifyReservationError = function (code, msg) {
var title = APP.translation.generateTranslationHTML( var title = APP.translation.generateTranslationHTML(
"dialog.reservationError"); "dialog.reservationError");
var message = APP.translation.generateTranslationHTML( var message = APP.translation.generateTranslationHTML(
@ -241,104 +119,51 @@ function registerListeners() {
return false; return false;
} }
); );
}); };
APP.xmpp.addListener(XMPPEvents.KICKED, function () {
messageHandler.openMessageDialog("dialog.sessTerminated", UI.notifyKicked = function () {
"dialog.kickMessage"); messageHandler.openMessageDialog("dialog.sessTerminated", "dialog.kickMessage");
}); };
APP.xmpp.addListener(XMPPEvents.MUC_DESTROYED, function (reason) {
//FIXME: use Session Terminated from translation, but UI.notifyBridgeDown = function () {
// 'reason' text comes from XMPP packet and is not translated messageHandler.showError("dialog.error", "dialog.bridgeUnavailable");
var title = APP.translation.generateTranslationHTML("dialog.sessTerminated"); };
messageHandler.openDialog(
title, reason, true, {}, UI.changeDisplayName = function (id, displayName) {
function (event, value, message, formVals) { ContactList.onDisplayNameChange(id, displayName);
return false; SettingsMenu.onDisplayNameChange(id, displayName);
VideoLayout.onDisplayNameChanged(id, displayName);
};
UI.initConference = function () {
var id = APP.conference.localId;
Toolbar.updateRoomUrl(window.location.href);
var meHTML = APP.translation.generateTranslationHTML("me");
var settings = Settings.getSettings();
$("#localNick").html(settings.email || settings.uid + " (" + meHTML + ")");
// Make sure we configure our avatar id, before creating avatar for us
UI.setUserAvatar(id, settings.email || settings.uid);
// Add myself to the contact list.
ContactList.addContact(id);
// Once we've joined the muc show the toolbar
ToolbarToggler.showToolbar();
var displayName = config.displayJids ? id : settings.displayName;
if (displayName) {
UI.changeDisplayName('localVideoContainer', displayName);
} }
);
});
APP.xmpp.addListener(XMPPEvents.BRIDGE_DOWN, function () {
messageHandler.showError("dialog.error",
"dialog.bridgeUnavailable");
});
APP.xmpp.addListener(XMPPEvents.USER_ID_CHANGED, function (from, id) {
Avatar.setUserAvatar(from, id);
});
APP.xmpp.addListener(XMPPEvents.DISPLAY_NAME_CHANGED, onDisplayNameChanged);
APP.xmpp.addListener(XMPPEvents.MUC_JOINED, onMucJoined);
APP.xmpp.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, onLocalRoleChanged);
APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_JOINED, onMucMemberJoined);
APP.xmpp.addListener(XMPPEvents.MUC_ROLE_CHANGED, onMucRoleChanged);
APP.xmpp.addListener(XMPPEvents.PRESENCE_STATUS, onMucPresenceStatus);
APP.xmpp.addListener(XMPPEvents.SUBJECT_CHANGED, chatSetSubject);
APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_LEFT, onMucMemberLeft);
APP.xmpp.addListener(XMPPEvents.PASSWORD_REQUIRED, onPasswordRequired);
APP.xmpp.addListener(XMPPEvents.ETHERPAD, initEtherpad);
APP.xmpp.addListener(XMPPEvents.AUTHENTICATION_REQUIRED,
onAuthenticationRequired);
APP.xmpp.addListener(XMPPEvents.PARTICIPANT_VIDEO_TYPE_CHANGED,
onPeerVideoTypeChanged);
APP.xmpp.addListener(XMPPEvents.DEVICE_AVAILABLE,
function (resource, devices) {
VideoLayout.setDeviceAvailabilityIcons(resource, devices);
});
APP.xmpp.addListener(XMPPEvents.PARTICIPANT_AUDIO_MUTED, VideoLayout.mucJoined();
VideoLayout.onAudioMute);
APP.xmpp.addListener(XMPPEvents.PARTICIPANT_VIDEO_MUTED,
VideoLayout.onVideoMute);
APP.xmpp.addListener(XMPPEvents.AUDIO_MUTED_BY_FOCUS, function (doMuteAudio) {
UI.setAudioMuted(doMuteAudio);
});
APP.members.addListener(MemberEvents.DTMF_SUPPORT_CHANGED,
onDtmfSupportChanged);
APP.xmpp.addListener(XMPPEvents.START_MUTED_SETTING_CHANGED, function (audio, video) {
SettingsMenu.setStartMuted(audio, video);
});
APP.xmpp.addListener(XMPPEvents.START_MUTED_FROM_FOCUS, function (audio, video) {
UI.setInitialMuteFromFocus(audio, video);
});
APP.xmpp.addListener(XMPPEvents.JINGLE_FATAL_ERROR, function (session, error) { Toolbar.checkAutoEnableDesktopSharing();
UI.messageHandler.showError("dialog.sorry", };
"dialog.internalError");
});
APP.xmpp.addListener(XMPPEvents.PROMPT_FOR_LOGIN, function (callback) {
// FIXME: re-use LoginDialog which supports retries
if (config.token) {
messageHandler.showError("dialog.error", "dialog.tokenAuthFailed");
} else {
UI.showLoginPopup(callback);
}
});
APP.xmpp.addListener(XMPPEvents.FOCUS_DISCONNECTED, function (focusComponent, retrySec) {
UI.messageHandler.notify(
null, "notify.focus",
'disconnected', "notify.focusFail",
{component: focusComponent, ms: retrySec});
});
APP.xmpp.addListener(XMPPEvents.ROOM_JOIN_ERROR, function (pres) {
UI.messageHandler.openReportDialog(null,
"dialog.connectError", pres);
});
APP.xmpp.addListener(XMPPEvents.ROOM_CONNECT_ERROR, function (pres) {
UI.messageHandler.openReportDialog(null,
"dialog.connectError", pres);
});
APP.xmpp.addListener(XMPPEvents.READY_TO_JOIN, function () {
var roomName = UI.generateRoomName();
APP.xmpp.allocateConferenceFocus(roomName, UI.checkForNicknameAndJoin);
});
//NicknameHandler emits this event
UI.addListener(UIEvents.NICKNAME_CHANGED, function (nickname) {
APP.xmpp.addToPresence("displayName", nickname);
});
function registerListeners() {
UI.addListener(UIEvents.LARGEVIDEO_INIT, function () { UI.addListener(UIEvents.LARGEVIDEO_INIT, function () {
AudioLevels.init(); AudioLevels.init();
}); });
@ -347,48 +172,26 @@ function registerListeners() {
VideoLayout.onFilmStripToggled(isToggled); VideoLayout.onFilmStripToggled(isToggled);
}); });
if (!interfaceConfig.filmStripOnly) { UI.addListener(UIEvents.EMAIL_CHANGED, function (email) {
APP.xmpp.addListener(XMPPEvents.MESSAGE_RECEIVED, updateChatConversation); UI.setUserAvatar(APP.conference.localId, email);
APP.xmpp.addListener(XMPPEvents.CHAT_ERROR_RECEIVED, chatAddError); });
// Listens for video interruption events.
APP.xmpp.addListener(XMPPEvents.CONNECTION_INTERRUPTED, VideoLayout.onVideoInterrupted);
// Listens for video restores events.
APP.xmpp.addListener(XMPPEvents.CONNECTION_RESTORED, VideoLayout.onVideoRestored);
}
}
/**
* Mutes/unmutes the local video.
*
* @param mute <tt>true</tt> to mute the local video; otherwise, <tt>false</tt>
* @param options an object which specifies optional arguments such as the
* <tt>boolean</tt> key <tt>byUser</tt> with default value <tt>true</tt> which
* specifies whether the method was initiated in response to a user command (in
* contrast to an automatic decision taken by the application logic)
*/
function setVideoMute(mute, options) {
APP.RTC.setVideoMute(mute,
UI.setVideoMuteButtonsState,
options);
} }
function bindEvents() {
function onResize() { function onResize() {
Chat.resizeChat(); Chat.resizeChat();
VideoLayout.resizeLargeVideoContainer(); VideoLayout.resizeLargeVideoContainer();
} }
function bindEvents() { // Resize and reposition videos in full screen mode.
/** $(document).on(
* Resizes and repositions videos in full screen mode. 'webkitfullscreenchange mozfullscreenchange fullscreenchange', onResize
*/ );
$(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange',
onResize);
$(window).resize(onResize); $(window).resize(onResize);
} }
UI.start = function (init) { UI.start = function () {
document.title = interfaceConfig.APP_NAME; document.title = interfaceConfig.APP_NAME;
var setupWelcomePage = null; var setupWelcomePage = null;
if(config.enableWelcomePage && window.location.pathname == "/" && if(config.enableWelcomePage && window.location.pathname == "/" &&
@ -407,11 +210,9 @@ UI.start = function (init) {
// Set the defaults for prompt dialogs. // Set the defaults for prompt dialogs.
$.prompt.setDefaults({persistent: false}); $.prompt.setDefaults({persistent: false});
registerListeners(); registerListeners();
VideoLayout.init(eventEmitter); VideoLayout.init(eventEmitter);
NicknameHandler.init(eventEmitter);
bindEvents(); bindEvents();
setupPrezi(); setupPrezi();
@ -427,12 +228,11 @@ UI.start = function (init) {
$('#notice').css({display: 'block'}); $('#notice').css({display: 'block'});
} }
$("#downloadlog").click(function (event) { $("#downloadlog").click(function (event) {
dump(event.target); // dump(event.target);
// FIXME integrate logs
}); });
Feedback.init(); Feedback.init();
} } else {
else
{
$("#header").css("display", "none"); $("#header").css("display", "none");
$("#bottomToolbar").css("display", "none"); $("#bottomToolbar").css("display", "none");
$("#downloadlog").css("display", "none"); $("#downloadlog").css("display", "none");
@ -440,25 +240,17 @@ UI.start = function (init) {
$("#remoteVideos").css("right", "0px"); $("#remoteVideos").css("right", "0px");
messageHandler.disableNotifications(); messageHandler.disableNotifications();
$('body').popover("disable"); $('body').popover("disable");
// $("[data-toggle=popover]").popover("disable");
JitsiPopover.enabled = false; JitsiPopover.enabled = false;
} }
document.title = interfaceConfig.APP_NAME; document.title = interfaceConfig.APP_NAME;
if(config.requireDisplayName) { if(config.requireDisplayName) {
var currentSettings = Settings.getSettings(); if (APP.settings.getDisplayName()) {
if (!currentSettings.displayName) {
promptDisplayName(); promptDisplayName();
} }
} }
init();
if (!interfaceConfig.filmStripOnly) { if (!interfaceConfig.filmStripOnly) {
toastr.options = { toastr.options = {
"closeButton": true, "closeButton": true,
@ -483,12 +275,31 @@ UI.start = function (init) {
"newestOnTop": false "newestOnTop": false
}; };
SettingsMenu.init(); SettingsMenu.init();
} }
}; };
UI.addLocalStream = function (stream, isMuted) {
switch (stream.type) {
case 'audio':
VideoLayout.changeLocalAudio(stream, isMuted);
break;
case 'video':
VideoLayout.changeLocalVideo(stream, isMuted);
break;
default:
console.error("Unknown stream type: " + stream.type);
break;
}
};
UI.addRemoteStream = function (stream) {
VideoLayout.onRemoteStreamAdded(stream);
};
function chatAddError(errorMessage, originalText) { function chatAddError(errorMessage, originalText) {
return Chat.chatAddError(errorMessage, originalText); return Chat.chatAddError(errorMessage, originalText);
} }
@ -497,59 +308,14 @@ function chatSetSubject(text) {
return Chat.chatSetSubject(text); return Chat.chatSetSubject(text);
} }
function updateChatConversation(from, displayName, message, myjid, stamp) { function updateChatConversation(from, displayName, message, stamp) {
return Chat.updateChatConversation(from, displayName, message, myjid, stamp); return Chat.updateChatConversation(from, displayName, message, stamp);
}
function onMucJoined(jid, info) {
Toolbar.updateRoomUrl(window.location.href);
var meHTML = APP.translation.generateTranslationHTML("me");
$("#localNick").html(Strophe.getResourceFromJid(jid) + " (" + meHTML + ")");
var settings = Settings.getSettings();
// Make sure we configure our avatar id, before creating avatar for us
Avatar.setUserAvatar(jid, settings.email || settings.uid);
// Add myself to the contact list.
ContactList.addContact(jid);
// Once we've joined the muc show the toolbar
ToolbarToggler.showToolbar();
var displayName =
config.displayJids ? Strophe.getResourceFromJid(jid) : info.displayName;
if (displayName)
onDisplayNameChanged('localVideoContainer', displayName);
VideoLayout.mucJoined();
Toolbar.checkAutoEnableDesktopSharing();
} }
function initEtherpad(name) { function initEtherpad(name) {
Etherpad.init(name); Etherpad.init(name);
} }
function onMucMemberLeft(jid) {
console.log('left.muc', jid);
var displayName = $('#participant_' + Strophe.getResourceFromJid(jid) +
'>.displayname').html();
messageHandler.notify(displayName,'notify.somebody',
'disconnected',
'notify.disconnected');
if (!config.startAudioMuted ||
config.startAudioMuted > APP.members.size()) {
UIUtil.playSoundNotification('userLeft');
}
ContactList.removeContact(jid);
VideoLayout.participantLeft(jid);
}
function onLocalRoleChanged(jid, info, pres, isModerator) { function onLocalRoleChanged(jid, info, pres, isModerator) {
console.info("My role changed, new role: " + info.role); console.info("My role changed, new role: " + info.role);
onModeratorStatusChanged(isModerator); onModeratorStatusChanged(isModerator);
@ -575,7 +341,7 @@ function onModeratorStatusChanged(isModerator) {
//Object.keys(connection.emuc.members).length >= 3); //Object.keys(connection.emuc.members).length >= 3);
} }
function onPasswordRequired(callback) { UI.notifyPasswordRequired = function (callback) {
// password is required // password is required
Toolbar.lockLockButton(); Toolbar.lockLockButton();
var message = '<h2 data-i18n="dialog.passwordRequired">'; var message = '<h2 data-i18n="dialog.passwordRequired">';
@ -603,7 +369,7 @@ function onPasswordRequired(callback) {
}, },
':input:first' ':input:first'
); );
} };
/** /**
* The dialpad button is shown iff there is at least one member that supports * The dialpad button is shown iff there is at least one member that supports
@ -614,22 +380,39 @@ function onDtmfSupportChanged(dtmfSupport) {
//Toolbar.showDialPadButton(dtmfSupport); //Toolbar.showDialPadButton(dtmfSupport);
} }
function onMucMemberJoined(jid, id, displayName) { UI.addUser = function (jid, id, displayName) {
messageHandler.notify(displayName,'notify.somebody', messageHandler.notify(
'connected', displayName,'notify.somebody', 'connected', 'notify.connected'
'notify.connected'); );
if (!config.startAudioMuted || if (!config.startAudioMuted ||
config.startAudioMuted > APP.members.size()) config.startAudioMuted > APP.conference.membersCount)
UIUtil.playSoundNotification('userJoined'); UIUtil.playSoundNotification('userJoined');
// Configure avatar // Configure avatar
Avatar.setUserAvatar(jid, id); UI.setUserAvatar(jid, id);
// Add Peer's container // Add Peer's container
VideoLayout.ensurePeerContainerExists(jid); VideoLayout.ensurePeerContainerExists(jid);
};
UI.removeUser = function (jid) {
console.log('left.muc', jid);
var displayName = $('#participant_' + Strophe.getResourceFromJid(jid) +
'>.displayname').html();
messageHandler.notify(displayName,'notify.somebody',
'disconnected',
'notify.disconnected');
if (!config.startAudioMuted ||
config.startAudioMuted > APP.conference.membersCount) {
UIUtil.playSoundNotification('userLeft');
} }
ContactList.removeContact(jid);
VideoLayout.participantLeft(jid);
};
function onMucPresenceStatus(jid, info) { function onMucPresenceStatus(jid, info) {
VideoLayout.setPresenceStatus(Strophe.getResourceFromJid(jid), info.status); VideoLayout.setPresenceStatus(Strophe.getResourceFromJid(jid), info.status);
} }
@ -657,19 +440,13 @@ function onMucRoleChanged(role, displayName) {
} }
} }
function onAuthenticationRequired(intervalCallback) { UI.notifyAuthRequired = function (intervalCallback) {
Authentication.openAuthenticationDialog( Authentication.openAuthenticationDialog(
roomName, intervalCallback, function () { roomName, intervalCallback, function () {
Toolbar.authenticateClicked(); Toolbar.authenticateClicked();
});
}
function onLastNChanged(oldValue, newValue) {
if (config.muteLocalVideoIfNotInLastN) {
setVideoMute(!newValue, { 'byUser': false });
}
} }
);
};
UI.toggleSmileys = function () { UI.toggleSmileys = function () {
@ -696,10 +473,6 @@ UI.inputDisplayNameHandler = function (value) {
VideoLayout.inputDisplayNameHandler(value); VideoLayout.inputDisplayNameHandler(value);
}; };
UI.getLargeVideoResource = function () {
return VideoLayout.getLargeVideoResource();
};
/** /**
* Return the type of the remote video. * Return the type of the remote video.
* @param jid the jid for the remote video * @param jid the jid for the remote video
@ -779,86 +552,29 @@ UI.showLoginPopup = function(callback) {
); );
}; };
UI.checkForNicknameAndJoin = function () { UI.closeAuthenticationDialog = function () {
Authentication.closeAuthenticationDialog(); Authentication.closeAuthenticationDialog();
Authentication.stopInterval(); Authentication.stopInterval();
var nick = null;
if (config.useNicks) {
nick = window.prompt('Your nickname (optional)');
}
APP.xmpp.joinRoom(roomName, config.useNicks, nick);
}; };
UI.askForNickname = function () {
function dump(elem, filename) { return window.prompt('Your nickname (optional)');
elem = elem.parentNode; };
elem.download = filename || 'meetlog.json';
elem.href = 'data:application/json;charset=utf-8,\n';
var data = APP.xmpp.getJingleLog();
var metadata = {};
metadata.time = new Date();
metadata.url = window.location.href;
metadata.ua = navigator.userAgent;
var log = APP.xmpp.getXmppLog();
if (log) {
metadata.xmpp = log;
}
data.metadata = metadata;
elem.href += encodeURIComponent(JSON.stringify(data, null, ' '));
return false;
}
UI.getRoomName = function () { UI.getRoomName = function () {
return roomName; return roomName;
}; };
UI.setInitialMuteFromFocus = function (muteAudio, muteVideo) {
if (muteAudio || muteVideo)
notifyForInitialMute();
if (muteAudio)
UI.setAudioMuted(true);
if (muteVideo)
UI.setVideoMute(true);
};
/**
* Mutes/unmutes the local video.
*/
UI.toggleVideo = function () {
setVideoMute(!APP.RTC.localVideo.isMuted());
};
/**
* Mutes / unmutes audio for the local participant.
*/
UI.toggleAudio = function() {
UI.setAudioMuted(!APP.RTC.localAudio.isMuted());
};
/** /**
* Sets muted audio state for the local participant. * Sets muted audio state for the local participant.
*/ */
UI.setAudioMuted = function (mute, earlyMute) { UI.setAudioMuted = function (mute) {
var audioMute = null;
if (earlyMute)
audioMute = function (mute, cb) {
return APP.xmpp.sendAudioInfoPresence(mute, cb);
};
else
audioMute = function (mute, cb) {
return APP.xmpp.setAudioMute(mute, cb);
};
if (!audioMute(mute, function () {
VideoLayout.showLocalAudioIndicator(mute); VideoLayout.showLocalAudioIndicator(mute);
UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled");
};
UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled"); UI.setVideoMuted = function (muted) {
})) { $('#toolbar_button_camera').toggleClass("icon-camera-disabled", muted);
// We still click the button.
UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled");
return;
}
}; };
UI.addListener = function (type, listener) { UI.addListener = function (type, listener) {
@ -882,27 +598,95 @@ UI.dockToolbar = function (isDock) {
return ToolbarToggler.dockToolbar(isDock); return ToolbarToggler.dockToolbar(isDock);
}; };
UI.setVideoMuteButtonsState = function (mute) { UI.setUserAvatar = function (id, email) {
var video = $('#toolbar_button_camera'); // update avatar
var communicativeClass = "icon-camera"; Avatar.setUserAvatar(id, email);
var muteClass = "icon-camera icon-camera-disabled";
if (mute) { var thumbUrl = Avatar.getThumbUrl(id);
video.removeClass(communicativeClass); var contactListUrl = Avatar.getContactListUrl(id);
video.addClass(muteClass);
} else { VideoLayout.changeUserAvatar(id, thumbUrl);
video.removeClass(muteClass); ContactList.changeUserAvatar(id, contactListUrl);
video.addClass(communicativeClass); if (APP.conference.isLocalId(id)) {
SettingsMenu.changeAvatar(thumbUrl);
} }
}; };
UI.userAvatarChanged = function (resourceJid, thumbUrl, contactListUrl) { UI.notifyConnectionFailed = function (stropheErrorMsg) {
VideoLayout.userAvatarChanged(resourceJid, thumbUrl); var title = APP.translation.generateTranslationHTML(
ContactList.userAvatarChanged(resourceJid, contactListUrl); "dialog.error");
if(resourceJid === APP.xmpp.myResource())
SettingsMenu.changeAvatar(thumbUrl); var message;
if (stropheErrorMsg) {
message = APP.translation.generateTranslationHTML(
"dialog.connectErrorWithMsg", {msg: stropheErrorMsg});
} else {
message = APP.translation.generateTranslationHTML(
"dialog.connectError");
}
messageHandler.openDialog(
title, message, true, {}, function (e, v, m, f) { return false; }
);
}; };
UI.setVideoMute = setVideoMute; UI.notifyFirefoxExtensionRequired = function (url) {
messageHandler.openMessageDialog(
"dialog.extensionRequired",
null,
null,
APP.translation.generateTranslationHTML(
"dialog.firefoxExtensionPrompt", {url: url}
)
);
};
UI.notifyInitiallyMuted = function () {
messageHandler.notify(
null, "notify.mutedTitle", "connected", "notify.muted", null, {timeOut: 120000}
);
};
UI.markDominantSpiker = function (id) {
VideoLayout.onDominantSpeakerChanged(id);
};
UI.handleLastNEndpoints = function (ids) {
VideoLayout.onLastNEndpointsChanged(ids, []);
};
UI.setAudioLevel = function (targetJid, lvl) {
AudioLevels.updateAudioLevel(
targetJid, lvl, VideoLayout.getLargeVideoResource()
);
};
UI.updateDesktopSharingButtons = function () {
Toolbar.changeDesktopSharingButtonState();
};
UI.hideStats = function () {
VideoLayout.hideStats();
};
UI.updateLocalStats = function (percent, stats) {
VideoLayout.updateLocalConnectionStats(percent, stats);
};
UI.updateRemoteStats = function (jid, percent, stats) {
VideoLayout.updateConnectionStats(jid, percent, stats);
};
UI.showAuthenticateButton = function (show) {
Toolbar.showAuthenticateButton(show);
};
UI.markVideoInterrupted = function (interrupted) {
if (interrupted) {
VideoLayout.onVideoInterrupted();
} else {
VideoLayout.onVideoRestored();
}
};
module.exports = UI; module.exports = UI;

View File

@ -109,10 +109,10 @@ var AudioLevels = (function(my) {
drawContext.drawImage(canvasCache, 0, 0); drawContext.drawImage(canvasCache, 0, 0);
if(resourceJid === AudioLevels.LOCAL_LEVEL) { if(resourceJid === AudioLevels.LOCAL_LEVEL) {
if(!APP.xmpp.myJid()) { resourceJid = APP.conference.localId;
if (!resourceJid) {
return; return;
} }
resourceJid = APP.xmpp.myResource();
} }
if(resourceJid === largeVideoResourceJid) { if(resourceJid === largeVideoResourceJid) {
@ -223,11 +223,11 @@ var AudioLevels = (function(my) {
*/ */
function getVideoSpanId(resourceJid) { function getVideoSpanId(resourceJid) {
var videoSpanId = null; var videoSpanId = null;
if (resourceJid === AudioLevels.LOCAL_LEVEL || if (resourceJid === AudioLevels.LOCAL_LEVEL || APP.conference.isLocalId(resourceJid)) {
(APP.xmpp.myResource() && resourceJid === APP.xmpp.myResource()))
videoSpanId = 'localVideoContainer'; videoSpanId = 'localVideoContainer';
else } else {
videoSpanId = 'participant_' + resourceJid; videoSpanId = 'participant_' + resourceJid;
}
return videoSpanId; return videoSpanId;
} }

View File

@ -1,6 +1,4 @@
/* global Strophe, APP, MD5 */ /* global MD5 */
var Settings = require("../../settings/Settings");
var users = {}; var users = {};
var Avatar = { var Avatar = {
@ -8,57 +6,55 @@ var Avatar = {
/** /**
* Sets the user's avatar in the settings menu(if local user), contact list * Sets the user's avatar in the settings menu(if local user), contact list
* and thumbnail * and thumbnail
* @param jid jid of the user * @param id id of the user
* @param id email or userID to be used as a hash * @param email email or nickname to be used as a hash
*/ */
setUserAvatar: function (jid, id) { setUserAvatar: function (id, email) {
if (id) { if (email) {
if (users[jid] === id) { if (users[id] === email) {
return; return;
} }
users[jid] = id; users[id] = email;
} }
var thumbUrl = this.getThumbUrl(jid); var thumbUrl = this.getThumbUrl(id);
var contactListUrl = this.getContactListUrl(jid); var contactListUrl = this.getContactListUrl(id);
var resourceJid = Strophe.getResourceFromJid(jid);
APP.UI.userAvatarChanged(resourceJid, thumbUrl, contactListUrl);
}, },
/** /**
* Returns image URL for the avatar to be displayed on large video area * Returns image URL for the avatar to be displayed on large video area
* where current active speaker is presented. * where current active speaker is presented.
* @param jid full MUC jid of the user for whom we want to obtain avatar URL * @param id id of the user for whom we want to obtain avatar URL
*/ */
getActiveSpeakerUrl: function (jid) { getActiveSpeakerUrl: function (id) {
return this.getGravatarUrl(jid, 100); return this.getGravatarUrl(id, 100);
}, },
/** /**
* Returns image URL for the avatar to be displayed on small video thumbnail * Returns image URL for the avatar to be displayed on small video thumbnail
* @param jid full MUC jid of the user for whom we want to obtain avatar URL * @param id id of the user for whom we want to obtain avatar URL
*/ */
getThumbUrl: function (jid) { getThumbUrl: function (id) {
return this.getGravatarUrl(jid, 100); return this.getGravatarUrl(id, 100);
}, },
/** /**
* Returns the URL for the avatar to be displayed as contactlist item * Returns the URL for the avatar to be displayed as contactlist item
* @param jid full MUC jid of the user for whom we want to obtain avatar URL * @param id id of the user for whom we want to obtain avatar URL
*/ */
getContactListUrl: function (jid) { getContactListUrl: function (id) {
return this.getGravatarUrl(jid, 30); return this.getGravatarUrl(id, 30);
}, },
getGravatarUrl: function (jid, size) { getGravatarUrl: function (id, size) {
if (!jid) { if (!id) {
console.error("Get gravatar - jid is undefined"); console.error("Get gravatar - id is undefined");
return null; return null;
} }
var id = users[jid]; var email = users[id];
if (!id) { if (!email) {
console.warn( console.warn(
"No avatar stored yet for " + jid + " - using JID as ID"); "No avatar stored yet for " + id + " - using user id as ID"
id = jid; );
email = id;
} }
return 'https://www.gravatar.com/avatar/' + return 'https://www.gravatar.com/avatar/' +
MD5.hexdigest(id.trim().toLowerCase()) + MD5.hexdigest(email.trim().toLowerCase()) +
"?d=wavatar&size=" + (size || "30"); "?d=wavatar&size=" + (size || "30");
} }

View File

@ -1,9 +1,8 @@
/* global APP, $, Util, nickname:true */ /* global APP, $ */
var Replacement = require("./Replacement"); var Replacement = require("./Replacement");
var CommandsProcessor = require("./Commands"); var CommandsProcessor = require("./Commands");
var ToolbarToggler = require("../../toolbars/ToolbarToggler"); var ToolbarToggler = require("../../toolbars/ToolbarToggler");
var smileys = require("./smileys.json").smileys; var smileys = require("./smileys.json").smileys;
var NicknameHandler = require("../../util/NicknameHandler");
var UIUtil = require("../../util/UIUtil"); var UIUtil = require("../../util/UIUtil");
var UIEvents = require("../../../../service/UI/UIEvents"); var UIEvents = require("../../../../service/UI/UIEvents");
@ -169,22 +168,18 @@ var Chat = (function (my) {
/** /**
* Initializes chat related interface. * Initializes chat related interface.
*/ */
my.init = function () { my.init = function (eventEmitter) {
if(NicknameHandler.getNickname()) if (APP.settings.getDisplayName()) {
Chat.setChatConversationMode(true); Chat.setChatConversationMode(true);
NicknameHandler.addListener(UIEvents.NICKNAME_CHANGED, }
function (nickname) {
Chat.setChatConversationMode(true);
});
$('#nickinput').keydown(function (event) { $('#nickinput').keydown(function (event) {
if (event.keyCode === 13) { if (event.keyCode === 13) {
event.preventDefault(); event.preventDefault();
var val = UIUtil.escapeHtml(this.value); var val = UIUtil.escapeHtml(this.value);
this.value = ''; this.value = '';
if (!NicknameHandler.getNickname()) { if (APP.settings.getDisplayName()) {
NicknameHandler.setNickname(val); eventEmitter.emit(UIEvents.NICKNAME_CHANGED, val);
return; return;
} }
} }
@ -203,8 +198,7 @@ var Chat = (function (my) {
} }
else { else {
var message = UIUtil.escapeHtml(value); var message = UIUtil.escapeHtml(value);
APP.xmpp.sendChatMessage(message, eventEmitter.emit(UIEvents.MESSAGE_CREATED, message);
NicknameHandler.getNickname());
} }
} }
}); });
@ -228,7 +222,7 @@ var Chat = (function (my) {
* Appends the given message to the chat conversation. * Appends the given message to the chat conversation.
*/ */
my.updateChatConversation = my.updateChatConversation =
function (from, displayName, message, myjid, stamp) { function (from, displayName, message, stamp) {
var divClassName = ''; var divClassName = '';
if (APP.xmpp.myJid() === from) { if (APP.xmpp.myJid() === from) {

View File

@ -169,21 +169,20 @@ var ContactList = {
} }
}, },
onDisplayNameChange: function (peerJid, displayName) { onDisplayNameChange: function (id, displayName) {
if (peerJid === 'localVideoContainer') if (id === 'localVideoContainer') {
peerJid = APP.xmpp.myJid(); id = APP.conference.localId;
}
var contactName = $('#contacts #' + id + '>p');
var resourceJid = Strophe.getResourceFromJid(peerJid); if (contactName && displayName && displayName.length > 0) {
var contactName = $('#contacts #' + resourceJid + '>p');
if (contactName && displayName && displayName.length > 0)
contactName.html(displayName); contactName.html(displayName);
}
}, },
userAvatarChanged: function (resourceJid, contactListUrl) { changeUserAvatar: function (id, contactListUrl) {
// set the avatar in the contact list // set the avatar in the contact list
var contact = $('#' + resourceJid + '>img'); var contact = $('#' + id + '>img');
if (contact && contact.length > 0) { if (contact && contact.length > 0) {
contact.get(0).src = contactListUrl; contact.get(0).src = contactListUrl;
} }

View File

@ -1,8 +1,8 @@
/* global APP, $ */ /* global APP, $ */
var Avatar = require("../../avatar/Avatar");
var Settings = require("./../../../settings/Settings"); var Settings = require("./../../../settings/Settings");
var UIUtil = require("../../util/UIUtil"); var UIUtil = require("../../util/UIUtil");
var languages = require("../../../../service/translation/languages"); var languages = require("../../../../service/translation/languages");
var UIEvents = require("../../../../service/UI/UIEvents");
function generateLanguagesSelectBox() { function generateLanguagesSelectBox() {
var currentLang = APP.translation.getCurrentLanguage(); var currentLang = APP.translation.getCurrentLanguage();
@ -24,7 +24,9 @@ function generateLanguagesSelectBox() {
var SettingsMenu = { var SettingsMenu = {
init: function () { init: function (emitter) {
this.emitter = emitter;
var startMutedSelector = $("#startMutedOptions"); var startMutedSelector = $("#startMutedOptions");
startMutedSelector.before(generateLanguagesSelectBox()); startMutedSelector.before(generateLanguagesSelectBox());
APP.translation.translateElement($("#languages_selectbox")); APP.translation.translateElement($("#languages_selectbox"));
@ -34,10 +36,9 @@ var SettingsMenu = {
} }
}); });
if (APP.xmpp.isModerator()) { if (APP.conference.isModerator) {
startMutedSelector.css("display", "block"); startMutedSelector.css("display", "block");
} } else {
else {
startMutedSelector.css("display", "none"); startMutedSelector.css("display", "none");
} }
@ -47,7 +48,7 @@ var SettingsMenu = {
}, },
onRoleChanged: function () { onRoleChanged: function () {
if(APP.xmpp.isModerator()) { if(APP.conference.isModerator) {
$("#startMutedOptions").css("display", "block"); $("#startMutedOptions").css("display", "block");
} }
else { else {
@ -61,43 +62,35 @@ var SettingsMenu = {
}, },
update: function() { update: function() {
// FIXME check if this values really changed:
// compare them with Settings etc.
var newDisplayName = var newDisplayName =
UIUtil.escapeHtml($('#setDisplayName').get(0).value); UIUtil.escapeHtml($('#setDisplayName').get(0).value);
var newEmail = UIUtil.escapeHtml($('#setEmail').get(0).value);
if (newDisplayName) { if (newDisplayName) {
var displayName = Settings.setDisplayName(newDisplayName); this.emitter.emit(UIEvents.NICKNAME_CHANGED, newDisplayName);
APP.xmpp.addToPresence("displayName", displayName, true);
} }
var language = $("#languages_selectbox").val(); var language = $("#languages_selectbox").val();
APP.translation.setLanguage(language); this.emitter.emit(UIEvents.LANG_CHANGED, language);
Settings.setLanguage(language);
APP.xmpp.addToPresence("email", newEmail); var newEmail = UIUtil.escapeHtml($('#setEmail').get(0).value);
var email = Settings.setEmail(newEmail); this.emitter.emit(UIEvents.EMAIL_CHANGED, newEmail);
var startAudioMuted = ($("#startAudioMuted").is(":checked")); var startAudioMuted = ($("#startAudioMuted").is(":checked"));
var startVideoMuted = ($("#startVideoMuted").is(":checked")); var startVideoMuted = ($("#startVideoMuted").is(":checked"));
APP.xmpp.addToPresence("startMuted", this.emitter.emit(
[startAudioMuted, startVideoMuted]); UIEvents.START_MUTED_CHANGED, startAudioMuted, startVideoMuted
);
Avatar.setUserAvatar(APP.xmpp.myJid(), email);
}, },
isVisible: function() { isVisible: function() {
return $('#settingsmenu').is(':visible'); return $('#settingsmenu').is(':visible');
}, },
setDisplayName: function(newDisplayName) { onDisplayNameChange: function(id, newDisplayName) {
var displayName = Settings.setDisplayName(newDisplayName); if(id === 'localVideoContainer' || APP.conference.isLocalId(id)) {
$('#setDisplayName').get(0).value = displayName; $('#setDisplayName').get(0).value = newDisplayName;
},
onDisplayNameChange: function(peerJid, newDisplayName) {
if(peerJid === 'localVideoContainer' ||
peerJid === APP.xmpp.myJid()) {
this.setDisplayName(newDisplayName);
} }
}, },
changeAvatar: function (thumbUrl) { changeAvatar: function (thumbUrl) {

View File

@ -1,5 +1,4 @@
/* global APP, $, buttonClick, config, lockRoom, interfaceConfig, setSharedKey, /* global APP, $, config, interfaceConfig */
Util */
/* jshint -W101 */ /* jshint -W101 */
var messageHandler = require("../util/MessageHandler"); var messageHandler = require("../util/MessageHandler");
var BottomToolbar = require("./BottomToolbar"); var BottomToolbar = require("./BottomToolbar");
@ -12,28 +11,31 @@ var AuthenticationEvents
= require("../../../service/authentication/AuthenticationEvents"); = require("../../../service/authentication/AuthenticationEvents");
var AnalyticsAdapter = require("../../statistics/AnalyticsAdapter"); var AnalyticsAdapter = require("../../statistics/AnalyticsAdapter");
var Feedback = require("../Feedback"); var Feedback = require("../Feedback");
var UIEvents = require("../../../service/UI/UIEvents");
var roomUrl = null; var roomUrl = null;
var sharedKey = ''; var sharedKey = '';
var UI = null;
var recordingToaster = null; var recordingToaster = null;
var emitter = null;
var buttonHandlers = { var buttonHandlers = {
"toolbar_button_mute": function () { "toolbar_button_mute": function () {
if (APP.RTC.localAudio.isMuted()) { if (APP.RTC.localAudio.isMuted()) {
AnalyticsAdapter.sendEvent('toolbar.audio.unmuted'); AnalyticsAdapter.sendEvent('toolbar.audio.unmuted');
emitter.emit(UIEvents.AUDIO_MUTED, false);
} else { } else {
AnalyticsAdapter.sendEvent('toolbar.audio.muted'); AnalyticsAdapter.sendEvent('toolbar.audio.muted');
emitter.emit(UIEvents.AUDIO_MUTED, true);
} }
return APP.UI.toggleAudio();
}, },
"toolbar_button_camera": function () { "toolbar_button_camera": function () {
if (APP.RTC.localVideo.isMuted()) { if (APP.RTC.localVideo.isMuted()) {
AnalyticsAdapter.sendEvent('toolbar.video.enabled'); AnalyticsAdapter.sendEvent('toolbar.video.enabled');
emitter.emit(UIEvents.VIDEO_MUTED, false);
} else { } else {
AnalyticsAdapter.sendEvent('toolbar.video.disabled'); AnalyticsAdapter.sendEvent('toolbar.video.disabled');
emitter.emit(UIEvents.VIDEO_MUTED, true);
} }
return APP.UI.toggleVideo();
}, },
/*"toolbar_button_authentication": function () { /*"toolbar_button_authentication": function () {
return Toolbar.authenticateClicked(); return Toolbar.authenticateClicked();
@ -299,7 +301,7 @@ function callSipButtonClicked() {
var numberInput = f.sipNumber; var numberInput = f.sipNumber;
if (numberInput) { if (numberInput) {
APP.xmpp.dial( APP.xmpp.dial(
numberInput, 'fromnumber', UI.getRoomName(), sharedKey); numberInput, 'fromnumber', APP.UI.getRoomName(), sharedKey);
} }
} }
}, },
@ -309,12 +311,12 @@ function callSipButtonClicked() {
var Toolbar = (function (my) { var Toolbar = (function (my) {
my.init = function (ui) { my.init = function (eventEmitter) {
emitter = eventEmitter;
UIUtil.hideDisabledButtons(defaultToolbarButtons); UIUtil.hideDisabledButtons(defaultToolbarButtons);
for(var k in buttonHandlers) for(var k in buttonHandlers)
$("#" + k).click(buttonHandlers[k]); $("#" + k).click(buttonHandlers[k]);
UI = ui;
// Update login info // Update login info
APP.xmpp.addListener( APP.xmpp.addListener(
AuthenticationEvents.IDENTITY_UPDATED, AuthenticationEvents.IDENTITY_UPDATED,
@ -353,12 +355,12 @@ var Toolbar = (function (my) {
} }
// Get authentication URL // Get authentication URL
if (!APP.xmpp.isMUCJoined()) { if (!APP.xmpp.isMUCJoined()) {
APP.xmpp.getLoginUrl(UI.getRoomName(), function (url) { APP.xmpp.getLoginUrl(APP.UI.getRoomName(), function (url) {
// If conference has not been started yet - redirect to login page // If conference has not been started yet - redirect to login page
window.location.href = url; window.location.href = url;
}); });
} else { } else {
APP.xmpp.getPopupLoginUrl(UI.getRoomName(), function (url) { APP.xmpp.getPopupLoginUrl(APP.UI.getRoomName(), function (url) {
// Otherwise - open popup with authentication URL // Otherwise - open popup with authentication URL
var authenticationWindow = Authentication.createAuthenticationWindow( var authenticationWindow = Authentication.createAuthenticationWindow(
function () { function () {

View File

@ -1,5 +1,4 @@
/* global APP, config, $, interfaceConfig, Moderator, /* global APP, config, $, interfaceConfig */
DesktopStreaming.showDesktopSharingButton */
var toolbarTimeoutObject, var toolbarTimeoutObject,
toolbarTimeout = interfaceConfig.INITIAL_TOOLBAR_TIMEOUT, toolbarTimeout = interfaceConfig.INITIAL_TOOLBAR_TIMEOUT,
@ -75,13 +74,6 @@ var ToolbarToggler = {
toolbarTimeout = interfaceConfig.TOOLBAR_TIMEOUT; toolbarTimeout = interfaceConfig.TOOLBAR_TIMEOUT;
} }
if (APP.xmpp.isModerator())
{
// TODO: Enable settings functionality.
// Need to uncomment the settings button in index.html.
// $('#settingsButton').css({visibility:"visible"});
}
// Show/hide desktop sharing button // Show/hide desktop sharing button
showDesktopSharingButton(); showDesktopSharingButton();
}, },

View File

@ -1,30 +0,0 @@
var UIEvents = require("../../../service/UI/UIEvents");
var nickname = null;
var eventEmitter = null;
var NicknameHandler = {
init: function (emitter) {
eventEmitter = emitter;
var storedDisplayName = window.localStorage.displayname;
if (storedDisplayName) {
nickname = storedDisplayName;
}
},
setNickname: function (newNickname) {
if (!newNickname || nickname === newNickname)
return;
nickname = newNickname;
window.localStorage.displayname = nickname;
eventEmitter.emit(UIEvents.NICKNAME_CHANGED, newNickname);
},
getNickname: function () {
return nickname;
},
addListener: function (type, listener) {
eventEmitter.on(type, listener);
}
};
module.exports = NicknameHandler;

View File

@ -1,12 +1,12 @@
/* global $, interfaceConfig, APP */ /* global $, interfaceConfig, APP */
var SmallVideo = require("./SmallVideo"); var SmallVideo = require("./SmallVideo");
var ConnectionIndicator = require("./ConnectionIndicator"); var ConnectionIndicator = require("./ConnectionIndicator");
var NicknameHandler = require("../util/NicknameHandler");
var UIUtil = require("../util/UIUtil"); var UIUtil = require("../util/UIUtil");
var UIEvents = require("../../../service/UI/UIEvents");
var LargeVideo = require("./LargeVideo"); var LargeVideo = require("./LargeVideo");
var RTCBrowserType = require("../../RTC/RTCBrowserType"); var RTCBrowserType = require("../../RTC/RTCBrowserType");
function LocalVideo(VideoLayout) { function LocalVideo(VideoLayout, emitter) {
this.videoSpanId = "localVideoContainer"; this.videoSpanId = "localVideoContainer";
this.container = $("#localVideoContainer").get(0); this.container = $("#localVideoContainer").get(0);
this.bindHoverHandler(); this.bindHoverHandler();
@ -14,6 +14,7 @@ function LocalVideo(VideoLayout) {
this.flipX = true; this.flipX = true;
this.isLocal = true; this.isLocal = true;
this.peerJid = null; this.peerJid = null;
this.emitter = emitter;
} }
LocalVideo.prototype = Object.create(SmallVideo.prototype); LocalVideo.prototype = Object.create(SmallVideo.prototype);
@ -117,11 +118,13 @@ LocalVideo.prototype.setDisplayName = function(displayName, key) {
editDisplayName.one("focusout", function (e) { editDisplayName.one("focusout", function (e) {
self.VideoLayout.inputDisplayNameHandler(this.value); self.VideoLayout.inputDisplayNameHandler(this.value);
$('#editDisplayName').hide();
}); });
editDisplayName.on('keydown', function (e) { editDisplayName.on('keydown', function (e) {
if (e.keyCode === 13) { if (e.keyCode === 13) {
e.preventDefault(); e.preventDefault();
$('#editDisplayName').hide();
self.VideoLayout.inputDisplayNameHandler(this.value); self.VideoLayout.inputDisplayNameHandler(this.value);
} }
}); });
@ -130,25 +133,7 @@ LocalVideo.prototype.setDisplayName = function(displayName, key) {
}; };
LocalVideo.prototype.inputDisplayNameHandler = function (name) { LocalVideo.prototype.inputDisplayNameHandler = function (name) {
name = UIUtil.escapeHtml(name); this.emitter.emit(UIEvents.NICKNAME_CHANGED, UIUtil.escapeHtml(name));
NicknameHandler.setNickname(name);
var localDisplayName = $('#localDisplayName');
if (!localDisplayName.is(":visible")) {
if (NicknameHandler.getNickname()) {
var meHTML = APP.translation.generateTranslationHTML("me");
localDisplayName.html(NicknameHandler.getNickname() + " (" +
meHTML + ")");
} else {
var defaultHTML = APP.translation.generateTranslationHTML(
interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME);
localDisplayName .html(defaultHTML);
}
localDisplayName.show();
}
$('#editDisplayName').hide();
}; };
LocalVideo.prototype.createConnectionIndicator = function() { LocalVideo.prototype.createConnectionIndicator = function() {

View File

@ -36,7 +36,7 @@ var focusedVideoResourceJid = null;
var VideoLayout = (function (my) { var VideoLayout = (function (my) {
my.init = function (emitter) { my.init = function (emitter) {
eventEmitter = emitter; eventEmitter = emitter;
localVideoThumbnail = new LocalVideo(VideoLayout); localVideoThumbnail = new LocalVideo(VideoLayout, emitter);
if (interfaceConfig.filmStripOnly) { if (interfaceConfig.filmStripOnly) {
LargeVideo.disable(); LargeVideo.disable();
} else { } else {
@ -56,8 +56,6 @@ var VideoLayout = (function (my) {
}; };
my.changeLocalAudio = function(stream, isMuted) { my.changeLocalAudio = function(stream, isMuted) {
if (isMuted)
APP.UI.setAudioMuted(true, true);
APP.RTC.attachMediaStream($('#localAudio'), stream.getOriginalStream()); APP.RTC.attachMediaStream($('#localAudio'), stream.getOriginalStream());
var localAudio = document.getElementById('localAudio'); var localAudio = document.getElementById('localAudio');
// Writing volume not allowed in IE // Writing volume not allowed in IE
@ -589,16 +587,13 @@ var VideoLayout = (function (my) {
/** /**
* Display name changed. * Display name changed.
*/ */
my.onDisplayNameChanged = my.onDisplayNameChanged = function (id, displayName, status) {
function (jid, displayName, status) { if (id === 'localVideoContainer' ||
if (jid === 'localVideoContainer' || APP.conference.isLocalId(id)) {
jid === APP.xmpp.myJid()) {
localVideoThumbnail.setDisplayName(displayName); localVideoThumbnail.setDisplayName(displayName);
} else { } else {
VideoLayout.ensurePeerContainerExists(jid); VideoLayout.ensurePeerContainerExists(id);
remoteVideos[Strophe.getResourceFromJid(jid)].setDisplayName( remoteVideos[id].setDisplayName(displayName, status);
displayName,
status);
} }
}; };
@ -652,9 +647,7 @@ var VideoLayout = (function (my) {
* @param endpointsEnteringLastN the list currently entering last N * @param endpointsEnteringLastN the list currently entering last N
* endpoints * endpoints
*/ */
my.onLastNEndpointsChanged = function (lastNEndpoints, my.onLastNEndpointsChanged = function (lastNEndpoints, endpointsEnteringLastN) {
endpointsEnteringLastN,
stream) {
if (lastNCount !== lastNEndpoints.length) if (lastNCount !== lastNEndpoints.length)
lastNCount = lastNEndpoints.length; lastNCount = lastNEndpoints.length;
@ -847,7 +840,7 @@ var VideoLayout = (function (my) {
/** /**
* Hides all the indicators * Hides all the indicators
*/ */
my.onStatsStop = function () { my.hideStats = function () {
for(var video in remoteVideos) { for(var video in remoteVideos) {
remoteVideos[video].hideIndicator(); remoteVideos[video].hideIndicator();
} }
@ -1005,14 +998,16 @@ var VideoLayout = (function (my) {
} }
}; };
my.userAvatarChanged = function(resourceJid, thumbUrl) { my.changeUserAvatar = function(id, thumbUrl) {
var smallVideo = VideoLayout.getSmallVideo(resourceJid); var smallVideo = VideoLayout.getSmallVideo(id);
if(smallVideo) if (smallVideo) {
smallVideo.avatarChanged(thumbUrl); smallVideo.avatarChanged(thumbUrl);
else } else {
console.warn( console.warn(
"Missed avatar update - no small video yet for " + resourceJid); "Missed avatar update - no small video yet for " + id
LargeVideo.updateAvatar(resourceJid, thumbUrl); );
}
LargeVideo.updateAvatar(id, thumbUrl);
}; };
my.createEtherpadIframe = function(src, onloadHandler) my.createEtherpadIframe = function(src, onloadHandler)

View File

@ -3,7 +3,6 @@
var EventEmitter = require("events"); var EventEmitter = require("events");
var eventEmitter = new EventEmitter(); var eventEmitter = new EventEmitter();
var CQEvents = require("../../service/connectionquality/CQEvents"); var CQEvents = require("../../service/connectionquality/CQEvents");
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
var StatisticsEvents = require("../../service/statistics/Events"); var StatisticsEvents = require("../../service/statistics/Events");
/** /**
@ -18,43 +17,6 @@ var stats = {};
*/ */
var remoteStats = {}; var remoteStats = {};
/**
* Interval for sending statistics to other participants
* @type {null}
*/
var sendIntervalId = null;
/**
* Start statistics sending.
*/
function startSendingStats() {
sendStats();
sendIntervalId = setInterval(sendStats, 10000);
}
/**
* Sends statistics to other participants
*/
function sendStats() {
APP.xmpp.addToPresence("connectionQuality", convertToMUCStats(stats));
}
/**
* Converts statistics to format for sending through XMPP
* @param stats the statistics
* @returns {{bitrate_donwload: *, bitrate_uplpoad: *, packetLoss_total: *, packetLoss_download: *, packetLoss_upload: *}}
*/
function convertToMUCStats(stats) {
return {
"bitrate_download": stats.bitrate.download,
"bitrate_upload": stats.bitrate.upload,
"packetLoss_total": stats.packetLoss.total,
"packetLoss_download": stats.packetLoss.download,
"packetLoss_upload": stats.packetLoss.upload
};
}
/** /**
* Converts statistics to format used by VideoLayout * Converts statistics to format used by VideoLayout
* @param stats * @param stats
@ -76,11 +38,12 @@ function parseMUCStats(stats) {
var ConnectionQuality = { var ConnectionQuality = {
init: function () { init: function () {
APP.xmpp.addListener(XMPPEvents.REMOTE_STATS, this.updateRemoteStats); APP.statistics.addListener(
APP.statistics.addListener(StatisticsEvents.CONNECTION_STATS, StatisticsEvents.CONNECTION_STATS, this.updateLocalStats
this.updateLocalStats); );
APP.statistics.addListener(StatisticsEvents.STOP, APP.statistics.addListener(
this.stopSendingStats); StatisticsEvents.STOP, this.stopSendingStats
);
}, },
/** /**
@ -90,33 +53,29 @@ var ConnectionQuality = {
updateLocalStats: function (data) { updateLocalStats: function (data) {
stats = data; stats = data;
eventEmitter.emit(CQEvents.LOCALSTATS_UPDATED, 100 - stats.packetLoss.total, stats); eventEmitter.emit(CQEvents.LOCALSTATS_UPDATED, 100 - stats.packetLoss.total, stats);
if (!sendIntervalId) {
startSendingStats();
}
}, },
/** /**
* Updates remote statistics * Updates remote statistics
* @param jid the jid associated with the statistics * @param id the id associated with the statistics
* @param data the statistics * @param data the statistics
*/ */
updateRemoteStats: function (jid, data) { updateRemoteStats: function (id, data) {
if (!data || !data.packetLoss_total) { if (!data || !data.packetLoss_total) {
eventEmitter.emit(CQEvents.REMOTESTATS_UPDATED, jid, null, null); eventEmitter.emit(CQEvents.REMOTESTATS_UPDATED, id, null, null);
return; return;
} }
remoteStats[jid] = parseMUCStats(data); remoteStats[id] = parseMUCStats(data);
eventEmitter.emit(CQEvents.REMOTESTATS_UPDATED, eventEmitter.emit(
jid, 100 - data.packetLoss_total, remoteStats[jid]); CQEvents.REMOTESTATS_UPDATED, id, 100 - data.packetLoss_total, remoteStats[id]
);
}, },
/** /**
* Stops statistics sending. * Stops statistics sending.
*/ */
stopSendingStats: function () { stopSendingStats: function () {
clearInterval(sendIntervalId);
sendIntervalId = null;
//notify UI about stopping statistics gathering //notify UI about stopping statistics gathering
eventEmitter.emit(CQEvents.STOP); eventEmitter.emit(CQEvents.STOP);
}, },
@ -130,8 +89,22 @@ var ConnectionQuality = {
addListener: function (type, listener) { addListener: function (type, listener) {
eventEmitter.on(type, listener); eventEmitter.on(type, listener);
} },
/**
* Converts statistics to format for sending through XMPP
* @param stats the statistics
* @returns {{bitrate_donwload: *, bitrate_uplpoad: *, packetLoss_total: *, packetLoss_download: *, packetLoss_upload: *}}
*/
convertToMUCStats: function (stats) {
return {
"bitrate_download": stats.bitrate.download,
"bitrate_upload": stats.bitrate.upload,
"packetLoss_total": stats.packetLoss.total,
"packetLoss_download": stats.packetLoss.download,
"packetLoss_upload": stats.packetLoss.upload
};
}
}; };
module.exports = ConnectionQuality; module.exports = ConnectionQuality;

View File

@ -21,20 +21,18 @@ function initShortcutHandlers() {
77: { 77: {
character: "M", character: "M",
id: "mutePopover", id: "mutePopover",
function: APP.UI.toggleAudio function: APP.conference.toggleAudioMuted
}, },
84: { 84: {
character: "T", character: "T",
function: function() { function: function() {
if(!APP.RTC.localAudio.isMuted()) { APP.conference.muteAudio(true);
APP.UI.toggleAudio();
}
} }
}, },
86: { 86: {
character: "V", character: "V",
id: "toggleVideoPopover", id: "toggleVideoPopover",
function: APP.UI.toggleVideo function: APP.conference.toggleVideoMuted
} }
}; };
} }
@ -67,9 +65,7 @@ var KeyboardShortcut = {
$(":focus").is("input[type=password]") || $(":focus").is("input[type=password]") ||
$(":focus").is("textarea"))) { $(":focus").is("textarea"))) {
if(e.which === "T".charCodeAt(0)) { if(e.which === "T".charCodeAt(0)) {
if(APP.RTC.localAudio.isMuted()) { APP.conference.muteAudio(true);
APP.UI.toggleAudio();
}
} }
} }
}; };

View File

@ -1,128 +0,0 @@
/* global APP, require, $ */
/**
* This module is meant to (eventually) contain and manage all information
* about members/participants of the conference, so that other modules don't
* have to do it on their own, and so that other modules can access members'
* information from a single place.
*
* Currently this module only manages information about the support of jingle
* DTMF of the members. Other fields, as well as accessor methods are meant to
* be added as needed.
*/
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
var Events = require("../../service/members/Events");
var EventEmitter = require("events");
var eventEmitter = new EventEmitter();
/**
* The actual container.
*/
var members = {};
/**
* There is at least one member that supports DTMF (i.e. is jigasi).
*/
var atLeastOneDtmf = false;
function registerListeners() {
APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_JOINED, onMucMemberJoined);
APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_LEFT, onMucMemberLeft);
}
/**
* Handles a new member joining the MUC.
*/
function onMucMemberJoined(jid, id, displayName) {
var member = {
displayName: displayName
};
APP.xmpp.getConnection().disco.info(
jid, "" /* node */, function(iq) { onDiscoInfoReceived(jid, iq); });
members[jid] = member;
}
/**
* Handles a member leaving the MUC.
*/
function onMucMemberLeft(jid) {
delete members[jid];
updateAtLeastOneDtmf();
}
/**
* Handles the reception of a disco#info packet from a particular JID.
* @param jid the JID sending the packet.
* @param iq the packet.
*/
function onDiscoInfoReceived(jid, iq) {
if (!members[jid])
return;
var supportsDtmf
= $(iq).find('>query>feature[var="urn:xmpp:jingle:dtmf:0"]').length > 0;
updateDtmf(jid, supportsDtmf);
}
/**
* Updates the 'supportsDtmf' field for a member.
* @param jid the jid of the member.
* @param newValue the new value for the 'supportsDtmf' field.
*/
function updateDtmf(jid, newValue) {
var oldValue = members[jid].supportsDtmf;
members[jid].supportsDtmf = newValue;
if (newValue != oldValue) {
updateAtLeastOneDtmf();
}
}
/**
* Checks each member's 'supportsDtmf' field and updates
* 'atLastOneSupportsDtmf'.
*/
function updateAtLeastOneDtmf() {
var newAtLeastOneDtmf = false;
for (var key in members) {
if (typeof members[key].supportsDtmf !== 'undefined'
&& members[key].supportsDtmf) {
newAtLeastOneDtmf= true;
break;
}
}
if (atLeastOneDtmf != newAtLeastOneDtmf) {
atLeastOneDtmf = newAtLeastOneDtmf;
eventEmitter.emit(Events.DTMF_SUPPORT_CHANGED, atLeastOneDtmf);
}
}
/**
* Exported interface.
*/
var Members = {
start: function() {
registerListeners();
},
addListener: function(type, listener) {
eventEmitter.on(type, listener);
},
removeListener: function (type, listener) {
eventEmitter.removeListener(type, listener);
},
size: function () {
return Object.keys(members).length;
},
getMembers: function () {
return members;
}
};
module.exports = Members;

View File

@ -57,6 +57,9 @@ var Settings = {
* @returns {string} the display name we just set * @returns {string} the display name we just set
*/ */
setDisplayName: function (newDisplayName) { setDisplayName: function (newDisplayName) {
if (displayName === newDisplayName) {
return displayName;
}
displayName = newDisplayName; displayName = newDisplayName;
window.localStorage.displayname = displayName; window.localStorage.displayname = displayName;
return displayName; return displayName;
@ -84,6 +87,10 @@ var Settings = {
return email; return email;
}, },
getEmail: function () {
return email;
},
getSettings: function () { getSettings: function () {
return { return {
email: email, email: email,

View File

@ -1,5 +1,4 @@
/* global $, $iq, config, connection, focusMucJid, forceMuted, /* global $, $iq, config, connection, focusMucJid, forceMuted, Strophe */
setAudioMuted, Strophe */
/** /**
* Moderate connection plugin. * Moderate connection plugin.
*/ */

View File

@ -3,6 +3,24 @@ var UIEvents = {
SELECTED_ENDPOINT: "UI.selected_endpoint", SELECTED_ENDPOINT: "UI.selected_endpoint",
PINNED_ENDPOINT: "UI.pinned_endpoint", PINNED_ENDPOINT: "UI.pinned_endpoint",
LARGEVIDEO_INIT: "UI.largevideo_init", LARGEVIDEO_INIT: "UI.largevideo_init",
/**
* Notifies that local user created text message.
*/
MESSAGE_CREATED: "UI.message_created",
/**
* Notifies that local user changed language.
*/
LANG_CHANGED: "UI.lang_changed",
/**
* Notifies that local user changed email.
*/
EMAIL_CHANGED: "UI.email_changed",
/**
* Notifies that "start muted" settings changed.
*/
START_MUTED_CHANGED: "UI.start_muted_changed",
AUDIO_MUTED: "UI.audio_muted",
VIDEO_MUTED: "UI.video_muted",
/** /**
* Notifies interested parties when the film strip (remote video's panel) * Notifies interested parties when the film strip (remote video's panel)
* is hidden (toggled) or shown (un-toggled). * is hidden (toggled) or shown (un-toggled).

View File

@ -1,5 +0,0 @@
var Events = {
DTMF_SUPPORT_CHANGED: "members.dtmf_support_changed"
};
module.exports = Events;