Merge pull request #421 from isymchych/use-API
Use JS API in jitsi-meet
This commit is contained in:
commit
98f0de258b
|
@ -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
|
|
@ -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
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -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
307
app.js
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 -->
|
||||||
<!--
|
<!--
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||||
|
|
626
modules/UI/UI.js
626
modules/UI/UI.js
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 () {
|
||||||
|
|
|
@ -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();
|
||||||
},
|
},
|
||||||
|
|
|
@ -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;
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
|
|
@ -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,
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
var Events = {
|
|
||||||
DTMF_SUPPORT_CHANGED: "members.dtmf_support_changed"
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Events;
|
|
Loading…
Reference in New Issue