From 4f210c0594541aa71c8b43b30e43732d77e50acf Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 22 Mar 2019 12:14:30 -0300 Subject: [PATCH 1/6] fix multiple calls after video call --- app/videobridge/client/views/videoFlexTab.js | 152 ++++++++++-------- app/videobridge/constants.js | 4 + .../server/methods/jitsiSetTimeout.js | 13 +- 3 files changed, 92 insertions(+), 77 deletions(-) create mode 100644 app/videobridge/constants.js diff --git a/app/videobridge/client/views/videoFlexTab.js b/app/videobridge/client/views/videoFlexTab.js index d1c1dc097f56..550149a7cb4b 100644 --- a/app/videobridge/client/views/videoFlexTab.js +++ b/app/videobridge/client/views/videoFlexTab.js @@ -4,6 +4,9 @@ import { Template } from 'meteor/templating'; import { settings } from '../../../settings'; import { modal, TabBar } from '../../../ui-utils'; import { t } from '../../../utils'; +import { Users, Rooms } from '../../../models'; + +import CONSTANTS from '../../constants'; Template.videoFlexTab.helpers({ openInNewWindow() { @@ -14,11 +17,14 @@ Template.videoFlexTab.helpers({ Template.videoFlexTab.onCreated(function() { this.tabBar = Template.currentData().tabBar; }); +Template.videoFlexTab.onDestroyed(function() { + return this.stop && this.stop(); +}); Template.videoFlexTab.onRendered(function() { this.api = null; - let timeOut = null; + const rid = Session.get('openedRoom'); const width = 'auto'; const height = 500; @@ -40,6 +46,30 @@ Template.videoFlexTab.onRendered(function() { TabBar.updateButton('video', { class: '' }); }; + const stop = () => { + if (this.timeOut) { + Meteor.defer(() => this.api && this.api.dispose()); + clearInterval(this.timeOut); + } + }; + + this.stop = stop; + + const start = () => { + + const update = () => { + const { jitsiTimeout } = Rooms.findOne({ _id: rid }, { fields: { jitsiTimeout: 1 }, reactive: false }); + + if (jitsiTimeout && (new Date() - new Date(jitsiTimeout) + CONSTANTS.TIMEOUT < CONSTANTS.HEARTBEAT / 2)) { + return; + } + return Meteor.status().connected && Meteor.call('jitsi:updateTimeout', rid); + }; + update(); + this.timeOut = Meteor.setInterval(update, CONSTANTS.HEARTBEAT); + TabBar.updateButton('video', { class: 'red' }); + }; + modal.open({ title: t('Video_Conference'), text: t('Start_video_call'), @@ -54,84 +84,64 @@ Template.videoFlexTab.onRendered(function() { } this.timeout = null; this.autorun(() => { - if (settings.get('Jitsi_Enabled')) { - if (this.tabBar.getState() === 'opened') { - const roomId = Session.get('openedRoom'); + if (!settings.get('Jitsi_Enabled')) { + return closePanel(); + } - const domain = settings.get('Jitsi_Domain'); - const jitsiRoom = settings.get('Jitsi_URL_Room_Prefix') + settings.get('uniqueID') + roomId; - const noSsl = !settings.get('Jitsi_SSL'); + if (this.tabBar.getState() !== 'opened') { + TabBar.updateButton('video', { class: '' }); + return stop(); + } - if (jitsiRoomActive !== null && jitsiRoomActive !== jitsiRoom) { - jitsiRoomActive = null; + const domain = settings.get('Jitsi_Domain'); + const jitsiRoom = settings.get('Jitsi_URL_Room_Prefix') + settings.get('uniqueID') + rid; + const noSsl = !settings.get('Jitsi_SSL'); - closePanel(); + if (jitsiRoomActive !== null && jitsiRoomActive !== jitsiRoom) { + jitsiRoomActive = null; - // Clean up and stop updating timeout. - Meteor.defer(() => this.api && this.api.dispose()); - if (timeOut) { - clearInterval(timeOut); - } - } else { - jitsiRoomActive = jitsiRoom; - - TabBar.updateButton('video', { class: 'red' }); - - if (settings.get('Jitsi_Open_New_Window')) { - Meteor.call('jitsi:updateTimeout', roomId); - - timeOut = Meteor.setInterval(() => Meteor.call('jitsi:updateTimeout', roomId), 10 * 1000); - const newWindow = window.open(`${ (noSsl ? 'http://' : 'https://') + domain }/${ jitsiRoom }`, jitsiRoom); - const closeInterval = setInterval(() => { - if (newWindow.closed !== false) { - closePanel(); - clearInterval(closeInterval); - clearInterval(timeOut); - } - }, 300); - if (newWindow) { - newWindow.focus(); - } - - - // Lets make sure its loaded before we try to show it. - } else if (typeof JitsiMeetExternalAPI !== 'undefined') { - - // Keep it from showing duplicates when re-evaluated on variable change. - if (!$('[id^=jitsiConference]').length) { - this.api = new JitsiMeetExternalAPI(domain, jitsiRoom, width, height, this.$('.video-container').get(0), configOverwrite, interfaceConfigOverwrite, noSsl); - - /* - * Hack to send after frame is loaded. - * postMessage converts to events in the jitsi meet iframe. - * For some reason those aren't working right. - */ - Meteor.setTimeout(() => { - this.api.executeCommand('displayName', [Meteor.user().name]); - }, 5000); - - Meteor.call('jitsi:updateTimeout', roomId); - - timeOut = Meteor.setInterval(() => Meteor.call('jitsi:updateTimeout', roomId), 10 * 1000); - } - - // Execute any commands that might be reactive. Like name changing. - this.api && this.api.executeCommand('displayName', [Meteor.user().name]); + closePanel(); + + return stop(); + } + + jitsiRoomActive = jitsiRoom; + + if (settings.get('Jitsi_Open_New_Window')) { + start(); + const newWindow = window.open(`${ (noSsl ? 'http://' : 'https://') + domain }/${ jitsiRoom }`, jitsiRoom); + if (newWindow) { + const closeInterval = setInterval(() => { + if (newWindow.closed === false) { + return; } - } - } else { - TabBar.updateButton('video', { class: '' }); - - // Clean up and stop updating timeout. - if (timeOut) { - Meteor.defer(() => this.api && this.api.dispose()); - clearInterval(timeOut); - } + closePanel(); + stop(); + clearInterval(closeInterval); + }, 300); + return newWindow.focus(); } - + // Lets make sure its loaded before we try to show it. } + if (typeof JitsiMeetExternalAPI !== 'undefined') { + // Keep it from showing duplicates when re-evaluated on variable change. + const name = Users.findOne(Meteor.userId(), { fields: { name: 1 } }); + if (!$('[id^=jitsiConference]').length) { + this.api = new JitsiMeetExternalAPI(domain, jitsiRoom, width, height, this.$('.video-container').get(0), configOverwrite, interfaceConfigOverwrite, noSsl); + + /* + * Hack to send after frame is loaded. + * postMessage converts to events in the jitsi meet iframe. + * For some reason those aren't working right. + */ + Meteor.setTimeout(() => this.api.executeCommand('displayName', [name]), 5000); + return start(); + } + + // Execute any commands that might be reactive. Like name changing. + this.api && this.api.executeCommand('displayName', [name]); + } }); }); }); - diff --git a/app/videobridge/constants.js b/app/videobridge/constants.js new file mode 100644 index 000000000000..4e0f2d5be290 --- /dev/null +++ b/app/videobridge/constants.js @@ -0,0 +1,4 @@ +export default { + HEARTBEAT: 35 * 1000 / 2, + TIMEOUT: 35 * 1000, +}; diff --git a/app/videobridge/server/methods/jitsiSetTimeout.js b/app/videobridge/server/methods/jitsiSetTimeout.js index 4b1c4c22017c..0b0378cf8831 100644 --- a/app/videobridge/server/methods/jitsiSetTimeout.js +++ b/app/videobridge/server/methods/jitsiSetTimeout.js @@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { TAPi18n } from 'meteor/tap:i18n'; import { Rooms, Messages } from '../../../models'; import { callbacks } from '../../../callbacks'; +import CONSTANTS from '../../constants'; Meteor.methods({ 'jitsi:updateTimeout': (rid) => { @@ -15,14 +16,16 @@ Meteor.methods({ const jitsiTimeout = new Date((room && room.jitsiTimeout) || currentTime).getTime(); - if (jitsiTimeout <= currentTime) { - Rooms.setJitsiTimeout(rid, new Date(currentTime + 35 * 1000)); + if (currentTime > jitsiTimeout - CONSTANTS.TIMEOUT / 2) { + Rooms.setJitsiTimeout(rid, new Date(currentTime + CONSTANTS.TIMEOUT)); + } + + if (currentTime > jitsiTimeout) { const message = Messages.createWithTypeRoomIdMessageAndUser('jitsi_call_started', rid, '', Meteor.user(), { actionLinks : [ { icon: 'icon-videocam', label: TAPi18n.__('Click_to_join'), method_id: 'joinJitsiCall', params: '' }, ], }); - const room = Rooms.findOneById(rid); message.msg = TAPi18n.__('Started_a_video_call'); message.mentions = [ { @@ -30,9 +33,7 @@ Meteor.methods({ username:'here', }, ]; - callbacks.run('afterSaveMessage', message, room); - } else if ((jitsiTimeout - currentTime) / 1000 <= 15) { - Rooms.setJitsiTimeout(rid, new Date(jitsiTimeout + 25 * 1000)); + callbacks.run('afterSaveMessage', message, { ...room, jitsiTimeout: currentTime + CONSTANTS.TIMEOUT }); } }, }); From ef17fae59f93ef625c7ac672b8e2d477de407a89 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 26 Mar 2019 02:11:11 -0300 Subject: [PATCH 2/6] fix review --- app/videobridge/client/views/videoFlexTab.js | 12 ++++++------ app/videobridge/constants.js | 7 +++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/app/videobridge/client/views/videoFlexTab.js b/app/videobridge/client/views/videoFlexTab.js index 550149a7cb4b..547c59fb51ca 100644 --- a/app/videobridge/client/views/videoFlexTab.js +++ b/app/videobridge/client/views/videoFlexTab.js @@ -6,7 +6,7 @@ import { modal, TabBar } from '../../../ui-utils'; import { t } from '../../../utils'; import { Users, Rooms } from '../../../models'; -import CONSTANTS from '../../constants'; +import * as CONSTANTS from '../../constants'; Template.videoFlexTab.helpers({ openInNewWindow() { @@ -47,9 +47,9 @@ Template.videoFlexTab.onRendered(function() { }; const stop = () => { - if (this.timeOut) { + if (this.intervalHandler) { Meteor.defer(() => this.api && this.api.dispose()); - clearInterval(this.timeOut); + clearInterval(this.intervalHandler); } }; @@ -60,13 +60,13 @@ Template.videoFlexTab.onRendered(function() { const update = () => { const { jitsiTimeout } = Rooms.findOne({ _id: rid }, { fields: { jitsiTimeout: 1 }, reactive: false }); - if (jitsiTimeout && (new Date() - new Date(jitsiTimeout) + CONSTANTS.TIMEOUT < CONSTANTS.HEARTBEAT / 2)) { + if (jitsiTimeout && (new Date() - new Date(jitsiTimeout) + CONSTANTS.TIMEOUT < CONSTANTS.DEBOUNCE)) { return; } return Meteor.status().connected && Meteor.call('jitsi:updateTimeout', rid); }; update(); - this.timeOut = Meteor.setInterval(update, CONSTANTS.HEARTBEAT); + this.intervalHandler = Meteor.setInterval(update, CONSTANTS.HEARTBEAT); TabBar.updateButton('video', { class: 'red' }); }; @@ -82,7 +82,7 @@ Template.videoFlexTab.onRendered(function() { if (!dismiss) { return closePanel(); } - this.timeout = null; + this.intervalHandler = null; this.autorun(() => { if (!settings.get('Jitsi_Enabled')) { return closePanel(); diff --git a/app/videobridge/constants.js b/app/videobridge/constants.js index 4e0f2d5be290..14cec201fbcb 100644 --- a/app/videobridge/constants.js +++ b/app/videobridge/constants.js @@ -1,4 +1,3 @@ -export default { - HEARTBEAT: 35 * 1000 / 2, - TIMEOUT: 35 * 1000, -}; +export const TIMEOUT = 30 * 1000; +export const HEARTBEAT = TIMEOUT / 3; +export const DEBOUNCE = HEARTBEAT / 2; From bef3faf23e1d62430541eb743b70c66a4b4cea2f Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 26 Mar 2019 15:33:17 -0300 Subject: [PATCH 3/6] Update app/videobridge/client/views/videoFlexTab.js Co-Authored-By: ggazzo --- app/videobridge/client/views/videoFlexTab.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/videobridge/client/views/videoFlexTab.js b/app/videobridge/client/views/videoFlexTab.js index d7b6b230a62d..85063ef59e48 100644 --- a/app/videobridge/client/views/videoFlexTab.js +++ b/app/videobridge/client/views/videoFlexTab.js @@ -5,7 +5,6 @@ import { settings } from '../../../settings'; import { modal, TabBar } from '../../../ui-utils'; import { t } from '../../../utils'; import { Users, Rooms } from '../../../models'; - import * as CONSTANTS from '../../constants'; Template.videoFlexTab.helpers({ From 5bf149d32408e0d8398450afe3ed5e00aa64e13d Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 26 Mar 2019 15:33:26 -0300 Subject: [PATCH 4/6] Update app/videobridge/client/views/videoFlexTab.js Co-Authored-By: ggazzo --- app/videobridge/client/views/videoFlexTab.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/videobridge/client/views/videoFlexTab.js b/app/videobridge/client/views/videoFlexTab.js index 85063ef59e48..8abfa4d9db36 100644 --- a/app/videobridge/client/views/videoFlexTab.js +++ b/app/videobridge/client/views/videoFlexTab.js @@ -55,7 +55,6 @@ Template.videoFlexTab.onRendered(function() { this.stop = stop; const start = () => { - const update = () => { const { jitsiTimeout } = Rooms.findOne({ _id: rid }, { fields: { jitsiTimeout: 1 }, reactive: false }); From 96dbca58482edb6b8c5d29cb2e77b9d21c22bd09 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 26 Mar 2019 15:33:37 -0300 Subject: [PATCH 5/6] Update app/videobridge/server/methods/jitsiSetTimeout.js Co-Authored-By: ggazzo --- app/videobridge/server/methods/jitsiSetTimeout.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/videobridge/server/methods/jitsiSetTimeout.js b/app/videobridge/server/methods/jitsiSetTimeout.js index 0b0378cf8831..1c5863c27127 100644 --- a/app/videobridge/server/methods/jitsiSetTimeout.js +++ b/app/videobridge/server/methods/jitsiSetTimeout.js @@ -2,7 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { TAPi18n } from 'meteor/tap:i18n'; import { Rooms, Messages } from '../../../models'; import { callbacks } from '../../../callbacks'; -import CONSTANTS from '../../constants'; +import * as CONSTANTS from '../../constants'; Meteor.methods({ 'jitsi:updateTimeout': (rid) => { From 34be392c6f173761e39aac278678247aa9584cf7 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 26 Mar 2019 16:34:29 -0300 Subject: [PATCH 6/6] fix unset jitsiTimeout --- app/videobridge/client/views/videoFlexTab.js | 2 -- app/videobridge/server/methods/jitsiSetTimeout.js | 15 +++++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/videobridge/client/views/videoFlexTab.js b/app/videobridge/client/views/videoFlexTab.js index d7b6b230a62d..8abfa4d9db36 100644 --- a/app/videobridge/client/views/videoFlexTab.js +++ b/app/videobridge/client/views/videoFlexTab.js @@ -5,7 +5,6 @@ import { settings } from '../../../settings'; import { modal, TabBar } from '../../../ui-utils'; import { t } from '../../../utils'; import { Users, Rooms } from '../../../models'; - import * as CONSTANTS from '../../constants'; Template.videoFlexTab.helpers({ @@ -56,7 +55,6 @@ Template.videoFlexTab.onRendered(function() { this.stop = stop; const start = () => { - const update = () => { const { jitsiTimeout } = Rooms.findOne({ _id: rid }, { fields: { jitsiTimeout: 1 }, reactive: false }); diff --git a/app/videobridge/server/methods/jitsiSetTimeout.js b/app/videobridge/server/methods/jitsiSetTimeout.js index 0b0378cf8831..763940e55c45 100644 --- a/app/videobridge/server/methods/jitsiSetTimeout.js +++ b/app/videobridge/server/methods/jitsiSetTimeout.js @@ -1,8 +1,10 @@ import { Meteor } from 'meteor/meteor'; import { TAPi18n } from 'meteor/tap:i18n'; + import { Rooms, Messages } from '../../../models'; import { callbacks } from '../../../callbacks'; -import CONSTANTS from '../../constants'; +import * as CONSTANTS from '../../constants'; +import { canAccessRoom } from '../../../authorization/server'; Meteor.methods({ 'jitsi:updateTimeout': (rid) => { @@ -12,15 +14,20 @@ Meteor.methods({ } const room = Rooms.findOneById(rid); + + if (!canAccessRoom(room, Meteor.user())) { + throw new Meteor.Error('error-not-allowerd', 'not allowed', { method: 'jitsi:updateTimeout' }); + } + const currentTime = new Date().getTime(); - const jitsiTimeout = new Date((room && room.jitsiTimeout) || currentTime).getTime(); + const jitsiTimeout = room.jitsiTimeout && new Date(room.jitsiTimeout).getTime(); - if (currentTime > jitsiTimeout - CONSTANTS.TIMEOUT / 2) { + if (!jitsiTimeout || currentTime > jitsiTimeout - CONSTANTS.TIMEOUT / 2) { Rooms.setJitsiTimeout(rid, new Date(currentTime + CONSTANTS.TIMEOUT)); } - if (currentTime > jitsiTimeout) { + if (!jitsiTimeout || currentTime > jitsiTimeout) { const message = Messages.createWithTypeRoomIdMessageAndUser('jitsi_call_started', rid, '', Meteor.user(), { actionLinks : [ { icon: 'icon-videocam', label: TAPi18n.__('Click_to_join'), method_id: 'joinJitsiCall', params: '' },