added some documentation (jsdocs)
This commit is contained in:
parent
a0355ea080
commit
6b98fd52ea
|
@ -17,6 +17,9 @@ const ConferenceErrors = JitsiMeetJS.errors.conference;
|
|||
|
||||
let room, connection, localTracks, localAudio, localVideo, roomLocker;
|
||||
|
||||
/**
|
||||
* Known custom conference commands.
|
||||
*/
|
||||
const Commands = {
|
||||
CONNECTION_QUALITY: "stats",
|
||||
EMAIL: "email",
|
||||
|
@ -26,6 +29,10 @@ const Commands = {
|
|||
STOP_PREZI: "stop-prezi"
|
||||
};
|
||||
|
||||
/**
|
||||
* Open Connection. When authentication failed it shows auth dialog.
|
||||
* @returns Promise<JitsiConnection>
|
||||
*/
|
||||
function connect() {
|
||||
return openConnection({retry: true}).catch(function (err) {
|
||||
if (err === ConnectionErrors.PASSWORD_REQUIRED) {
|
||||
|
@ -37,8 +44,14 @@ function connect() {
|
|||
});
|
||||
}
|
||||
|
||||
const addTrack = (track) => {
|
||||
/**
|
||||
* Add local track to the conference and shares
|
||||
* video type with other users if its video track.
|
||||
* @param {JitsiLocalTrack} track local track
|
||||
*/
|
||||
function addTrack (track) {
|
||||
room.addTrack(track);
|
||||
|
||||
if (track.isAudioTrack()) {
|
||||
return;
|
||||
}
|
||||
|
@ -50,25 +63,35 @@ const addTrack = (track) => {
|
|||
xmlns: 'http://jitsi.org/jitmeet/video'
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// share email with other users
|
||||
const sendEmail = (email) => {
|
||||
/**
|
||||
* Share email with other users.
|
||||
* @param {string} email new email
|
||||
*/
|
||||
function sendEmail (email) {
|
||||
room.sendCommand(Commands.EMAIL, {
|
||||
value: email,
|
||||
attributes: {
|
||||
id: room.myUserId()
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const unload = () => {
|
||||
/**
|
||||
* Leave the conference and close connection.
|
||||
*/
|
||||
function unload () {
|
||||
room.leave();
|
||||
connection.disconnect();
|
||||
};
|
||||
}
|
||||
|
||||
const getDisplayName = (id) => {
|
||||
/**
|
||||
* Get user nickname by user id.
|
||||
* @param {string} id user id
|
||||
* @returns {string?} user nickname or undefined if user is unknown.
|
||||
*/
|
||||
function getDisplayName (id) {
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
return APP.settings.getDisplayName();
|
||||
}
|
||||
|
@ -77,7 +100,7 @@ const getDisplayName = (id) => {
|
|||
if (participant && participant.getDisplayName()) {
|
||||
return participant.getDisplayName();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class ConferenceConnector {
|
||||
constructor(resolve, reject) {
|
||||
|
@ -151,6 +174,12 @@ export default {
|
|||
isModerator: false,
|
||||
audioMuted: false,
|
||||
videoMuted: false,
|
||||
/**
|
||||
* Open new connection and join to the conference.
|
||||
* @param {object} options
|
||||
* @param {string} roomName name of the conference
|
||||
* @returns {Promise}
|
||||
*/
|
||||
init(options) {
|
||||
this.roomName = options.roomName;
|
||||
JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.TRACE);
|
||||
|
@ -173,6 +202,12 @@ export default {
|
|||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Create local tracks of specified types.
|
||||
* If we cannot obtain required tracks it will return empty array.
|
||||
* @param {string[]} devices required track types ('audio', 'video' etc.)
|
||||
* @returns {Promise<JitsiLocalTrack[]>}
|
||||
*/
|
||||
createLocalTracks (...devices) {
|
||||
return JitsiMeetJS.createLocalTracks({
|
||||
// copy array to avoid mutations inside library
|
||||
|
@ -184,6 +219,11 @@ export default {
|
|||
return Promise.reject(err);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Check if id is id of the local user.
|
||||
* @param {string} id id to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isLocalId (id) {
|
||||
return this.localId === id;
|
||||
},
|
||||
|
@ -217,12 +257,24 @@ export default {
|
|||
toggleVideoMuted () {
|
||||
this.muteVideo(!this.videoMuted);
|
||||
},
|
||||
/**
|
||||
* Retrieve list of conference participants (without local user).
|
||||
* @returns {JitsiParticipant[]}
|
||||
*/
|
||||
listMembers () {
|
||||
return room.getParticipants();
|
||||
},
|
||||
/**
|
||||
* Retrieve list of ids of conference participants (without local user).
|
||||
* @returns {string[]}
|
||||
*/
|
||||
listMembersIds () {
|
||||
return room.getParticipants().map(p => p.getId());
|
||||
},
|
||||
/**
|
||||
* Check if SIP is supported.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
sipGatewayEnabled () {
|
||||
return room.isSIPCallingSupported();
|
||||
},
|
||||
|
@ -279,7 +331,7 @@ export default {
|
|||
/**
|
||||
* Will check for number of remote particiapnts that have at least one
|
||||
* remote track.
|
||||
* @return boolean whether we have enough participants with remote streams
|
||||
* @return {boolean} whether we have enough participants with remote streams
|
||||
*/
|
||||
checkEnoughParticipants (number) {
|
||||
var participants = this._room.getParticipants();
|
||||
|
@ -336,6 +388,9 @@ export default {
|
|||
}
|
||||
return options;
|
||||
},
|
||||
/**
|
||||
* Setup interaction between conference and UI.
|
||||
*/
|
||||
_setupListeners () {
|
||||
// add local streams when joined to the conference
|
||||
room.on(ConferenceEvents.CONFERENCE_JOINED, () => {
|
||||
|
|
|
@ -5,6 +5,13 @@ import LoginDialog from './modules/UI/authentication/LoginDialog';
|
|||
const ConnectionEvents = JitsiMeetJS.events.connection;
|
||||
const ConnectionErrors = JitsiMeetJS.errors.connection;
|
||||
|
||||
/**
|
||||
* Try to open connection using provided credentials.
|
||||
* @param {string} [id]
|
||||
* @param {string} [password]
|
||||
* @returns {Promise<JitsiConnection>} connection if
|
||||
* everything is ok, else error.
|
||||
*/
|
||||
function connect(id, password) {
|
||||
let connection = new JitsiMeetJS.JitsiConnection(null, null, config);
|
||||
|
||||
|
@ -42,6 +49,12 @@ function connect(id, password) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Authentication Dialog and try to connect with new credentials.
|
||||
* If failed to connect because of PASSWORD_REQUIRED error
|
||||
* then ask for password again.
|
||||
* @returns {Promise<JitsiConnection>}
|
||||
*/
|
||||
function requestAuth() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
let authDialog = LoginDialog.showAuthDialog(
|
||||
|
@ -62,6 +75,18 @@ function requestAuth() {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open JitsiConnection using provided credentials.
|
||||
* If retry option is true it will show auth dialog on PASSWORD_REQUIRED error.
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {string} [options.id]
|
||||
* @param {string} [options.password]
|
||||
* @param {boolean} [retry] if we should show auth dialog
|
||||
* on PASSWORD_REQUIRED error.
|
||||
*
|
||||
* @returns {Promise<JitsiConnection>}
|
||||
*/
|
||||
export function openConnection({id, password, retry}) {
|
||||
return connect(id, password).catch(function (err) {
|
||||
if (!retry) {
|
||||
|
|
178
modules/UI/UI.js
178
modules/UI/UI.js
|
@ -31,6 +31,9 @@ UI.eventEmitter = eventEmitter;
|
|||
let preziManager;
|
||||
let etherpadManager;
|
||||
|
||||
/**
|
||||
* Prompt user for nickname.
|
||||
*/
|
||||
function promptDisplayName() {
|
||||
let nickRequiredMsg = APP.translation.translateString("dialog.displayNameRequired");
|
||||
let defaultNickMsg = APP.translation.translateString(
|
||||
|
@ -76,6 +79,9 @@ function promptDisplayName() {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize chat.
|
||||
*/
|
||||
function setupChat() {
|
||||
Chat.init(eventEmitter);
|
||||
$("#toggle_smileys").click(function() {
|
||||
|
@ -83,6 +89,9 @@ function setupChat() {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize toolbars.
|
||||
*/
|
||||
function setupToolbars() {
|
||||
Toolbar.init(eventEmitter);
|
||||
Toolbar.setupButtonsFromConfig();
|
||||
|
@ -113,6 +122,9 @@ function toggleFullScreen () {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify user that server has shut down.
|
||||
*/
|
||||
UI.notifyGracefulShudown = function () {
|
||||
messageHandler.openMessageDialog(
|
||||
'dialog.serviceUnavailable',
|
||||
|
@ -120,6 +132,9 @@ UI.notifyGracefulShudown = function () {
|
|||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify user that reservation error happened.
|
||||
*/
|
||||
UI.notifyReservationError = function (code, msg) {
|
||||
var title = APP.translation.generateTranslationHTML(
|
||||
"dialog.reservationError");
|
||||
|
@ -135,14 +150,25 @@ UI.notifyReservationError = function (code, msg) {
|
|||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify user that he has been kicked from the server.
|
||||
*/
|
||||
UI.notifyKicked = function () {
|
||||
messageHandler.openMessageDialog("dialog.sessTerminated", "dialog.kickMessage");
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify user that Jitsi Videobridge is not accessible.
|
||||
*/
|
||||
UI.notifyBridgeDown = function () {
|
||||
messageHandler.showError("dialog.error", "dialog.bridgeUnavailable");
|
||||
};
|
||||
|
||||
/**
|
||||
* Change nickname for the user.
|
||||
* @param {string} id user id
|
||||
* @param {string} displayName new nickname
|
||||
*/
|
||||
UI.changeDisplayName = function (id, displayName) {
|
||||
ContactList.onDisplayNameChange(id, displayName);
|
||||
SettingsMenu.onDisplayNameChange(id, displayName);
|
||||
|
@ -153,6 +179,9 @@ UI.changeDisplayName = function (id, displayName) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Intitialize conference UI.
|
||||
*/
|
||||
UI.initConference = function () {
|
||||
var id = APP.conference.localId;
|
||||
Toolbar.updateRoomUrl(window.location.href);
|
||||
|
@ -186,6 +215,9 @@ UI.mucJoined = function () {
|
|||
VideoLayout.mucJoined();
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup some UI event listeners.
|
||||
*/
|
||||
function registerListeners() {
|
||||
UI.addListener(UIEvents.EMAIL_CHANGED, function (email) {
|
||||
UI.setUserAvatar(APP.conference.localId, email);
|
||||
|
@ -214,6 +246,9 @@ function registerListeners() {
|
|||
UI.addListener(UIEvents.TOGGLE_FILM_STRIP, UI.toggleFilmStrip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup some DOM event listeners.
|
||||
*/
|
||||
function bindEvents() {
|
||||
function onResize() {
|
||||
PanelToggler.resizeChat();
|
||||
|
@ -341,6 +376,10 @@ UI.start = function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Show local stream on UI.
|
||||
* @param {JitsiTrack} track stream to show
|
||||
*/
|
||||
UI.addLocalStream = function (track) {
|
||||
switch (track.getType()) {
|
||||
case 'audio':
|
||||
|
@ -356,18 +395,30 @@ UI.addLocalStream = function (track) {
|
|||
};
|
||||
|
||||
|
||||
UI.addRemoteStream = function (stream) {
|
||||
VideoLayout.onRemoteStreamAdded(stream);
|
||||
/**
|
||||
* Show remote stream on UI.
|
||||
* @param {JitsiTrack} track stream to show
|
||||
*/
|
||||
UI.addRemoteStream = function (track) {
|
||||
VideoLayout.onRemoteStreamAdded(track);
|
||||
};
|
||||
|
||||
function chatAddError(errorMessage, originalText) {
|
||||
return Chat.chatAddError(errorMessage, originalText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update chat subject.
|
||||
* @param {string} subject new chat subject
|
||||
*/
|
||||
UI.setSubject = function (subject) {
|
||||
Chat.setSubject(subject);
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup and show Etherpad.
|
||||
* @param {string} name etherpad id
|
||||
*/
|
||||
UI.initEtherpad = function (name) {
|
||||
if (etherpadManager || !config.etherpad_base || !name) {
|
||||
return;
|
||||
|
@ -377,6 +428,11 @@ UI.initEtherpad = function (name) {
|
|||
Toolbar.showEtherpadButton();
|
||||
};
|
||||
|
||||
/**
|
||||
* Show user on UI.
|
||||
* @param {string} id user id
|
||||
* @param {string} displayName user nickname
|
||||
*/
|
||||
UI.addUser = function (id, displayName) {
|
||||
ContactList.addContact(id);
|
||||
|
||||
|
@ -395,6 +451,11 @@ UI.addUser = function (id, displayName) {
|
|||
VideoLayout.addParticipantContainer(id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove user from UI.
|
||||
* @param {string} id user id
|
||||
* @param {string} displayName user nickname
|
||||
*/
|
||||
UI.removeUser = function (id, displayName) {
|
||||
ContactList.removeContact(id);
|
||||
|
||||
|
@ -415,10 +476,19 @@ UI.removeUser = function (id, displayName) {
|
|||
// VideoLayout.setPresenceStatus(Strophe.getResourceFromJid(jid), info.status);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Update videotype for specified user.
|
||||
* @param {string} id user id
|
||||
* @param {string} newVideoType new videotype
|
||||
*/
|
||||
UI.onPeerVideoTypeChanged = (id, newVideoType) => {
|
||||
VideoLayout.onVideoTypeChanged(id, newVideoType);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update local user role and show notification if user is moderator.
|
||||
* @param {boolean} isModerator if local user is moderator or not
|
||||
*/
|
||||
UI.updateLocalRole = function (isModerator) {
|
||||
VideoLayout.showModeratorIndicator();
|
||||
|
||||
|
@ -462,22 +532,38 @@ UI.updateUserRole = function (user) {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Toggles smileys in the chat.
|
||||
*/
|
||||
UI.toggleSmileys = function () {
|
||||
Chat.toggleSmileys();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get current settings.
|
||||
* @returns {object} settings
|
||||
*/
|
||||
UI.getSettings = function () {
|
||||
return Settings.getSettings();
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggles film strip.
|
||||
*/
|
||||
UI.toggleFilmStrip = function () {
|
||||
BottomToolbar.toggleFilmStrip();
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggles chat panel.
|
||||
*/
|
||||
UI.toggleChat = function () {
|
||||
PanelToggler.toggleChat();
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggles contact list panel.
|
||||
*/
|
||||
UI.toggleContactList = function () {
|
||||
PanelToggler.toggleContactList();
|
||||
};
|
||||
|
@ -499,6 +585,7 @@ UI.connectionIndicatorShowMore = function(jid) {
|
|||
return VideoLayout.showMore(jid);
|
||||
};
|
||||
|
||||
// FIXME check if someone user this
|
||||
UI.showLoginPopup = function(callback) {
|
||||
console.log('password is required');
|
||||
var message = '<h2 data-i18n="dialog.passwordRequired">';
|
||||
|
@ -569,6 +656,11 @@ UI.dockToolbar = function (isDock) {
|
|||
ToolbarToggler.dockToolbar(isDock);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update user avatar.
|
||||
* @param {string} id user id
|
||||
* @param {stirng} email user email
|
||||
*/
|
||||
UI.setUserAvatar = function (id, email) {
|
||||
// update avatar
|
||||
Avatar.setUserAvatar(id, email);
|
||||
|
@ -582,6 +674,10 @@ UI.setUserAvatar = function (id, email) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify user that connection failed.
|
||||
* @param {string} stropheErrorMsg raw Strophe error message
|
||||
*/
|
||||
UI.notifyConnectionFailed = function (stropheErrorMsg) {
|
||||
var title = APP.translation.generateTranslationHTML(
|
||||
"dialog.error");
|
||||
|
@ -600,6 +696,10 @@ UI.notifyConnectionFailed = function (stropheErrorMsg) {
|
|||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify user that he need to install Firefox extension to share screen.
|
||||
* @param {stirng} url extension url
|
||||
*/
|
||||
UI.notifyFirefoxExtensionRequired = function (url) {
|
||||
messageHandler.openMessageDialog(
|
||||
"dialog.extensionRequired",
|
||||
|
@ -611,12 +711,19 @@ UI.notifyFirefoxExtensionRequired = function (url) {
|
|||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify user that he was automatically muted when joned the conference.
|
||||
*/
|
||||
UI.notifyInitiallyMuted = function () {
|
||||
messageHandler.notify(
|
||||
null, "notify.mutedTitle", "connected", "notify.muted", null, {timeOut: 120000}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark user as dominant speaker.
|
||||
* @param {string} id user id
|
||||
*/
|
||||
UI.markDominantSpeaker = function (id) {
|
||||
VideoLayout.onDominantSpeakerChanged(id);
|
||||
};
|
||||
|
@ -625,26 +732,53 @@ UI.handleLastNEndpoints = function (ids) {
|
|||
VideoLayout.onLastNEndpointsChanged(ids, []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update audio level visualization for specified user.
|
||||
* @param {string} id user id
|
||||
* @param {number} lvl audio level
|
||||
*/
|
||||
UI.setAudioLevel = function (id, lvl) {
|
||||
VideoLayout.setAudioLevel(id, lvl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update state of desktop sharing buttons.
|
||||
* @param {boolean} isSharingScreen if user is currently sharing his screen
|
||||
*/
|
||||
UI.updateDesktopSharingButtons = function (isSharingScreen) {
|
||||
Toolbar.changeDesktopSharingButtonState(isSharingScreen);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide connection quality statistics from UI.
|
||||
*/
|
||||
UI.hideStats = function () {
|
||||
VideoLayout.hideStats();
|
||||
};
|
||||
|
||||
/**
|
||||
* Update local connection quality statistics.
|
||||
* @param {number} percent
|
||||
* @param {object} stats
|
||||
*/
|
||||
UI.updateLocalStats = function (percent, stats) {
|
||||
VideoLayout.updateLocalConnectionStats(percent, stats);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update connection quality statistics for remote user.
|
||||
* @param {string} id user id
|
||||
* @param {number} percent
|
||||
* @param {object} stats
|
||||
*/
|
||||
UI.updateRemoteStats = function (id, percent, stats) {
|
||||
VideoLayout.updateConnectionStats(id, percent, stats);
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark video as interrupted or not.
|
||||
* @param {boolean} interrupted if video is interrupted
|
||||
*/
|
||||
UI.markVideoInterrupted = function (interrupted) {
|
||||
if (interrupted) {
|
||||
VideoLayout.onVideoInterrupted();
|
||||
|
@ -653,6 +787,10 @@ UI.markVideoInterrupted = function (interrupted) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark room as locked or not.
|
||||
* @param {boolean} locked if room is locked.
|
||||
*/
|
||||
UI.markRoomLocked = function (locked) {
|
||||
if (locked) {
|
||||
Toolbar.lockLockButton();
|
||||
|
@ -661,6 +799,13 @@ UI.markRoomLocked = function (locked) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Add chat message.
|
||||
* @param {string} from user id
|
||||
* @param {string} displayName user nickname
|
||||
* @param {string} message message text
|
||||
* @param {number} stamp timestamp when message was created
|
||||
*/
|
||||
UI.addMessage = function (from, displayName, message, stamp) {
|
||||
Chat.updateChatConversation(from, displayName, message, stamp);
|
||||
};
|
||||
|
@ -672,6 +817,10 @@ UI.updateDTMFSupport = function (isDTMFSupported) {
|
|||
|
||||
/**
|
||||
* Invite participants to conference.
|
||||
* @param {string} roomUrl
|
||||
* @param {string} conferenceName
|
||||
* @param {string} key
|
||||
* @param {string} nick
|
||||
*/
|
||||
UI.inviteParticipants = function (roomUrl, conferenceName, key, nick) {
|
||||
let keyText = "";
|
||||
|
@ -710,6 +859,10 @@ UI.inviteParticipants = function (roomUrl, conferenceName, key, nick) {
|
|||
window.open(`mailto:?subject=${subject}&body=${body}`, '_blank');
|
||||
};
|
||||
|
||||
/**
|
||||
* Show user feedback dialog if its required or just show "thank you" dialog.
|
||||
* @returns {Promise} when dialog is closed.
|
||||
*/
|
||||
UI.requestFeedback = function () {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (Feedback.isEnabled()) {
|
||||
|
@ -736,6 +889,10 @@ UI.requestFeedback = function () {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Request recording token from the user.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
UI.requestRecordingToken = function () {
|
||||
let msg = APP.translation.generateTranslationHTML("dialog.recordingToken");
|
||||
let token = APP.translation.translateString("dialog.token");
|
||||
|
@ -769,6 +926,11 @@ UI.notifyTokenAuthFailed = function () {
|
|||
messageHandler.showError("dialog.error", "dialog.tokenAuthFailed");
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates auth info on the UI.
|
||||
* @param {boolean} isAuthEnabled if authentication is enabled
|
||||
* @param {string} [login] current login
|
||||
*/
|
||||
UI.updateAuthInfo = function (isAuthEnabled, login) {
|
||||
let loggedIn = !!login;
|
||||
|
||||
|
@ -782,10 +944,20 @@ UI.updateAuthInfo = function (isAuthEnabled, login) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Show Prezi from the user.
|
||||
* @param {string} userId user id
|
||||
* @param {string} url Prezi url
|
||||
* @param {number} slide slide to show
|
||||
*/
|
||||
UI.showPrezi = function (userId, url, slide) {
|
||||
preziManager.showPrezi(userId, url, slide);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop showing Prezi from the user.
|
||||
* @param {string} userId user id
|
||||
*/
|
||||
UI.stopPrezi = function (userId) {
|
||||
if (preziManager.isSharing(userId)) {
|
||||
preziManager.removePrezi(userId);
|
||||
|
@ -798,7 +970,7 @@ UI.onStartMutedChanged = function () {
|
|||
|
||||
/**
|
||||
* Returns the id of the current video shown on large.
|
||||
* Currently used by tests (troture).
|
||||
* Currently used by tests (torture).
|
||||
*/
|
||||
UI.getLargeVideoID = function () {
|
||||
return VideoLayout.getLargeVideoID();
|
||||
|
|
|
@ -10,6 +10,13 @@ const ConferenceEvents = JitsiMeetJS.events.conference;
|
|||
let externalAuthWindow;
|
||||
let authRequiredDialog;
|
||||
|
||||
/**
|
||||
* Authenticate using external service or just focus
|
||||
* external auth window if there is one already.
|
||||
*
|
||||
* @param {JitsiConference} room
|
||||
* @param {string} [lockPassword] password to use if the conference is locked
|
||||
*/
|
||||
function doExternalAuth (room, lockPassword) {
|
||||
if (externalAuthWindow) {
|
||||
externalAuthWindow.focus();
|
||||
|
@ -32,6 +39,11 @@ function doExternalAuth (room, lockPassword) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate on the server.
|
||||
* @param {JitsiConference} room
|
||||
* @param {string} [lockPassword] password to use if the conference is locked
|
||||
*/
|
||||
function doXmppAuth (room, lockPassword) {
|
||||
let loginDialog = LoginDialog.showAuthDialog(function (id, password) {
|
||||
// auth "on the fly":
|
||||
|
@ -83,6 +95,12 @@ function doXmppAuth (room, lockPassword) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate for the conference.
|
||||
* Uses external service for auth if conference supports that.
|
||||
* @param {JitsiConference} room
|
||||
* @param {string} [lockPassword] password to use if the conference is locked
|
||||
*/
|
||||
function authenticate (room, lockPassword) {
|
||||
if (room.isExternalAuthEnabled()) {
|
||||
doExternalAuth(room, lockPassword);
|
||||
|
@ -91,6 +109,9 @@ function authenticate (room, lockPassword) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify user that authentication is required to create the conference.
|
||||
*/
|
||||
function requireAuth(roomName) {
|
||||
if (authRequiredDialog) {
|
||||
return;
|
||||
|
@ -101,6 +122,9 @@ function requireAuth(roomName) {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close auth-related dialogs if there are any.
|
||||
*/
|
||||
function closeAuth() {
|
||||
if (externalAuthWindow) {
|
||||
externalAuthWindow.close();
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
var messageHandler = require('../util/MessageHandler');
|
||||
|
||||
/**
|
||||
* Build html for "password required" dialog.
|
||||
* @returns {string} html string
|
||||
*/
|
||||
function getPasswordInputHtml() {
|
||||
let placeholder = config.hosts.authdomain
|
||||
? "user identity"
|
||||
|
@ -13,11 +17,16 @@ function getPasswordInputHtml() {
|
|||
<h2 data-i18n="dialog.passwordRequired">${passRequiredMsg}</h2>
|
||||
<input name="username" type="text" placeholder=${placeholder} autofocus>
|
||||
<input name="password" type="password"
|
||||
data-i18n="[placeholder]dialog.userPassword"
|
||||
placeholder="user password">
|
||||
data-i18n="[placeholder]dialog.userPassword"
|
||||
placeholder="user password">
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert provided id to jid if it's not jid yet.
|
||||
* @param {string} id user id or jid
|
||||
* @returns {string} jid
|
||||
*/
|
||||
function toJid(id) {
|
||||
if (id.indexOf("@") >= 0) {
|
||||
return id;
|
||||
|
@ -33,6 +42,10 @@ function toJid(id) {
|
|||
return jid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate cancel button config for the dialog.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function cancelButton() {
|
||||
return {
|
||||
title: APP.translation.generateTranslationHTML("dialog.Cancel"),
|
||||
|
@ -40,7 +53,18 @@ function cancelButton() {
|
|||
};
|
||||
}
|
||||
|
||||
function Dialog(successCallback, cancelCallback) {
|
||||
/**
|
||||
* Auth dialog for JitsiConnection which supports retries.
|
||||
* If no cancelCallback provided then there will be
|
||||
* no cancel button on the dialog.
|
||||
*
|
||||
* @class LoginDialog
|
||||
* @constructor
|
||||
*
|
||||
* @param {function(jid, password)} successCallback
|
||||
* @param {function} [cancelCallback] callback to invoke if user canceled.
|
||||
*/
|
||||
function LoginDialog(successCallback, cancelCallback) {
|
||||
let loginButtons = [{
|
||||
title: APP.translation.generateTranslationHTML("dialog.Ok"),
|
||||
value: true
|
||||
|
@ -118,6 +142,10 @@ function Dialog(successCallback, cancelCallback) {
|
|||
connDialog.goToState('finished');
|
||||
};
|
||||
|
||||
/**
|
||||
* Show message as connection status.
|
||||
* @param {string} message
|
||||
*/
|
||||
this.displayConnectionStatus = function (message) {
|
||||
let connectingState = connDialog.getState('connecting');
|
||||
|
||||
|
@ -133,12 +161,26 @@ function Dialog(successCallback, cancelCallback) {
|
|||
};
|
||||
}
|
||||
|
||||
const LoginDialog = {
|
||||
export default {
|
||||
|
||||
/**
|
||||
* Show new auth dialog for JitsiConnection.
|
||||
*
|
||||
* @param {function(jid, password)} successCallback
|
||||
* @param {function} [cancelCallback] callback to invoke if user canceled.
|
||||
*
|
||||
* @returns {LoginDialog}
|
||||
*/
|
||||
showAuthDialog: function (successCallback, cancelCallback) {
|
||||
return new Dialog(successCallback, cancelCallback);
|
||||
return new LoginDialog(successCallback, cancelCallback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Show notification that external auth is required (using provided url).
|
||||
* @param {string} url URL to use for external auth.
|
||||
* @param {function} callback callback to invoke when auth popup is closed.
|
||||
* @returns auth dialog
|
||||
*/
|
||||
showExternalAuthDialog: function (url, callback) {
|
||||
var dialog = messageHandler.openCenteredPopup(
|
||||
url, 910, 660,
|
||||
|
@ -153,6 +195,14 @@ const LoginDialog = {
|
|||
return dialog;
|
||||
},
|
||||
|
||||
/**
|
||||
* Show notification that authentication is required
|
||||
* to create the conference, so he should authenticate or wait for a host.
|
||||
* @param {string} roomName name of the conference
|
||||
* @param {function} onAuthNow callback to invoke if
|
||||
* user want to authenticate.
|
||||
* @returns dialog
|
||||
*/
|
||||
showAuthRequiredDialog: function (roomName, onAuthNow) {
|
||||
var title = APP.translation.generateTranslationHTML(
|
||||
"dialog.WaitingForHost"
|
||||
|
@ -184,5 +234,3 @@ const LoginDialog = {
|
|||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default LoginDialog;
|
||||
|
|
|
@ -4,6 +4,10 @@ import UIUtil from '../util/UIUtil';
|
|||
//FIXME:
|
||||
import AnalyticsAdapter from '../../statistics/AnalyticsAdapter';
|
||||
|
||||
/**
|
||||
* Show dialog which asks user for new password for the conference.
|
||||
* @returns {Promise<string>} password or nothing if user canceled
|
||||
*/
|
||||
function askForNewPassword () {
|
||||
let passMsg = APP.translation.generateTranslationHTML("dialog.passwordMsg");
|
||||
let yourPassMsg = APP.translation.translateString("dialog.yourPassword");
|
||||
|
@ -30,6 +34,10 @@ function askForNewPassword () {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show dialog which asks for required conference password.
|
||||
* @returns {Promise<string>} password or nothing if user canceled
|
||||
*/
|
||||
function askForPassword () {
|
||||
let passRequiredMsg = APP.translation.translateString(
|
||||
"dialog.passwordRequired"
|
||||
|
@ -58,6 +66,10 @@ function askForPassword () {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show dialog which asks if user want remove password from the conference.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function askToUnlock () {
|
||||
return new Promise(function (resolve, reject) {
|
||||
messageHandler.openTwoButtonDialog(
|
||||
|
@ -74,18 +86,32 @@ function askToUnlock () {
|
|||
});
|
||||
}
|
||||
|
||||
function notifyPasswordNotSupported (err) {
|
||||
console.warn('setting password failed', err);
|
||||
/**
|
||||
* Show notification that user cannot set password for the conference
|
||||
* because server doesn't support that.
|
||||
*/
|
||||
function notifyPasswordNotSupported () {
|
||||
console.warn('room passwords not supported');
|
||||
messageHandler.showError("dialog.warning", "dialog.passwordNotSupported");
|
||||
}
|
||||
|
||||
function notifyPasswordFailed() {
|
||||
console.warn('room passwords not supported');
|
||||
/**
|
||||
* Show notification that setting password for the conference failed.
|
||||
* @param {Error} err error
|
||||
*/
|
||||
function notifyPasswordFailed(err) {
|
||||
console.warn('setting password failed', err);
|
||||
messageHandler.showError("dialog.lockTitle", "dialog.lockMessage");
|
||||
}
|
||||
|
||||
const ConferenceErrors = JitsiMeetJS.errors.conference;
|
||||
|
||||
/**
|
||||
* Create new RoomLocker for the conference.
|
||||
* It allows to set or remove password for the conference,
|
||||
* or ask for required password.
|
||||
* @returns {RoomLocker}
|
||||
*/
|
||||
export default function createRoomLocker (room) {
|
||||
let password;
|
||||
|
||||
|
@ -103,6 +129,9 @@ export default function createRoomLocker (room) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @class RoomLocker
|
||||
*/
|
||||
return {
|
||||
get isLocked () {
|
||||
return !!password;
|
||||
|
@ -112,6 +141,10 @@ export default function createRoomLocker (room) {
|
|||
return password;
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows to remove password from the conference (asks user first).
|
||||
* @returns {Promise}
|
||||
*/
|
||||
askToUnlock () {
|
||||
return askToUnlock().then(function () {
|
||||
return lock();
|
||||
|
@ -120,6 +153,11 @@ export default function createRoomLocker (room) {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Allows to set password for the conference.
|
||||
* It asks user for new password and locks the room.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
askToLock () {
|
||||
return askForNewPassword().then(function (newPass) {
|
||||
return lock(newPass);
|
||||
|
@ -128,12 +166,18 @@ export default function createRoomLocker (room) {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Asks user for required conference password.
|
||||
*/
|
||||
requirePassword () {
|
||||
return askForPassword().then(function (newPass) {
|
||||
password = newPass;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Show notification that to set/remove password user must be moderator.
|
||||
*/
|
||||
notifyModeratorRequired () {
|
||||
if (password) {
|
||||
messageHandler.openMessageDialog(null, "dialog.passwordError");
|
||||
|
|
|
@ -6,6 +6,9 @@ import UIUtil from "../util/UIUtil";
|
|||
import SidePanelToggler from "../side_pannels/SidePanelToggler";
|
||||
import BottomToolbar from '../toolbars/BottomToolbar';
|
||||
|
||||
/**
|
||||
* Etherpad options.
|
||||
*/
|
||||
const options = $.param({
|
||||
showControns: true,
|
||||
showChat: false,
|
||||
|
@ -40,11 +43,20 @@ function bubbleIframeMouseMove(iframe){
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Etherpad frame width.
|
||||
*/
|
||||
const DEFAULT_WIDTH = 640;
|
||||
/**
|
||||
* Default Etherpad frame height.
|
||||
*/
|
||||
const DEFAULT_HEIGHT = 480;
|
||||
|
||||
const EtherpadContainerType = "etherpad";
|
||||
|
||||
/**
|
||||
* Container for Etherpad iframe.
|
||||
*/
|
||||
class Etherpad extends LargeContainer {
|
||||
constructor (domain, name) {
|
||||
super();
|
||||
|
@ -123,6 +135,9 @@ class Etherpad extends LargeContainer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manager of the Etherpad frame.
|
||||
*/
|
||||
export default class EtherpadManager {
|
||||
constructor (domain, name) {
|
||||
if (!domain || !name) {
|
||||
|
@ -138,6 +153,9 @@ export default class EtherpadManager {
|
|||
return !!this.etherpad;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new Etherpad frame.
|
||||
*/
|
||||
openEtherpad () {
|
||||
this.etherpad = new Etherpad(this.domain, this.name);
|
||||
VideoLayout.addLargeVideoContainer(
|
||||
|
@ -146,6 +164,10 @@ export default class EtherpadManager {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle Etherpad frame visibility.
|
||||
* Open new Etherpad frame if there is no Etherpad frame yet.
|
||||
*/
|
||||
toggleEtherpad () {
|
||||
if (!this.isOpen) {
|
||||
this.openEtherpad();
|
||||
|
|
|
@ -11,17 +11,31 @@ import ToolbarToggler from "../toolbars/ToolbarToggler";
|
|||
import SidePanelToggler from "../side_pannels/SidePanelToggler";
|
||||
import BottomToolbar from '../toolbars/BottomToolbar';
|
||||
|
||||
/**
|
||||
* Example of Prezi link.
|
||||
*/
|
||||
const defaultPreziLink = "http://prezi.com/wz7vhjycl7e6/my-prezi";
|
||||
const alphanumRegex = /^[a-z0-9-_\/&\?=;]+$/i;
|
||||
/**
|
||||
* Default aspect ratio for Prezi frame.
|
||||
*/
|
||||
const aspectRatio = 16.0 / 9.0;
|
||||
|
||||
/**
|
||||
* Default Prezi frame width.
|
||||
*/
|
||||
const DEFAULT_WIDTH = 640;
|
||||
/**
|
||||
* Default Prezi frame height.
|
||||
*/
|
||||
const DEFAULT_HEIGHT = 480;
|
||||
|
||||
/**
|
||||
* Indicates if the given string is an alphanumeric string.
|
||||
* Note that some special characters are also allowed (-, _ , /, &, ?, =, ;) for the
|
||||
* purpose of checking URIs.
|
||||
* @param {string} unsafeText string to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isAlphanumeric(unsafeText) {
|
||||
return alphanumRegex.test(unsafeText);
|
||||
|
@ -29,12 +43,19 @@ function isAlphanumeric(unsafeText) {
|
|||
|
||||
/**
|
||||
* Returns the presentation id from the given url.
|
||||
* @param {string} url Prezi link
|
||||
* @returns {string} presentation id
|
||||
*/
|
||||
function getPresentationId (url) {
|
||||
let presId = url.substring(url.indexOf("prezi.com/") + 10);
|
||||
return presId.substring(0, presId.indexOf('/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given string is Prezi url.
|
||||
* @param {string} url string to check.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isPreziLink(url) {
|
||||
if (url.indexOf('http://prezi.com/') !== 0 && url.indexOf('https://prezi.com/') !== 0) {
|
||||
return false;
|
||||
|
@ -48,6 +69,9 @@ function isPreziLink(url) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify user that other user if already sharing Prezi.
|
||||
*/
|
||||
function notifyOtherIsSharingPrezi() {
|
||||
messageHandler.openMessageDialog(
|
||||
"dialog.sharePreziTitle",
|
||||
|
@ -55,6 +79,9 @@ function notifyOtherIsSharingPrezi() {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask user if he want to close Prezi he's sharing.
|
||||
*/
|
||||
function proposeToClosePrezi() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
messageHandler.openTwoButtonDialog(
|
||||
|
@ -76,6 +103,10 @@ function proposeToClosePrezi() {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask user for Prezi url to share with others.
|
||||
* Dialog validates client input to allow only Prezi urls.
|
||||
*/
|
||||
function requestPreziLink() {
|
||||
const title = APP.translation.generateTranslationHTML("dialog.sharePreziTitle");
|
||||
const cancelButton = APP.translation.generateTranslationHTML("dialog.Cancel");
|
||||
|
@ -154,6 +185,9 @@ function requestPreziLink() {
|
|||
|
||||
export const PreziContainerType = "prezi";
|
||||
|
||||
/**
|
||||
* Container for Prezi iframe.
|
||||
*/
|
||||
class PreziContainer extends LargeContainer {
|
||||
|
||||
constructor ({preziId, isMy, slide, onSlideChanged}) {
|
||||
|
@ -187,6 +221,10 @@ class PreziContainer extends LargeContainer {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Prezi slide.
|
||||
* @param {number} slide slide to show
|
||||
*/
|
||||
goToSlide (slide) {
|
||||
if (this.preziPlayer.getCurrentStep() === slide) {
|
||||
return;
|
||||
|
@ -204,6 +242,10 @@ class PreziContainer extends LargeContainer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show or hide "reload presentation" button.
|
||||
* @param {boolean} show
|
||||
*/
|
||||
showReloadBtn (show) {
|
||||
this.reloadBtn.css('display', show ? 'inline-block' : 'none');
|
||||
}
|
||||
|
@ -256,6 +298,9 @@ class PreziContainer extends LargeContainer {
|
|||
this.$iframe.width(width).height(height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Prezi frame.
|
||||
*/
|
||||
close () {
|
||||
this.showReloadBtn(false);
|
||||
this.preziPlayer.destroy();
|
||||
|
@ -263,6 +308,9 @@ class PreziContainer extends LargeContainer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manager of Prezi frames.
|
||||
*/
|
||||
export default class PreziManager {
|
||||
constructor (emitter) {
|
||||
this.emitter = emitter;
|
||||
|
@ -282,6 +330,10 @@ export default class PreziManager {
|
|||
return this.userId === APP.conference.localId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is currently sharing.
|
||||
* @param {string} id user id to check for
|
||||
*/
|
||||
isSharing (id) {
|
||||
return this.userId === id;
|
||||
}
|
||||
|
@ -302,6 +354,9 @@ export default class PreziManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload current Prezi frame.
|
||||
*/
|
||||
reloadPresentation () {
|
||||
if (!this.prezi) {
|
||||
return;
|
||||
|
@ -310,6 +365,12 @@ export default class PreziManager {
|
|||
iframe.src = iframe.src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Prezi. Create new Prezi if there is no Prezi yet.
|
||||
* @param {string} id owner id
|
||||
* @param {string} url Prezi url
|
||||
* @param {number} slide slide to show
|
||||
*/
|
||||
showPrezi (id, url, slide) {
|
||||
if (!this.isPresenting) {
|
||||
this.createPrezi(id, url, slide);
|
||||
|
@ -324,6 +385,12 @@ export default class PreziManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new Prezi frame..
|
||||
* @param {string} id owner id
|
||||
* @param {string} url Prezi url
|
||||
* @param {number} slide slide to show
|
||||
*/
|
||||
createPrezi (id, url, slide) {
|
||||
console.log("presentation added", url);
|
||||
|
||||
|
@ -354,6 +421,10 @@ export default class PreziManager {
|
|||
VideoLayout.showLargeVideoContainer(PreziContainerType, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Prezi.
|
||||
* @param {string} id owner id
|
||||
*/
|
||||
removePrezi (id) {
|
||||
if (this.userId !== id) {
|
||||
throw new Error(`cannot close presentation from ${this.userId} instead of ${id}`);
|
||||
|
|
|
@ -1,24 +1,41 @@
|
|||
|
||||
/**
|
||||
* Base class for all Large containers which we can show.
|
||||
*/
|
||||
export default class LargeContainer {
|
||||
|
||||
/**
|
||||
* Show this container.
|
||||
* @returns Promise
|
||||
*/
|
||||
show () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide this container.
|
||||
* @returns Promise
|
||||
*/
|
||||
hide () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize this container.
|
||||
* @param {number} containerWidth available width
|
||||
* @param {number} containerHeight available height
|
||||
* @param {boolean} animate if container should animate it's resize process
|
||||
*/
|
||||
resize (containerWidth, containerHeight, animate) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for "hover in" events.
|
||||
*/
|
||||
onHoverIn (e) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for "hover out" events.
|
||||
*/
|
||||
onHoverOut (e) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,10 @@ const RTCBrowserType = require("../../RTC/RTCBrowserType");
|
|||
|
||||
const avatarSize = interfaceConfig.DOMINANT_SPEAKER_AVATAR_SIZE;
|
||||
|
||||
/**
|
||||
* Get stream id.
|
||||
* @param {JitsiTrack?} stream
|
||||
*/
|
||||
function getStreamId(stream) {
|
||||
if(!stream)
|
||||
return;
|
||||
|
@ -147,6 +151,9 @@ function getDesktopVideoPosition(videoWidth,
|
|||
|
||||
export const VideoContainerType = "video";
|
||||
|
||||
/**
|
||||
* Container for user video.
|
||||
*/
|
||||
class VideoContainer extends LargeContainer {
|
||||
// FIXME: With Temasys we have to re-select everytime
|
||||
get $video () {
|
||||
|
@ -174,6 +181,10 @@ class VideoContainer extends LargeContainer {
|
|||
this.$video.on('play', onPlay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of video element.
|
||||
* @returns {{width, height}}
|
||||
*/
|
||||
getStreamSize () {
|
||||
let video = this.$video[0];
|
||||
return {
|
||||
|
@ -182,6 +193,12 @@ class VideoContainer extends LargeContainer {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate optimal video size for specified container size.
|
||||
* @param {number} containerWidth container width
|
||||
* @param {number} containerHeight container height
|
||||
* @returns {{availableWidth, availableHeight}}
|
||||
*/
|
||||
getVideoSize (containerWidth, containerHeight) {
|
||||
let { width, height } = this.getStreamSize();
|
||||
if (this.stream && this.isScreenSharing()) {
|
||||
|
@ -197,6 +214,15 @@ class VideoContainer extends LargeContainer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate optimal video position (offset for top left corner)
|
||||
* for specified video size and container size.
|
||||
* @param {number} width video width
|
||||
* @param {number} height video height
|
||||
* @param {number} containerWidth container width
|
||||
* @param {number} containerHeight container height
|
||||
* @returns {{horizontalIndent, verticalIndent}}
|
||||
*/
|
||||
getVideoPosition (width, height, containerWidth, containerHeight) {
|
||||
if (this.stream && this.isScreenSharing()) {
|
||||
return getDesktopVideoPosition( width,
|
||||
|
@ -238,6 +264,11 @@ class VideoContainer extends LargeContainer {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update video stream.
|
||||
* @param {JitsiTrack?} stream new stream
|
||||
* @param {string} videoType video type
|
||||
*/
|
||||
setStream (stream, videoType) {
|
||||
this.stream = stream;
|
||||
this.videoType = videoType;
|
||||
|
@ -250,10 +281,18 @@ class VideoContainer extends LargeContainer {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current video stream is screen sharing.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isScreenSharing () {
|
||||
return this.videoType === 'desktop';
|
||||
}
|
||||
|
||||
/**
|
||||
* Show or hide user avatar.
|
||||
* @param {boolean} show
|
||||
*/
|
||||
showAvatar (show) {
|
||||
this.$avatar.css("visibility", show ? "visible" : "hidden");
|
||||
}
|
||||
|
@ -289,7 +328,9 @@ class VideoContainer extends LargeContainer {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Manager for all Large containers.
|
||||
*/
|
||||
export default class LargeVideoManager {
|
||||
constructor () {
|
||||
this.containers = {};
|
||||
|
@ -356,6 +397,13 @@ export default class LargeVideoManager {
|
|||
return this.videoContainer.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update large video.
|
||||
* Switches to large video even if previously other container was visible.
|
||||
* @param {JitsiTrack?} stream new stream
|
||||
* @param {string?} videoType new video type
|
||||
* @returns {Promise}
|
||||
*/
|
||||
updateLargeVideo (smallVideo, videoType, largeVideoUpdatedCallBack) {
|
||||
let id = getStreamId(smallVideo.stream);
|
||||
|
||||
|
@ -380,16 +428,29 @@ export default class LargeVideoManager {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update container size optionally taking side bar size into account.
|
||||
* @param {boolean} isSideBarVisible if side bar is visible.
|
||||
*/
|
||||
updateContainerSize (isSideBarVisible) {
|
||||
this.width = UIUtil.getAvailableVideoWidth(isSideBarVisible);
|
||||
this.height = window.innerHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize Large container of specified type.
|
||||
* @param {string} type type of container which should be resized.
|
||||
* @param {boolean} [animate=false] if resize process should be animated.
|
||||
*/
|
||||
resizeContainer (type, animate = false) {
|
||||
let container = this.getContainer(type);
|
||||
container.resize(this.width, this.height, animate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize all Large containers.
|
||||
* @param {boolean} animate if resize process should be animated.
|
||||
*/
|
||||
resize (animate) {
|
||||
// resize all containers
|
||||
Object.keys(this.containers)
|
||||
|
@ -420,11 +481,20 @@ export default class LargeVideoManager {
|
|||
$("#dominantSpeakerAvatar").attr('src', avatarUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show avatar on Large video container or not.
|
||||
* @param {boolean} show
|
||||
*/
|
||||
showAvatar (show) {
|
||||
show ? this.videoContainer.hide() : this.videoContainer.show();
|
||||
this.videoContainer.showAvatar(show);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add container of specified type.
|
||||
* @param {string} type container type
|
||||
* @param {LargeContainer} container container to add.
|
||||
*/
|
||||
addContainer (type, container) {
|
||||
if (this.containers[type]) {
|
||||
throw new Error(`container of type ${type} already exist`);
|
||||
|
@ -434,6 +504,11 @@ export default class LargeVideoManager {
|
|||
this.resizeContainer(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Large container of specified type.
|
||||
* @param {string} type container type.
|
||||
* @returns {LargeContainer}
|
||||
*/
|
||||
getContainer (type) {
|
||||
let container = this.containers[type];
|
||||
|
||||
|
@ -444,6 +519,10 @@ export default class LargeVideoManager {
|
|||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Large container of specified type.
|
||||
* @param {string} type container type.
|
||||
*/
|
||||
removeContainer (type) {
|
||||
if (!this.containers[type]) {
|
||||
throw new Error(`container of type ${type} doesn't exist`);
|
||||
|
@ -452,6 +531,12 @@ export default class LargeVideoManager {
|
|||
delete this.containers[type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Large container of specified type.
|
||||
* Does nothing if such container is already visible.
|
||||
* @param {string} type container type.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
showContainer (type) {
|
||||
if (this.state === type) {
|
||||
return Promise.resolve();
|
||||
|
|
|
@ -997,7 +997,7 @@ var VideoLayout = {
|
|||
// update current small video and the old one
|
||||
smallVideo.updateView();
|
||||
oldSmallVideo && oldSmallVideo.updateView();
|
||||
});
|
||||
});
|
||||
|
||||
} else if (currentId) {
|
||||
let currentSmallVideo = this.getSmallVideo(currentId);
|
||||
|
|
Loading…
Reference in New Issue