From 47d39ed5cab74f753c2e36bd731012f77b22166e Mon Sep 17 00:00:00 2001 From: hristoterezov Date: Wed, 5 Oct 2016 16:33:09 -0500 Subject: [PATCH 1/2] feat(iframe_api): Implement readyToClose event and hangup command --- conference.js | 110 +++++++++++---------------- doc/api.md | 7 ++ modules/API/API.js | 14 +++- modules/API/external/external_api.js | 8 +- modules/TokenData/TokenData.js | 3 +- 5 files changed, 71 insertions(+), 71 deletions(-) diff --git a/conference.js b/conference.js index 0cc7726462..72b600b468 100644 --- a/conference.js +++ b/conference.js @@ -229,42 +229,10 @@ function disconnectAndShowFeedback(requestFeedback) { APP.UI.hideRingOverLay(); connection.disconnect(); APP.API.notifyConferenceLeft(APP.conference.roomName); - if (requestFeedback) { - return APP.UI.requestFeedback(); - } else { - return Promise.resolve(); - } -} - -/** - * Disconnect from the conference and optionally request user feedback. - * @param {boolean} [requestFeedback=false] if user feedback should be requested - */ -function hangup (requestFeedback = false) { - const errCallback = (err) => { - - // If we want to break out the chain in our error handler, it needs - // to return a rejected promise. In the case of feedback request - // in progress it's important to not redirect to the welcome page - // (see below maybeRedirectToWelcomePage call). - if (err === UIErrors.FEEDBACK_REQUEST_IN_PROGRESS) { - return Promise.reject('Feedback request in progress.'); - } - else { - console.error('Error occurred during hanging up: ', err); - return Promise.resolve(); - } - }; - const disconnect = disconnectAndShowFeedback.bind(null, requestFeedback); - - if (!conferenceLeftListener) - conferenceLeftListener = new ConferenceLeftListener(); - - // Make sure that leave is resolved successfully and the set the handlers - // to be invoked once conference had been left - APP.conference._room.leave() - .then(conferenceLeftListener.setHandler(disconnect, errCallback)) - .catch(errCallback); + let promise = (requestFeedback? + APP.UI.requestFeedback(): Promise.resolve()); + promise.then(() => APP.API.notifyReadyToClose()); + return promise; } /** @@ -276,8 +244,12 @@ class ConferenceLeftListener { /** * Creates ConferenceLeftListener and start listening for conference * failed event. + * @param {Function} handler the function that will be called when + * CONFERENCE_LEFT event is fired. + * @param errCallback */ - constructor() { + constructor(handler) { + this.handler = handler; room.on(ConferenceEvents.CONFERENCE_LEFT, this._handleConferenceLeft.bind(this)); } @@ -287,33 +259,7 @@ class ConferenceLeftListener { * @private */ _handleConferenceLeft() { - this.conferenceLeft = true; - - if (this.handler) - this._handleLeave(); - } - - /** - * Sets the handlers. If we already left the conference invoke them. - * @param handler - * @param errCallback - */ - setHandler (handler, errCallback) { - this.handler = handler; - this.errCallback = errCallback; - - if (this.conferenceLeft) - this._handleLeave(); - } - - /** - * Invokes the handlers. - * @private - */ - _handleLeave() - { this.handler() - .catch(this.errCallback) .then(maybeRedirectToWelcomePage) .catch(function(err){ console.log(err); @@ -1477,16 +1423,16 @@ export default { // call hangup APP.UI.addListener(UIEvents.HANGUP, () => { - hangup(true); + this.hangup(true); }); // logout APP.UI.addListener(UIEvents.LOGOUT, () => { - AuthHandler.logout(room).then(function (url) { + AuthHandler.logout(room).then(url => { if (url) { window.location.href = url; } else { - hangup(true); + this.hangup(true); } }); }); @@ -1827,5 +1773,37 @@ export default { if(room) { room.sendApplicationLog(JSON.stringify({name, value})); } + }, + /** + * Disconnect from the conference and optionally request user feedback. + * @param {boolean} [requestFeedback=false] if user feedback should be + * requested + */ + hangup (requestFeedback = false) { + const errCallback = (err) => { + // If we want to break out the chain in our error handler, it needs + // to return a rejected promise. In the case of feedback request + // in progress it's important to not redirect to the welcome page + // (see below maybeRedirectToWelcomePage call). + if (err === UIErrors.FEEDBACK_REQUEST_IN_PROGRESS) { + return Promise.reject('Feedback request in progress.'); + } + else { + console.error('Error occurred during hanging up: ', err); + return Promise.resolve(); + } + }; + + const disconnect = () => { + return disconnectAndShowFeedback(requestFeedback) + .catch(errCallback); + }; + + if (!conferenceLeftListener) { + conferenceLeftListener + = new ConferenceLeftListener(disconnect, errCallback); + } + + room.leave().catch(errCallback); } }; diff --git a/doc/api.md b/doc/api.md index 91aba67493..22841ca653 100644 --- a/doc/api.md +++ b/doc/api.md @@ -82,6 +82,11 @@ api.executeCommand('toggleContactList', []) api.executeCommand('toggleShareScreen', []) ``` +* **hangup** - Hangups the call. No arguments are required. +``` +api.executeCommand('hangup', []) +``` + You can also execute multiple commands using the method ```executeCommands```. ``` api.executeCommands(commands) @@ -156,6 +161,8 @@ roomName: room //the room name of the conference } ``` +* **readyToClose** - event notification fired when Jitsi Meet is ready to be closed (hangup operations are completed). + You can also add multiple event listeners by using ```addEventListeners```. This method requires one argument of type Object. The object argument must have keys with the names of the events and values the listeners of the events. diff --git a/modules/API/API.js b/modules/API/API.js index 91c4ca622d..07c717ccc4 100644 --- a/modules/API/API.js +++ b/modules/API/API.js @@ -50,7 +50,8 @@ function initCommands() { "toggle-film-strip": APP.UI.toggleFilmStrip, "toggle-chat": APP.UI.toggleChat, "toggle-contact-list": APP.UI.toggleContactList, - "toggle-share-screen": APP.conference.toggleScreenSharing + "toggle-share-screen": APP.conference.toggleScreenSharing, + "video-hangup": () => APP.conference.hangup() }; Object.keys(commands).forEach(function (key) { postis.listen(key, commands[key]); @@ -78,7 +79,8 @@ const events = { "participant-joined": false, "participant-left": false, "video-conference-joined": false, - "video-conference-left": false + "video-conference-left": false, + "video-ready-to-close": false }; /** @@ -243,6 +245,14 @@ export default { triggerEvent("video-conference-left", {roomName: room}); }, + /** + * Notify external application (if API is enabled) that + * we are ready to be closed. + */ + notifyReadyToClose () { + triggerEvent("video-ready-to-close", {}); + }, + /** * Removes the listeners. */ diff --git a/modules/API/external/external_api.js b/modules/API/external/external_api.js index 3074842875..94b28345e6 100644 --- a/modules/API/external/external_api.js +++ b/modules/API/external/external_api.js @@ -33,7 +33,8 @@ var commands = { "toggleFilmStrip": "toggle-film-strip", "toggleChat": "toggle-chat", "toggleContactList": "toggle-contact-list", - "toggleShareScreen": "toggle-share-screen" + "toggleShareScreen": "toggle-share-screen", + "hangup": "video-hangup" }; /** @@ -47,7 +48,8 @@ var events = { "participantJoined": "participant-joined", "participantLeft": "participant-left", "videoConferenceJoined": "video-conference-joined", - "videoConferenceLeft": "video-conference-left" + "videoConferenceLeft": "video-conference-left", + "readyToClose": "video-ready-to-close" }; /** @@ -246,6 +248,8 @@ JitsiMeetExternalAPI.prototype.executeCommands = function(object) { * {{ * roomName: room //the room name of the conference * }} + * readyToClose - all hangup operations are completed and Jitsi Meet is ready + * to be disposed. * @param object */ JitsiMeetExternalAPI.prototype.addEventListeners = function(object) { diff --git a/modules/TokenData/TokenData.js b/modules/TokenData/TokenData.js index 9db4df5832..0ed76fe32d 100644 --- a/modules/TokenData/TokenData.js +++ b/modules/TokenData/TokenData.js @@ -76,7 +76,8 @@ class TokenData{ //External API settings this.externalAPISettings = { forceEnable: true, - enabledEvents: ["video-conference-joined", "video-conference-left"] + enabledEvents: ["video-conference-joined", "video-conference-left", + "video-ready-to-close"] }; this._decode(); // Use JWT param as token if there is not other token set and if the From 7f24d148323d7c74e8ff3a4de3a67fe2b14e678e Mon Sep 17 00:00:00 2001 From: hristoterezov Date: Wed, 5 Oct 2016 20:23:43 -0500 Subject: [PATCH 2/2] refactor(conference.js) hangup functionality --- conference.js | 87 +++++++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 54 deletions(-) diff --git a/conference.js b/conference.js index 72b600b468..11b20cc970 100644 --- a/conference.js +++ b/conference.js @@ -16,7 +16,6 @@ import mediaDeviceHelper from './modules/devices/mediaDeviceHelper'; import {reportError} from './modules/util/helpers'; -import UIErrors from './modules/UI/UIErrors'; import UIUtil from './modules/UI/util/UIUtil'; const ConnectionErrors = JitsiMeetJS.errors.connection; @@ -42,7 +41,7 @@ let DSExternalInstallationInProgress = false; /** * Listens whether conference had been left from local user when we are trying * to navigate away from current page. - * @type {ConferenceLeftListener} + * @type {HangupConferenceLeftListener} */ let conferenceLeftListener = null; @@ -220,50 +219,47 @@ function maybeRedirectToWelcomePage(showThankYou) { }, 3000); } -/** - * Executes connection.disconnect and shows the feedback dialog - * @param {boolean} [requestFeedback=false] if user feedback should be requested - * @returns Promise. - */ -function disconnectAndShowFeedback(requestFeedback) { - APP.UI.hideRingOverLay(); - connection.disconnect(); - APP.API.notifyConferenceLeft(APP.conference.roomName); - let promise = (requestFeedback? - APP.UI.requestFeedback(): Promise.resolve()); - promise.then(() => APP.API.notifyReadyToClose()); - return promise; -} /** - * Listens for CONFERENCE_LEFT event so we can check whether it has finished. - * The handler will be called once the conference had been left or if it - * was already left when we are adding the handler. + * Listens for CONFERENCE_LEFT event after hangup function has been executed. */ -class ConferenceLeftListener { +class HangupConferenceLeftListener { /** - * Creates ConferenceLeftListener and start listening for conference - * failed event. - * @param {Function} handler the function that will be called when - * CONFERENCE_LEFT event is fired. - * @param errCallback + * Creates HangupConferenceLeftListener and start listening for conference + * left event. On CONFERENCE_LEFT event calls should disconnect the user + * and maybe show the feedback dialog. + * @param {boolean} [requestFeedback=false] if user feedback should be + * requested */ - constructor(handler) { - this.handler = handler; + constructor(requestFeedback) { + this.requestFeedback = requestFeedback; room.on(ConferenceEvents.CONFERENCE_LEFT, this._handleConferenceLeft.bind(this)); } /** - * Handles the conference left event, if we have a handler we invoke it. + * Handles the conference left event. * @private */ _handleConferenceLeft() { - this.handler() - .then(maybeRedirectToWelcomePage) - .catch(function(err){ - console.log(err); - }); + this._disconnectAndShowFeedback() + .then(() => { + APP.API.notifyReadyToClose(); + maybeRedirectToWelcomePage(); + }).catch(console.log); + } + + /** + * Executes connection.disconnect and shows the feedback dialog + * @returns Promise. + * @private + */ + _disconnectAndShowFeedback() { + APP.UI.hideRingOverLay(); + connection.disconnect(); + APP.API.notifyConferenceLeft(APP.conference.roomName); + return (this.requestFeedback) ? + APP.UI.requestFeedback() : Promise.resolve(); } } @@ -1780,30 +1776,13 @@ export default { * requested */ hangup (requestFeedback = false) { - const errCallback = (err) => { - // If we want to break out the chain in our error handler, it needs - // to return a rejected promise. In the case of feedback request - // in progress it's important to not redirect to the welcome page - // (see below maybeRedirectToWelcomePage call). - if (err === UIErrors.FEEDBACK_REQUEST_IN_PROGRESS) { - return Promise.reject('Feedback request in progress.'); - } - else { - console.error('Error occurred during hanging up: ', err); - return Promise.resolve(); - } - }; - - const disconnect = () => { - return disconnectAndShowFeedback(requestFeedback) - .catch(errCallback); - }; - if (!conferenceLeftListener) { conferenceLeftListener - = new ConferenceLeftListener(disconnect, errCallback); + = new HangupConferenceLeftListener(requestFeedback); } - room.leave().catch(errCallback); + //FIXME: Do something for the use case when we are not receiving + // CONFERENCE_LEFT for some reason + room.leave(); } };