use JS API; UI module refactoring

This commit is contained in:
isymchych 2015-11-30 13:54:54 +02:00
parent 6b621654ab
commit 59f98205c7
9 changed files with 247 additions and 241 deletions

View File

@ -8,10 +8,13 @@ DEPLOY_DIR = libs
BROWSERIFY_FLAGS = -d
OUTPUT_DIR = .
all: compile uglify deploy clean
all: update-deps compile uglify deploy clean
update-deps:
$(NPM) update
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:
rm -f $(OUTPUT_DIR)/app.bundle.*

143
app.js
View File

@ -1,4 +1,5 @@
/* jshint -W117 */
/* global JitsiMeetJS */
/* application specific logic */
require("jquery");
@ -12,18 +13,42 @@ window.toastr = require("toastr");
require("jQuery-Impromptu");
require("autosize");
var APP =
{
function createConference(connection, room) {
var localTracks = [];
var remoteTracks = {};
return {
muteAudio: function (mute) {
},
muteVideo: function (mute) {
},
toggleAudioMuted: function () {
APP.UI.setAudioMuted(muted);
},
toggleVideoMuted: function () {
APP.UI.setVideoMuted(muted);
}
};
}
var APP = {
init: function () {
this.JitsiMeetJS = JitsiMeetJS;
this.JitsiMeetJS.init();
this.conference = null;
this.UI = require("./modules/UI/UI");
this.API = require("./modules/API/API");
this.connectionquality =
require("./modules/connectionquality/connectionquality");
this.statistics = require("./modules/statistics/statistics");
this.RTC = require("./modules/RTC/RTC");
this.desktopsharing =
require("./modules/desktopsharing/desktopsharing");
this.xmpp = require("./modules/xmpp/xmpp");
this.keyboardshortcut =
require("./modules/keyboardshortcut/keyboardshortcut");
this.translation = require("./modules/translation/translation");
@ -34,15 +59,101 @@ var APP =
}
};
function init() {
function connect() {
var connection = new APP.JitsiMeetJS.JitsiConnection(null, null, {
hosts: config.hosts,
bosh: config.bosh,
clientNode: config.clientNode
});
APP.desktopsharing.init();
APP.RTC.start();
APP.xmpp.start();
APP.statistics.start();
APP.connectionquality.init();
APP.keyboardshortcut.init();
APP.members.start();
var events = APP.JitsiMeetJS.events.connection;
return new Promise(function (resolve, reject) {
var onConnectionSuccess = function () {
console.log('CONNECTED');
resolve(connection);
};
var onConnectionFailed = function () {
console.error('CONNECTION FAILED');
reject();
};
var onDisconnect = function () {
console.log('DISCONNECT');
connection.removeEventListener(
events.CONNECTION_ESTABLISHED, onConnectionSuccess
);
connection.removeEventListener(
events.CONNECTION_FAILED, onConnectionFailed
);
connection.removeEventListener(
events.CONNECTION_DISCONNECTED, onDisconnect
);
};
connection.addEventListener(
events.CONNECTION_ESTABLISHED, onConnectionSuccess
);
connection.addEventListener(
events.CONNECTION_FAILED, onConnectionFailed
);
connection.addEventListener(
events.CONNECTION_DISCONNECTED, onDisconnect
);
connection.connect();
}).catch(function (errType, msg) {
// TODO handle OTHER_ERROR only
UI.notifyConnectionFailed(msg);
// rethrow
throw new Error(errType);
});
}
var ConferenceEvents = APP.JitsiMeetJS.events.conference;
function initConference(connection, roomName) {
var room = connection.initJitsiConference(roomName, {
openSctp: config.openSctp,
disableAudioLevels: config.disableAudioLevels
});
room.on(ConferenceEvents.IN_LAST_N_CHANGED, function (inLastN) {
if (config.muteLocalVideoIfNotInLastN) {
// TODO mute or unmute if required
// mark video on UI
// UI.markVideoMuted(true/false);
}
});
room.on(
ConferenceEvents.ACTIVE_SPEAKER_CHANGED,
function (id) {
APP.UI.markDominantSpiker(id);
}
);
room.on(
ConferenceEvents.LAST_N_ENDPOINTS_CHANGED,
function (ids) {
APP.UI.handleLastNEndpoints(ids);
}
);
return initConference(connection, room);
}
function init() {
connect().then(function (connection) {
return initConference(connection, UI.generateRoomName());
}).then(function (conference) {
APP.conference = conference;
APP.desktopsharing.init();
APP.statistics.start();
APP.connectionquality.init();
APP.keyboardshortcut.init();
APP.members.start();
});
}
/**
@ -90,11 +201,12 @@ $(document).ready(function () {
APP.translation.init();
if(APP.API.isEnabled())
if(APP.API.isEnabled()) {
APP.API.init();
}
APP.UI.start(obtainConfigAndInit);
APP.UI.start();
obtainConfigAndInit();
});
$(window).bind('beforeunload', function () {
@ -103,4 +215,3 @@ $(window).bind('beforeunload', function () {
});
module.exports = APP;

View File

@ -14,6 +14,7 @@
<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="interface_config.js?v=6"></script>
<script src="libs/lib-jitsi-meet.js?v=139"></script>
<script src="libs/app.bundle.min.js?v=139"></script>
<script src="analytics.js?v=1"></script><!-- google analytics plugin -->
<!--

View File

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

View File

@ -26,10 +26,6 @@ var JitsiPopover = require("./util/JitsiPopover");
var CQEvents = require("../../service/connectionquality/CQEvents");
var 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 UIEvents = require("../../service/UI/UIEvents");
@ -86,11 +82,6 @@ function promptDisplayName() {
);
}
function notifyForInitialMute() {
messageHandler.notify(null, "notify.mutedTitle", "connected",
"notify.muted", null, {timeOut: 120000});
}
function setupPrezi() {
$("#reloadPresentationLink").click(function() {
Prezi.reloadPresentation();
@ -110,38 +101,6 @@ function setupToolbars() {
BottomToolbar.init(eventEmitter);
}
function streamHandler(stream, isMuted) {
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);
}
@ -153,74 +112,6 @@ function 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(
@ -287,17 +178,11 @@ function registerListeners() {
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) {
UI.messageHandler.showError("dialog.sorry",
@ -357,22 +242,6 @@ function registerListeners() {
}
}
/**
* 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 onResize() {
Chat.resizeChat();
VideoLayout.resizeLargeVideoContainer();
@ -388,7 +257,7 @@ function bindEvents() {
$(window).resize(onResize);
}
UI.start = function (init) {
UI.start = function () {
document.title = interfaceConfig.APP_NAME;
var setupWelcomePage = null;
if(config.enableWelcomePage && window.location.pathname == "/" &&
@ -457,8 +326,6 @@ UI.start = function (init) {
}
}
init();
if (!interfaceConfig.filmStripOnly) {
toastr.options = {
"closeButton": true,
@ -489,6 +356,26 @@ UI.start = function (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) {
return Chat.chatAddError(errorMessage, originalText);
}
@ -665,13 +552,6 @@ function onAuthenticationRequired(intervalCallback) {
}
function onLastNChanged(oldValue, newValue) {
if (config.muteLocalVideoIfNotInLastN) {
setVideoMute(!newValue, { 'byUser': false });
}
}
UI.toggleSmileys = function () {
Chat.toggleSmileys();
};
@ -696,10 +576,6 @@ UI.inputDisplayNameHandler = function (value) {
VideoLayout.inputDisplayNameHandler(value);
};
UI.getLargeVideoResource = function () {
return VideoLayout.getLargeVideoResource();
};
/**
* Return the type of the remote video.
* @param jid the jid for the remote video
@ -814,51 +690,16 @@ UI.getRoomName = function () {
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.
*/
UI.setAudioMuted = function (mute, earlyMute) {
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);
UI.setAudioMuted = function (mute) {
VideoLayout.showLocalAudioIndicator(mute);
UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled");
};
UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled");
})) {
// We still click the button.
UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled");
return;
}
UI.setVideoMuted = function (muted) {
$('#toolbar_button_camera').toggleClass("icon-camera-disabled", muted);
};
UI.addListener = function (type, listener) {
@ -882,27 +723,79 @@ UI.dockToolbar = function (isDock) {
return ToolbarToggler.dockToolbar(isDock);
};
UI.setVideoMuteButtonsState = function (mute) {
var video = $('#toolbar_button_camera');
var communicativeClass = "icon-camera";
var muteClass = "icon-camera icon-camera-disabled";
if (mute) {
video.removeClass(communicativeClass);
video.addClass(muteClass);
} else {
video.removeClass(muteClass);
video.addClass(communicativeClass);
}
};
UI.userAvatarChanged = function (resourceJid, thumbUrl, contactListUrl) {
VideoLayout.userAvatarChanged(resourceJid, thumbUrl);
ContactList.userAvatarChanged(resourceJid, contactListUrl);
if(resourceJid === APP.xmpp.myResource())
if(resourceJid === APP.xmpp.myResource()) {
SettingsMenu.changeAvatar(thumbUrl);
}
};
UI.setVideoMute = setVideoMute;
UI.notifyConnectionFailed = function (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; }
);
};
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.showToolbar = ToolbarToggler.showToolbar;
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);
};
module.exports = UI;

View File

@ -25,7 +25,7 @@ var buttonHandlers = {
} else {
AnalyticsAdapter.sendEvent('toolbar.audio.muted');
}
return APP.UI.toggleAudio();
return APP.conference.toggleAudioMuted();
},
"toolbar_button_camera": function () {
if (APP.RTC.localVideo.isMuted()) {
@ -33,7 +33,7 @@ var buttonHandlers = {
} else {
AnalyticsAdapter.sendEvent('toolbar.video.disabled');
}
return APP.UI.toggleVideo();
return APP.conference.toggleVideoMuted();
},
/*"toolbar_button_authentication": function () {
return Toolbar.authenticateClicked();

View File

@ -56,8 +56,9 @@ var VideoLayout = (function (my) {
};
my.changeLocalAudio = function(stream, isMuted) {
if (isMuted)
APP.UI.setAudioMuted(true, true);
if (isMuted) { // FIXME remove this?
APP.conference.muteAudio(true);
}
APP.RTC.attachMediaStream($('#localAudio'), stream.getOriginalStream());
var localAudio = document.getElementById('localAudio');
// Writing volume not allowed in IE
@ -177,7 +178,7 @@ var VideoLayout = (function (my) {
console.info("electLastVisibleVideo: " + jid);
return jid;
};
my.onRemoteStreamAdded = function (stream) {
if (stream.peerjid) {
VideoLayout.ensurePeerContainerExists(stream.peerjid);
@ -277,9 +278,9 @@ var VideoLayout = (function (my) {
/**
* Checks if container for participant identified by given peerJid exists
* in the document and creates it eventually.
*
*
* @param peerJid peer Jid to check.
*
*
* @return Returns <tt>true</tt> if the peer container exists,
* <tt>false</tt> - otherwise
*/
@ -652,9 +653,7 @@ var VideoLayout = (function (my) {
* @param endpointsEnteringLastN the list currently entering last N
* endpoints
*/
my.onLastNEndpointsChanged = function (lastNEndpoints,
endpointsEnteringLastN,
stream) {
my.onLastNEndpointsChanged = function (lastNEndpoints, endpointsEnteringLastN) {
if (lastNCount !== lastNEndpoints.length)
lastNCount = lastNEndpoints.length;
@ -847,7 +846,7 @@ var VideoLayout = (function (my) {
/**
* Hides all the indicators
*/
my.onStatsStop = function () {
my.hideStats = function () {
for(var video in remoteVideos) {
remoteVideos[video].hideIndicator();
}
@ -879,7 +878,7 @@ var VideoLayout = (function (my) {
VideoLayout.resizeThumbnails();
};
my.onVideoTypeChanged = function (resourceJid, newVideoType) {
if (remoteVideoTypes[resourceJid] === newVideoType) {
return;

View File

@ -21,20 +21,20 @@ function initShortcutHandlers() {
77: {
character: "M",
id: "mutePopover",
function: APP.UI.toggleAudio
function: APP.conference.toggleAudioMuted
},
84: {
character: "T",
function: function() {
if(!APP.RTC.localAudio.isMuted()) {
APP.UI.toggleAudio();
APP.conference.toggleAudioMuted();
}
}
},
86: {
character: "V",
id: "toggleVideoPopover",
function: APP.UI.toggleVideo
function: APP.conference.toggleVideoMuted
}
};
}
@ -68,7 +68,7 @@ var KeyboardShortcut = {
$(":focus").is("textarea"))) {
if(e.which === "T".charCodeAt(0)) {
if(APP.RTC.localAudio.isMuted()) {
APP.UI.toggleAudio();
APP.conference.toggleAudioMuted();
}
}
}

View File

@ -1,5 +1,4 @@
/* global $, $iq, config, connection, focusMucJid, forceMuted,
setAudioMuted, Strophe */
/* global $, $iq, config, connection, focusMucJid, forceMuted, Strophe */
/**
* Moderate connection plugin.
*/
@ -58,4 +57,4 @@ module.exports = function (XMPP, eventEmitter) {
this.connection.emuc.kick(jid);
}
});
};
};