Merge pull request #13574 from Tainan404/smooth-reconnection-25
Improve data structure to not break on reconnections
This commit is contained in:
commit
542db847ff
92
bigbluebutton-html5/client/collection-mirror-initializer.js
Normal file
92
bigbluebutton-html5/client/collection-mirror-initializer.js
Normal file
@ -0,0 +1,92 @@
|
||||
import AbstractCollection from '/imports/ui/services/LocalCollectionSynchronizer/LocalCollectionSynchronizer';
|
||||
|
||||
// Collections
|
||||
import Presentations from '/imports/api/presentations';
|
||||
import PresentationPods from '/imports/api/presentation-pods';
|
||||
import PresentationUploadToken from '/imports/api/presentation-upload-token';
|
||||
import Screenshare from '/imports/api/screenshare';
|
||||
import UserInfos from '/imports/api/users-infos';
|
||||
import Polls, { CurrentPoll } from '/imports/api/polls';
|
||||
import UsersPersistentData from '/imports/api/users-persistent-data';
|
||||
import UserSettings from '/imports/api/users-settings';
|
||||
import VideoStreams from '/imports/api/video-streams';
|
||||
import VoiceUsers from '/imports/api/voice-users';
|
||||
import WhiteboardMultiUser from '/imports/api/whiteboard-multi-user';
|
||||
import Note from '/imports/api/note';
|
||||
import GroupChat from '/imports/api/group-chat';
|
||||
import ConnectionStatus from '/imports/api/connection-status';
|
||||
import Captions from '/imports/api/captions';
|
||||
import AuthTokenValidation from '/imports/api/auth-token-validation';
|
||||
import Annotations from '/imports/api/annotations';
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import guestUsers from '/imports/api/guest-users';
|
||||
import Meetings, { RecordMeetings, ExternalVideoMeetings, MeetingTimeRemaining } from '/imports/api/meetings';
|
||||
import { UsersTyping } from '/imports/api/group-chat-msg';
|
||||
import Users, { CurrentUser } from '/imports/api/users';
|
||||
import { Slides, SlidePositions } from '/imports/api/slides';
|
||||
|
||||
// Custom Publishers
|
||||
export const localCurrentPollSync = new AbstractCollection(CurrentPoll, CurrentPoll);
|
||||
export const localCurrentUserSync = new AbstractCollection(CurrentUser, CurrentUser);
|
||||
export const localSlidesSync = new AbstractCollection(Slides, Slides);
|
||||
export const localSlidePositionsSync = new AbstractCollection(SlidePositions, SlidePositions);
|
||||
export const localPollsSync = new AbstractCollection(Polls, Polls);
|
||||
export const localPresentationsSync = new AbstractCollection(Presentations, Presentations);
|
||||
export const localPresentationPodsSync = new AbstractCollection(PresentationPods, PresentationPods);
|
||||
export const localPresentationUploadTokenSync = new AbstractCollection(PresentationUploadToken, PresentationUploadToken);
|
||||
export const localScreenshareSync = new AbstractCollection(Screenshare, Screenshare);
|
||||
export const localUserInfosSync = new AbstractCollection(UserInfos, UserInfos);
|
||||
export const localUsersPersistentDataSync = new AbstractCollection(UsersPersistentData, UsersPersistentData);
|
||||
export const localUserSettingsSync = new AbstractCollection(UserSettings, UserSettings);
|
||||
export const localVideoStreamsSync = new AbstractCollection(VideoStreams, VideoStreams);
|
||||
export const localVoiceUsersSync = new AbstractCollection(VoiceUsers, VoiceUsers);
|
||||
export const localWhiteboardMultiUserSync = new AbstractCollection(WhiteboardMultiUser, WhiteboardMultiUser);
|
||||
export const localNoteSync = new AbstractCollection(Note, Note);
|
||||
export const localGroupChatSync = new AbstractCollection(GroupChat, GroupChat);
|
||||
export const localConnectionStatusSync = new AbstractCollection(ConnectionStatus, ConnectionStatus);
|
||||
export const localCaptionsSync = new AbstractCollection(Captions, Captions);
|
||||
export const localAuthTokenValidationSync = new AbstractCollection(AuthTokenValidation, AuthTokenValidation);
|
||||
export const localAnnotationsSync = new AbstractCollection(Annotations, Annotations);
|
||||
export const localRecordMeetingsSync = new AbstractCollection(RecordMeetings, RecordMeetings);
|
||||
export const localExternalVideoMeetingsSync = new AbstractCollection(ExternalVideoMeetings, ExternalVideoMeetings);
|
||||
export const localMeetingTimeRemainingSync = new AbstractCollection(MeetingTimeRemaining, MeetingTimeRemaining);
|
||||
export const localUsersTypingSync = new AbstractCollection(UsersTyping, UsersTyping);
|
||||
export const localBreakoutsSync = new AbstractCollection(Breakouts, Breakouts);
|
||||
export const localGuestUsersSync = new AbstractCollection(guestUsers, guestUsers);
|
||||
export const localMeetingsSync = new AbstractCollection(Meetings, Meetings);
|
||||
export const localUsersSync = new AbstractCollection(Users, Users);
|
||||
|
||||
const collectionMirrorInitializer = () => {
|
||||
localCurrentPollSync.setupListeners();
|
||||
localCurrentUserSync.setupListeners();
|
||||
localSlidesSync.setupListeners();
|
||||
localSlidePositionsSync.setupListeners();
|
||||
localPollsSync.setupListeners();
|
||||
localPresentationsSync.setupListeners();
|
||||
localPresentationPodsSync.setupListeners();
|
||||
localPresentationUploadTokenSync.setupListeners();
|
||||
localScreenshareSync.setupListeners();
|
||||
localUserInfosSync.setupListeners();
|
||||
localUsersPersistentDataSync.setupListeners();
|
||||
localUserSettingsSync.setupListeners();
|
||||
localVideoStreamsSync.setupListeners();
|
||||
localVoiceUsersSync.setupListeners();
|
||||
localWhiteboardMultiUserSync.setupListeners();
|
||||
localNoteSync.setupListeners();
|
||||
localGroupChatSync.setupListeners();
|
||||
localConnectionStatusSync.setupListeners();
|
||||
localCaptionsSync.setupListeners();
|
||||
localAuthTokenValidationSync.setupListeners();
|
||||
localAnnotationsSync.setupListeners();
|
||||
localRecordMeetingsSync.setupListeners();
|
||||
localExternalVideoMeetingsSync.setupListeners();
|
||||
localMeetingTimeRemainingSync.setupListeners();
|
||||
localUsersTypingSync.setupListeners();
|
||||
localBreakoutsSync.setupListeners();
|
||||
localGuestUsersSync.setupListeners();
|
||||
localMeetingsSync.setupListeners();
|
||||
localUsersSync.setupListeners();
|
||||
};
|
||||
|
||||
export default collectionMirrorInitializer;
|
||||
// const localUsersSync = new AbstractCollection(CurrentUser, CurrentUser);
|
@ -17,8 +17,6 @@
|
||||
*/
|
||||
/* eslint no-unused-vars: 0 */
|
||||
|
||||
import '../imports/ui/services/collection-hooks/collection-hooks';
|
||||
|
||||
import React from 'react';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { render } from 'react-dom';
|
||||
@ -32,16 +30,15 @@ import ContextProviders from '/imports/ui/components/context-providers/component
|
||||
import ChatAdapter from '/imports/ui/components/components-data/chat-context/adapter';
|
||||
import UsersAdapter from '/imports/ui/components/components-data/users-context/adapter';
|
||||
import GroupChatAdapter from '/imports/ui/components/components-data/group-chat-context/adapter';
|
||||
import { liveDataEventBrokerInitializer } from '/imports/ui/services/LiveDataEventBroker/LiveDataEventBroker';
|
||||
|
||||
import '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import '/imports/ui/local-collections/breakouts-collection/breakouts';
|
||||
import '/imports/ui/local-collections/guest-users-collection/guest-users';
|
||||
import '/imports/ui/local-collections/users-collection/users';
|
||||
import collectionMirrorInitializer from './collection-mirror-initializer';
|
||||
|
||||
import('/imports/api/audio/client/bridge/bridge-whitelist').catch(() => {
|
||||
// bridge loading
|
||||
});
|
||||
|
||||
collectionMirrorInitializer();
|
||||
liveDataEventBrokerInitializer();
|
||||
Meteor.startup(() => {
|
||||
// Logs all uncaught exceptions to the client logger
|
||||
window.addEventListener('error', (e) => {
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const Annotations = new Mongo.Collection('annotations');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const Annotations = new Mongo.Collection('annotations', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the annotations (Total):
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const AuthTokenValidation = new Mongo.Collection('auth-token-validation');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const AuthTokenValidation = new Mongo.Collection('auth-token-validation', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
AuthTokenValidation._ensureIndex({ meetingId: 1, userId: 1 });
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const Breakouts = new Mongo.Collection('breakouts');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const Breakouts = new Mongo.Collection('breakouts', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the breakouts:
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const Captions = new Mongo.Collection('captions');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const Captions = new Mongo.Collection('captions', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
Captions._ensureIndex({ meetingId: 1, padId: 1 });
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const ConnectionStatus = new Mongo.Collection('connection-status');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const ConnectionStatus = new Mongo.Collection('connection-status', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
ConnectionStatus._ensureIndex({ meetingId: 1, userId: 1 });
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const GroupChatMsg = new Mongo.Collection('group-chat-msg');
|
||||
const UsersTyping = new Mongo.Collection('users-typing');
|
||||
const UsersTyping = new Mongo.Collection('users-typing', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
GroupChatMsg._ensureIndex({ meetingId: 1, chatId: 1 });
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const GroupChat = new Mongo.Collection('group-chat');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const GroupChat = new Mongo.Collection('group-chat', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
GroupChat._ensureIndex({
|
||||
|
@ -1,5 +1,9 @@
|
||||
import { Mongo } from 'meteor/mongo';
|
||||
|
||||
const GuestUsers = new Mongo.Collection('guestUsers');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const GuestUsers = new Mongo.Collection('guestUsers', collectionOptions);
|
||||
|
||||
export default GuestUsers;
|
||||
|
@ -1,9 +1,13 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const Meetings = new Mongo.Collection('meetings');
|
||||
const RecordMeetings = new Mongo.Collection('record-meetings');
|
||||
const ExternalVideoMeetings = new Mongo.Collection('external-video-meetings');
|
||||
const MeetingTimeRemaining = new Mongo.Collection('meeting-time-remaining');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const Meetings = new Mongo.Collection('meetings', collectionOptions);
|
||||
const RecordMeetings = new Mongo.Collection('record-meetings', collectionOptions);
|
||||
const ExternalVideoMeetings = new Mongo.Collection('external-video-meetings', collectionOptions);
|
||||
const MeetingTimeRemaining = new Mongo.Collection('meeting-time-remaining', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the meetings:
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const Note = new Mongo.Collection('note');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const Note = new Mongo.Collection('note', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
Note._ensureIndex({ meetingId: 1, noteId: 1 });
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const Polls = new Mongo.Collection('polls');
|
||||
export const CurrentPoll = new Mongo.Collection('current-poll');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const Polls = new Mongo.Collection('polls', collectionOptions);
|
||||
export const CurrentPoll = new Mongo.Collection('current-poll', { connection: null });
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// We can have just one active poll per meeting
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const PresentationPods = new Mongo.Collection('presentation-pods');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const PresentationPods = new Mongo.Collection('presentation-pods', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the presentation pods:
|
||||
|
@ -1,3 +1,7 @@
|
||||
const PresentationUploadToken = new Mongo.Collection('presentation-upload-token');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const PresentationUploadToken = new Mongo.Collection('presentation-upload-token', collectionOptions);
|
||||
|
||||
export default PresentationUploadToken;
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const Presentations = new Mongo.Collection('presentations');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const Presentations = new Mongo.Collection('presentations', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the presentations:
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const Screenshare = new Mongo.Collection('screenshare');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const Screenshare = new Mongo.Collection('screenshare', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the screenshare:
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const Slides = new Mongo.Collection('slides');
|
||||
const SlidePositions = new Mongo.Collection('slide-positions');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const Slides = new Mongo.Collection('slides', collectionOptions);
|
||||
const SlidePositions = new Mongo.Collection('slide-positions', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the slides:
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const UserInfos = new Mongo.Collection('users-infos');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const UserInfos = new Mongo.Collection('users-infos', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
UserInfos._ensureIndex({ meetingId: 1, userId: 1 });
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const UsersPersistentData = new Mongo.Collection('users-persistent-data');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const UsersPersistentData = new Mongo.Collection('users-persistent-data', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
UsersPersistentData._ensureIndex({ meetingId: 1, userId: 1 });
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const UserSettings = new Mongo.Collection('users-settings');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const UserSettings = new Mongo.Collection('users-settings', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
UserSettings._ensureIndex({
|
||||
|
@ -1,13 +1,17 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const Users = new Mongo.Collection('users');
|
||||
export const CurrentUser = new Mongo.Collection('current-user');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const Users = new Mongo.Collection('users', collectionOptions);
|
||||
export const CurrentUser = new Mongo.Collection('current-user', { connection: null });
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the users:
|
||||
// 1. meetingId
|
||||
// 2. meetingId, userId
|
||||
|
||||
// { connection: Meteor.isClient ? null : true }
|
||||
Users._ensureIndex({ meetingId: 1, userId: 1 });
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const VideoStreams = new Mongo.Collection('video-streams');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const VideoStreams = new Mongo.Collection('video-streams', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the video users:
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const VoiceUsers = new Mongo.Collection('voiceUsers');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const VoiceUsers = new Mongo.Collection('voiceUsers', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the voice users:
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
const WhiteboardMultiUser = new Mongo.Collection('whiteboard-multi-user');
|
||||
const collectionOptions = Meteor.isClient ? {
|
||||
connection: null,
|
||||
} : {};
|
||||
|
||||
const WhiteboardMultiUser = new Mongo.Collection('whiteboard-multi-user', collectionOptions);
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// types of queries for the whiteboard-multi-user:
|
||||
|
@ -8,14 +8,14 @@ import MeetingEnded from '/imports/ui/components/meeting-ended/component';
|
||||
import LoadingScreen from '/imports/ui/components/loading-screen/component';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
import logger from '/imports/startup/client/logger';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import { Session } from 'meteor/session';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { RecordMeetings } from '../../api/meetings';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import AppService from '/imports/ui/components/app/service';
|
||||
import Breakouts from '/imports/ui/local-collections/breakouts-collection/breakouts';
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import AudioService from '/imports/ui/components/audio/service';
|
||||
import { notify } from '/imports/ui/services/notification';
|
||||
import deviceInfo from '/imports/utils/deviceInfo';
|
||||
@ -218,6 +218,7 @@ class Base extends Component {
|
||||
if (approved && loading) this.updateLoadingState(false);
|
||||
|
||||
if (prevProps.ejected || ejected) {
|
||||
console.log(' if (prevProps.ejected || ejected) {');
|
||||
Session.set('codeError', '403');
|
||||
Session.set('isMeetingEnded', true);
|
||||
}
|
||||
@ -227,6 +228,10 @@ class Base extends Component {
|
||||
this.setMeetingExisted(false);
|
||||
}
|
||||
|
||||
if ((prevProps.isMeteorConnected !== isMeteorConnected) && !isMeteorConnected) {
|
||||
Session.set('globalIgnoreDeletes', true);
|
||||
}
|
||||
|
||||
const enabled = HTML.classList.contains('animationsEnabled');
|
||||
const disabled = HTML.classList.contains('animationsDisabled');
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Breakouts from '/imports/ui/local-collections/breakouts-collection/breakouts';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import { getVideoUrl } from '/imports/ui/components/external-video-player/service';
|
||||
|
||||
const USER_CONFIG = Meteor.settings.public.user;
|
||||
|
@ -3,8 +3,8 @@ import { withTracker } from 'meteor/react-meteor-data';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Users from '/imports/api/users';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import { notify } from '/imports/ui/services/notification';
|
||||
import CaptionsContainer from '/imports/ui/components/captions/container';
|
||||
import CaptionsService from '/imports/ui/components/captions/service';
|
||||
@ -13,11 +13,11 @@ import deviceInfo from '/imports/utils/deviceInfo';
|
||||
import UserInfos from '/imports/api/users-infos';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
import MediaService from '/imports/ui/components/media/service';
|
||||
import {
|
||||
layoutSelect,
|
||||
layoutSelectInput,
|
||||
layoutSelectOutput,
|
||||
layoutDispatch
|
||||
import {
|
||||
layoutSelect,
|
||||
layoutSelectInput,
|
||||
layoutSelectOutput,
|
||||
layoutDispatch,
|
||||
} from '../layout/context';
|
||||
|
||||
import {
|
||||
@ -119,10 +119,6 @@ const currentUserEmoji = (currentUser) => (currentUser
|
||||
);
|
||||
|
||||
export default injectIntl(withModalMounter(withTracker(({ intl, baseControls }) => {
|
||||
if (Auth.connectionID !== Meteor.connection._lastSessionId) {
|
||||
endMeeting('403');
|
||||
}
|
||||
|
||||
Users.find({ userId: Auth.userID, meetingId: Auth.meetingID }).observe({
|
||||
removed() {
|
||||
endMeeting('403');
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Breakouts from '/imports/ui/local-collections/breakouts-collection/breakouts';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
import Auth from '/imports/ui/services/auth/index';
|
||||
import deviceInfo from '/imports/utils/deviceInfo';
|
||||
|
@ -4,7 +4,7 @@ import { withModalMounter } from '/imports/ui/components/modal/service';
|
||||
import browserInfo from '/imports/utils/browserInfo';
|
||||
import getFromUserSettings from '/imports/ui/services/users-settings';
|
||||
import AudioModal from './component';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import lockContextContainer from '/imports/ui/components/lock-viewers/context/container';
|
||||
import AudioError from '/imports/ui/services/audio-manager/error-codes';
|
||||
|
@ -5,7 +5,7 @@ import { Session } from 'meteor/session';
|
||||
import { withModalMounter } from '/imports/ui/components/modal/service';
|
||||
import { injectIntl, defineMessages } from 'react-intl';
|
||||
import _ from 'lodash';
|
||||
import Breakouts from '/imports/ui/local-collections/breakouts-collection/breakouts';
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import AppService from '/imports/ui/components/app/service';
|
||||
import { notify } from '/imports/ui/services/notification';
|
||||
import getFromUserSettings from '/imports/ui/services/users-settings';
|
||||
|
@ -1,8 +1,8 @@
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { debounce, throttle } from 'lodash';
|
||||
import AudioManager from '/imports/ui/services/audio-manager';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import VoiceUsers from '/imports/api/voice-users';
|
||||
import logger from '/imports/startup/client/logger';
|
||||
|
@ -17,7 +17,7 @@ class AuthenticatedHandler extends Component {
|
||||
}
|
||||
|
||||
static updateStatus(status, lastStatus) {
|
||||
return status.retryCount > 0 && lastStatus !== STATUS_CONNECTING ? status.status : lastStatus;
|
||||
return lastStatus !== STATUS_CONNECTING ? status.status : lastStatus;
|
||||
}
|
||||
|
||||
static addReconnectObservable() {
|
||||
@ -27,6 +27,7 @@ class AuthenticatedHandler extends Component {
|
||||
lastStatus = AuthenticatedHandler.updateStatus(Meteor.status(), lastStatus);
|
||||
|
||||
if (AuthenticatedHandler.shouldAuthenticate(Meteor.status(), lastStatus)) {
|
||||
Session.set('userWillAuth', true);
|
||||
Auth.authenticate(true);
|
||||
lastStatus = Meteor.status().status;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Breakouts from '/imports/ui/local-collections/breakouts-collection/breakouts';
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import breakoutService from '/imports/ui/components/breakout-room/service';
|
||||
|
@ -1,9 +1,9 @@
|
||||
import Breakouts from '/imports/ui/local-collections/breakouts-collection/breakouts';
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import { MeetingTimeRemaining } from '/imports/api/meetings';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import UserListService from '/imports/ui/components/user-list/service';
|
||||
import fp from 'lodash/fp';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import _ from 'lodash';
|
||||
import Captions from '/imports/api/captions';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import { UsersContext } from '/imports/ui/components/components-data/users-context/context';
|
||||
import ChatDropdown from './component';
|
||||
|
||||
|
@ -2,8 +2,8 @@ import React from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { UsersTyping } from '/imports/api/group-chat-msg';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Users from '/imports/api/users';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import TypingIndicator from './component';
|
||||
|
||||
const CHAT_CONFIG = Meteor.settings.public.chat;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Users from '/imports/api/users';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import GroupChat from '/imports/api/group-chat';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import UnreadMessages from '/imports/ui/services/unread-messages';
|
||||
|
@ -5,7 +5,7 @@ import { UsersContext } from '../users-context/context';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import ChatLogger from '/imports/ui/components/chat/chat-logger/ChatLogger';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import CollectionEventsBroker from '/imports/ui/services/collection-hooks-callbacks/collection-hooks-callbacks';
|
||||
import CollectionEventsBroker from '/imports/ui/services/LiveDataEventBroker/LiveDataEventBroker';
|
||||
|
||||
let prevUserData = {};
|
||||
let currentUserData = {};
|
||||
|
@ -3,7 +3,7 @@ import React, {
|
||||
useReducer,
|
||||
} from 'react';
|
||||
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Storage from '/imports/ui/services/storage/session';
|
||||
import ChatLogger from '/imports/ui/components/chat/chat-logger/ChatLogger';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { CurrentUser } from '/imports/api/users';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import UsersPersistentData from '/imports/api/users-persistent-data';
|
||||
import { UsersContext, ACTIONS } from './context';
|
||||
import ChatLogger from '/imports/ui/components/chat/chat-logger/ChatLogger';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { defineMessages } from 'react-intl';
|
||||
import ConnectionStatus from '/imports/api/connection-status';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import UsersPersistentData from '/imports/api/users-persistent-data';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
|
||||
const getMeetingTitle = () => {
|
||||
const meeting = Meetings.findOne({
|
||||
|
@ -24,6 +24,7 @@ class JoinHandler extends Component {
|
||||
|
||||
this.state = {
|
||||
joined: false,
|
||||
hasAlreadyJoined: false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -38,8 +39,8 @@ class JoinHandler extends Component {
|
||||
connected,
|
||||
status,
|
||||
} = Meteor.status();
|
||||
|
||||
if (status === 'connecting') {
|
||||
const { hasAlreadyJoined } = this.state;
|
||||
if (status === 'connecting' && !hasAlreadyJoined) {
|
||||
this.setState({ joined: false });
|
||||
}
|
||||
|
||||
@ -83,6 +84,7 @@ class JoinHandler extends Component {
|
||||
}
|
||||
|
||||
async fetchToken() {
|
||||
const { hasAlreadyJoined } = this.state;
|
||||
if (!this._isMounted) return;
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
@ -94,7 +96,9 @@ class JoinHandler extends Component {
|
||||
}
|
||||
|
||||
// Old credentials stored in memory were being used when joining a new meeting
|
||||
Auth.clearCredentials();
|
||||
if (!hasAlreadyJoined) {
|
||||
Auth.clearCredentials();
|
||||
}
|
||||
const logUserInfo = () => {
|
||||
const userInfo = window.navigator;
|
||||
|
||||
@ -215,7 +219,10 @@ class JoinHandler extends Component {
|
||||
},
|
||||
}, 'User faced an error on main.joinRouteHandler.');
|
||||
}
|
||||
this.setState({ joined: true });
|
||||
this.setState({
|
||||
joined: true,
|
||||
hasAlreadyJoined: true,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Meetings from '../../../api/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
|
||||
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import { withModalMounter } from '/imports/ui/components/modal/service';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import LockViewersComponent from './component';
|
||||
import { updateLockSettings, updateWebcamsOnlyForModerator } from './service';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { LockStruct } from './context';
|
||||
import { withUsersConsumer } from '/imports/ui/components/components-data/users-context/context';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import LockViewersNotifyComponent from './component';
|
||||
|
||||
|
@ -2,7 +2,7 @@ import Presentations from '/imports/api/presentations';
|
||||
import { isVideoBroadcasting } from '/imports/ui/components/screenshare/service';
|
||||
import { getVideoUrl } from '/imports/ui/components/external-video-player/service';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
import getFromUserSettings from '/imports/ui/services/users-settings';
|
||||
import { ACTIONS } from '../layout/enums';
|
||||
|
@ -10,8 +10,8 @@ import logoutRouteHandler from '/imports/utils/logoutRouteHandler';
|
||||
import Rating from './rating/component';
|
||||
import Styled from './styles';
|
||||
import logger from '/imports/startup/client/logger';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Users from '/imports/api/users';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import AudioManager from '/imports/ui/services/audio-manager';
|
||||
import { meetingIsBreakout } from '/imports/ui/components/app/service';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { withModalMounter } from '/imports/ui/components/modal/service';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import getFromUserSettings from '/imports/ui/services/users-settings';
|
||||
import userListService from '/imports/ui/components/user-list/service';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import RecordMeetings from '/imports/api/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
|
||||
const processOutsideToggleRecording = (e) => {
|
||||
switch (e.data) {
|
||||
@ -9,7 +9,7 @@ const processOutsideToggleRecording = (e) => {
|
||||
break;
|
||||
}
|
||||
case 'c_recording_status': {
|
||||
const recordingState = (RecordMeetings.findOne({ meetingId: Auth.meetingID })).recording;
|
||||
const recordingState = (Meetings.findOne({ meetingId: Auth.meetingID })).recording;
|
||||
const recordingMessage = recordingState ? 'recordingStarted' : 'recordingStopped';
|
||||
this.window.parent.postMessage({ response: recordingMessage }, '*');
|
||||
break;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Users from '/imports/api/users';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Note from '/imports/api/note';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
|
@ -5,7 +5,7 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||
import _ from 'lodash';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { MeetingTimeRemaining } from '/imports/api/meetings';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import BreakoutRemainingTime from '/imports/ui/components/breakout-room/breakout-remaining-time/container';
|
||||
import Styled from './styles';
|
||||
import { layoutSelectInput, layoutDispatch } from '../layout/context';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { CurrentPoll } from '/imports/api/polls';
|
||||
import caseInsensitiveReducer from '/imports/utils/caseInsensitiveReducer';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import PollingService from './service';
|
||||
import PollService from '/imports/ui/components/poll/service';
|
||||
|
@ -11,7 +11,7 @@ import Presentation from '/imports/ui/components/presentation/component';
|
||||
import PresentationToolbarService from './presentation-toolbar/service';
|
||||
import { UsersContext } from '../components-data/users-context/context';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import getFromUserSettings from '/imports/ui/services/users-settings';
|
||||
import {
|
||||
layoutSelect,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Cursor from '/imports/ui/components/cursor/service';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
|
||||
const getCurrentCursor = (cursorId) => {
|
||||
const cursor = Cursor.findOne({ _id: cursorId });
|
||||
|
@ -4,7 +4,7 @@ import BridgeService from '/imports/api/screenshare/client/bridge/service';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
import logger from '/imports/startup/client/logger';
|
||||
import { stopWatching } from '/imports/ui/components/external-video-player/service';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import UserListService from '/imports/ui/components/user-list/service';
|
||||
import AudioService from '/imports/ui/components/audio/service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
import { notify } from '/imports/ui/services/notification';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
import { UsersContext } from '/imports/ui/components/components-data/users-context/context';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
|
@ -4,12 +4,15 @@ import Auth from '/imports/ui/services/auth';
|
||||
import logger from '/imports/startup/client/logger';
|
||||
import GroupChat from '/imports/api/group-chat';
|
||||
import Annotations from '/imports/api/annotations';
|
||||
import Users, { localUsersSync } from '/imports/ui/local-collections/users-collection/users';
|
||||
import { localBreakoutsSync } from '/imports/ui/local-collections/breakouts-collection/breakouts';
|
||||
import { localGuestUsersSync } from '/imports/ui/local-collections/guest-users-collection/guest-users';
|
||||
import { localMeetingsSync } from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Users from '/imports/api/users';
|
||||
import AnnotationsTextService from '/imports/ui/components/whiteboard/annotations/text/service';
|
||||
import { Annotations as AnnotationsLocal } from '/imports/ui/components/whiteboard/service';
|
||||
import {
|
||||
localBreakoutsSync,
|
||||
localGuestUsersSync,
|
||||
localMeetingsSync,
|
||||
localUsersSync,
|
||||
} from '/client/collection-mirror-initializer';
|
||||
import SubscriptionRegistry, { subscriptionReactivity } from '../../services/subscription-registry/subscriptionRegistry';
|
||||
|
||||
const CHAT_CONFIG = Meteor.settings.public.chat;
|
||||
@ -37,6 +40,7 @@ class Subscriptions extends Component {
|
||||
Session.set('subscriptionsReady', true);
|
||||
const event = new Event(EVENT_NAME_SUBSCRIPTION_READY);
|
||||
window.dispatchEvent(event);
|
||||
Session.set('globalIgnoreDeletes', false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,6 +53,12 @@ class Subscriptions extends Component {
|
||||
export default withTracker(() => {
|
||||
const { credentials } = Auth;
|
||||
const { meetingId, requesterUserId } = credentials;
|
||||
const userWillAuth = Session.get('userWillAuth');
|
||||
// This if exist because when a unauth user try to subscribe to a publisher
|
||||
// it returns a empty collection to the subscription
|
||||
// and not rerun when the user is authenticated
|
||||
if (userWillAuth) return {};
|
||||
|
||||
if (Session.get('codeError')) {
|
||||
return {
|
||||
subscriptionsReady: true,
|
||||
@ -90,11 +100,11 @@ export default withTracker(() => {
|
||||
if (oldRole === 'VIEWER' && currentUser?.role === 'MODERATOR') {
|
||||
// let this withTracker re-execute when a subscription is stopped
|
||||
subscriptionReactivity.depend();
|
||||
// Prevent data being removed by subscription stop
|
||||
localBreakoutsSync.setIgnoreDeletes(true);
|
||||
localGuestUsersSync.setIgnoreDeletes(true);
|
||||
localMeetingsSync.setIgnoreDeletes(true);
|
||||
localUsersSync.setIgnoreDeletes(true);
|
||||
// Prevent data being removed by subscription stop
|
||||
// stop role dependent subscriptions
|
||||
[
|
||||
SubscriptionRegistry.getSubscription('meetings'),
|
||||
|
@ -1,8 +1,8 @@
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import VoiceUsers from '/imports/api/voice-users';
|
||||
import GroupChat from '/imports/api/group-chat';
|
||||
import Breakouts from '/imports/ui/local-collections/breakouts-collection/breakouts';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Storage from '/imports/ui/services/storage/session';
|
||||
import { EMOJI_STATUSES } from '/imports/utils/statuses';
|
||||
|
@ -4,7 +4,7 @@ import { Session } from 'meteor/session';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Storage from '/imports/ui/services/storage/session';
|
||||
import UserContent from './component';
|
||||
import GuestUsers from '/imports/ui/local-collections/guest-users-collection/guest-users';
|
||||
import GuestUsers from '/imports/api/guest-users';
|
||||
import { layoutSelectInput, layoutDispatch } from '../../layout/context';
|
||||
import { UsersContext } from '/imports/ui/components/components-data/users-context/context';
|
||||
import WaitingUsersService from '/imports/ui/components/waiting-users/service';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import BreakoutService from '/imports/ui/components/breakout-room/service';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import UserListItem from './component';
|
||||
import UserListService from '/imports/ui/components/user-list/service';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import PropTypes from 'prop-types';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import ActionsBarService from '/imports/ui/components/actions-bar/service';
|
||||
import LearningDashboardService from '/imports/ui/components/learning-dashboard/service';
|
||||
import UserListService from '/imports/ui/components/user-list/service';
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { withModalMounter } from '/imports/ui/components/modal/service';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Users from '/imports/api/users';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Service from './service';
|
||||
import VideoPreview from './component';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Users from '/imports/api/users/';
|
||||
import VideoStreams from '/imports/api/video-streams';
|
||||
|
@ -2,8 +2,8 @@ import { Tracker } from 'meteor/tracker';
|
||||
import { Session } from 'meteor/session';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Users from '/imports/api/users';
|
||||
import VideoStreams from '/imports/api/video-streams';
|
||||
import UserListService from '/imports/ui/components/user-list/service';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import GuestUsers from '/imports/ui/local-collections/guest-users-collection/guest-users';
|
||||
import GuestUsers from '/imports/api/guest-users';
|
||||
import { UsersContext } from '/imports/ui/components/components-data/users-context/context';
|
||||
import WaitingComponent from './component';
|
||||
import { layoutSelectInput, layoutDispatch } from '../../layout/context';
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import GuestUsers from '/imports/ui/local-collections/guest-users-collection/guest-users';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import GuestUsers from '/imports/api/guest-users';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Service from './service';
|
||||
import WaitingComponent from './component';
|
||||
import { layoutDispatch } from '../layout/context';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
|
||||
|
@ -5,7 +5,7 @@ import MediaService, { getSwapLayout, shouldEnableSwapLayout } from '/imports/ui
|
||||
import ReactiveAnnotationService from './service';
|
||||
import ReactiveAnnotation from './component';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import getFromUserSettings from '/imports/ui/services/users-settings';
|
||||
|
||||
const ROLE_VIEWER = Meteor.settings.public.user.role_viewer;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Storage from '/imports/ui/services/storage/session';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
|
||||
const DRAW_SETTINGS = 'drawSettings';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import WhiteboardMultiUser from '/imports/api/whiteboard-multi-user';
|
||||
import addAnnotationQuery from '/imports/api/annotations/addAnnotation';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import Storage from '/imports/ui/services/storage/session';
|
||||
import Users from '/imports/ui/local-collections/users-collection/users';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import getFromUserSettings from '/imports/ui/services/users-settings';
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import AbstractCollection from '/imports/ui/local-collections/abstract-collection/abstract-collection';
|
||||
|
||||
const localBreakouts = new Mongo.Collection('local-breakouts', { connection: null });
|
||||
|
||||
export const localBreakoutsSync = new AbstractCollection(Breakouts, localBreakouts);
|
||||
|
||||
export default localBreakouts;
|
@ -1,8 +0,0 @@
|
||||
import guestUsers from '/imports/api/guest-users';
|
||||
import AbstractCollection from '/imports/ui/local-collections/abstract-collection/abstract-collection';
|
||||
|
||||
const localGuestUsers = new Mongo.Collection('local-guest-users', { connection: null });
|
||||
|
||||
export const localGuestUsersSync = new AbstractCollection(guestUsers, localGuestUsers);
|
||||
|
||||
export default localGuestUsers;
|
@ -1,8 +0,0 @@
|
||||
import Meetings from '/imports/api/meetings';
|
||||
import AbstractCollection from '/imports/ui/local-collections/abstract-collection/abstract-collection';
|
||||
|
||||
const localMeetings = new Mongo.Collection('local-meetings', { connection: null });
|
||||
|
||||
export const localMeetingsSync = new AbstractCollection(Meetings, localMeetings);
|
||||
|
||||
export default localMeetings;
|
@ -1,8 +0,0 @@
|
||||
import Users from '/imports/api/users';
|
||||
import AbstractCollection from '/imports/ui/local-collections/abstract-collection/abstract-collection';
|
||||
|
||||
const localUsers = new Mongo.Collection('local-users', { connection: null });
|
||||
|
||||
export const localUsersSync = new AbstractCollection(Users, localUsers);
|
||||
|
||||
export default localUsers;
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
This class allows other parts of the code to get called when an event (insert/update/delete) occurs in a server-side published cursor.
|
||||
|
||||
In implementation time it was created for the publisher ( meteor live data hooks ) notify the listener ( LocalCollectionSynchronizer ) about the events.
|
||||
|
||||
*/
|
||||
class CollectionEventsBroker {
|
||||
static getKey(msg, updates) {
|
||||
// the msg.msg has the collection event,
|
||||
// see the collection hooks event object for more information
|
||||
return `/${msg.collection}/${msg.msg}/`;
|
||||
// TODO: also process the updates object
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.callbacks = {};
|
||||
}
|
||||
|
||||
addListener(collection, event, callback) {
|
||||
try {
|
||||
const index = CollectionEventsBroker.getKey({ collection, msg: event });
|
||||
const TheresCallback = this.callbacks[index];
|
||||
if (TheresCallback) {
|
||||
throw new Error('There is already an associated callback for this event');
|
||||
}
|
||||
this.callbacks[index] = callback;
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dispatchEvent(msg, updates) {
|
||||
try {
|
||||
const msgIndex = CollectionEventsBroker.getKey(msg, updates);
|
||||
const { fields } = msg;
|
||||
const callback = this.callbacks[msgIndex];
|
||||
if (callback) {
|
||||
callback({ ...fields, referenceId: msg.id });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
// TODO: also process the updates object
|
||||
}
|
||||
}
|
||||
|
||||
const collectionEventsBroker = new CollectionEventsBroker();
|
||||
|
||||
export const liveDataEventBrokerInitializer = () => {
|
||||
Meteor.connection._processOneDataMessage = function (msg, updates) {
|
||||
try {
|
||||
const messageType = msg.msg;
|
||||
let col = null;
|
||||
if (msg.collection && msg.collection.indexOf('stream-cursor') === -1) {
|
||||
col = Meteor.connection._stores[msg.collection]?._getCollection();
|
||||
}
|
||||
collectionEventsBroker.dispatchEvent(msg, updates);
|
||||
// msg is one of ['added', 'changed', 'removed', 'ready', 'updated']
|
||||
if (messageType === 'added') {
|
||||
if (!col || !col.onAdded || col.onAdded(msg, updates)) {
|
||||
this._process_added(msg, updates);
|
||||
}
|
||||
} else if (messageType === 'changed') {
|
||||
if (!col || !col.onChanged || col.onChanged(msg, updates)) {
|
||||
this._process_changed(msg, updates);
|
||||
}
|
||||
} else if (messageType === 'removed') {
|
||||
if (!col || !col.onRemoved || col.onRemoved(msg, updates)) {
|
||||
this._process_removed(msg, updates);
|
||||
}
|
||||
} else if (messageType === 'ready') {
|
||||
if (!col || !col.onReady || col.onReady(msg, updates)) {
|
||||
this._process_ready(msg, updates);
|
||||
}
|
||||
} else if (messageType === 'updated') {
|
||||
if (!col || !col.onUpdated || col.onUpdated(msg, updates)) {
|
||||
this._process_updated(msg, updates);
|
||||
}
|
||||
} else if (messageType === 'nosub') {
|
||||
// ignore this
|
||||
} else {
|
||||
Meteor._debug('discarding unknown livedata data message type', msg);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error when calling hooks', err);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default collectionEventsBroker;
|
@ -1,7 +1,13 @@
|
||||
import SubscriptionRegistry from '/imports/ui/services/subscription-registry/subscriptionRegistry';
|
||||
import CollectionEventsBroker from '/imports/ui/services/collection-hooks-callbacks/collection-hooks-callbacks';
|
||||
import CollectionEventsBroker from '/imports/ui/services/LiveDataEventBroker/LiveDataEventBroker';
|
||||
|
||||
class AbstractCollection {
|
||||
/*
|
||||
This class connects a local collection with the LiveDataEventBroker, propagating the changes of a server-side published cursor to a local collection.
|
||||
|
||||
It also guarantee that in case of a reconnection or a re-subscription, the data is only removed after subscription is ready, avoiding the situation of missing data during re-synchronization.
|
||||
*/
|
||||
|
||||
class LocalCollectionSynchronizer {
|
||||
constructor(serverCollection, localCollection, options = {}) {
|
||||
this.serverCollection = serverCollection;
|
||||
this.localCollection = localCollection;
|
||||
@ -9,21 +15,24 @@ class AbstractCollection {
|
||||
this.lastSubscriptionId = '';
|
||||
this.options = options;
|
||||
this.ignoreDeletes = false;
|
||||
this.createObserver();
|
||||
}
|
||||
|
||||
/*
|
||||
This method allow to enable/disable the ignoreDeletes feature.
|
||||
When enabled, system will skip the received deletes ( not apply on local collection ).
|
||||
Don't panic: these deletes will be processed when the subscription gets ready - see removeOldSubscriptionData method.
|
||||
*/
|
||||
setIgnoreDeletes(value) {
|
||||
this.ignoreDeletes = value;
|
||||
}
|
||||
|
||||
// Replicates remote collection to local collection ( avoiding cleanup during the forced resync )
|
||||
createObserver() {
|
||||
setupListeners() {
|
||||
const self = this;
|
||||
|
||||
const addedCallback = function (item) {
|
||||
const subscription = SubscriptionRegistry
|
||||
.getSubscription(self.serverCollection._name);
|
||||
|
||||
if (item.id === 'publication-stop-marker' && item.stopped) {
|
||||
self.ignoreDeletes = true;
|
||||
return;
|
||||
@ -34,8 +43,9 @@ class AbstractCollection {
|
||||
const wasEmpty = self.lastSubscriptionId === '';
|
||||
self.lastSubscriptionId = subscription.subscriptionId;
|
||||
if (!wasEmpty) {
|
||||
self.PollForReadyStatus(() => {
|
||||
self.callWhenSubscriptionReady(() => {
|
||||
self.ignoreDeletes = false;
|
||||
Session.set('globalIgnoreDeletes', false);
|
||||
self.removeOldSubscriptionData();
|
||||
});
|
||||
}
|
||||
@ -73,7 +83,8 @@ class AbstractCollection {
|
||||
};
|
||||
|
||||
const removedCallback = function (item) {
|
||||
if (self.ignoreDeletes) {
|
||||
const globalIgnoreDeletes = Session.get('globalIgnoreDeletes');
|
||||
if (self.ignoreDeletes || globalIgnoreDeletes) {
|
||||
return;
|
||||
}
|
||||
const selector = { referenceId: item.referenceId };
|
||||
@ -86,7 +97,10 @@ class AbstractCollection {
|
||||
CollectionEventsBroker.addListener(this.serverCollection._name, 'removed', removedCallback);
|
||||
}
|
||||
|
||||
PollForReadyStatus(func) {
|
||||
/*
|
||||
This method calls the function received as parameter when the subscription gets ready.
|
||||
*/
|
||||
callWhenSubscriptionReady(func) {
|
||||
const temp = (res) => {
|
||||
setTimeout(() => {
|
||||
const subscription = SubscriptionRegistry.getSubscription(this.serverCollection._name);
|
||||
@ -103,6 +117,9 @@ class AbstractCollection {
|
||||
return tempPromise;
|
||||
}
|
||||
|
||||
/*
|
||||
This method removes data from previous subscriptions after the current one is ready.
|
||||
*/
|
||||
removeOldSubscriptionData() {
|
||||
const subscription = SubscriptionRegistry.getSubscription(this.serverCollection._name);
|
||||
|
||||
@ -122,4 +139,4 @@ class AbstractCollection {
|
||||
}
|
||||
}
|
||||
|
||||
export default AbstractCollection;
|
||||
export default LocalCollectionSynchronizer;
|
@ -244,6 +244,7 @@ class Auth {
|
||||
initAnnotationsStreamListener();
|
||||
clearTimeout(validationTimeout);
|
||||
this.connectionID = authenticationTokenValidation.connectionId;
|
||||
Session.set('userWillAuth', false);
|
||||
setTimeout(() => resolve(true), 100);
|
||||
break;
|
||||
default:
|
||||
|
@ -1,43 +0,0 @@
|
||||
class CollectionEventsBroker {
|
||||
static getKey(msg, updates) {
|
||||
// the msg.msg has the collection event,
|
||||
// see the collection hooks event object for more information
|
||||
return `/${msg.collection}/${msg.msg}/`;
|
||||
// TODO: also process the updates object
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.callbacks = {};
|
||||
}
|
||||
|
||||
addListener(collection, event, callback) {
|
||||
try {
|
||||
const index = CollectionEventsBroker.getKey({ collection, msg: event });
|
||||
const TheresCallback = this.callbacks[index];
|
||||
if (TheresCallback) {
|
||||
throw new Error('There is already an associated callback for this event');
|
||||
}
|
||||
this.callbacks[index] = callback;
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dispatchEvent(msg, updates) {
|
||||
try {
|
||||
const msgIndex = CollectionEventsBroker.getKey(msg, updates);
|
||||
const { fields } = msg;
|
||||
const callback = this.callbacks[msgIndex];
|
||||
if (callback) {
|
||||
callback({ ...fields, referenceId: msg.id });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
// TODO: also process the updates object
|
||||
}
|
||||
}
|
||||
|
||||
export default new CollectionEventsBroker();
|
@ -1,41 +0,0 @@
|
||||
import CollectionEventsBroker from '/imports/ui/services/collection-hooks-callbacks/collection-hooks-callbacks';
|
||||
|
||||
Meteor.connection._processOneDataMessage = function (msg, updates) {
|
||||
try {
|
||||
const messageType = msg.msg;
|
||||
|
||||
let col = null;
|
||||
if (msg.collection && msg.collection.indexOf('stream-cursor') === -1) {
|
||||
col = Meteor.connection._stores[msg.collection]?._getCollection();
|
||||
}
|
||||
CollectionEventsBroker.dispatchEvent(msg, updates);
|
||||
// msg is one of ['added', 'changed', 'removed', 'ready', 'updated']
|
||||
if (messageType === 'added') {
|
||||
if (!col || !col.onAdded || col.onAdded(msg, updates)) {
|
||||
this._process_added(msg, updates);
|
||||
}
|
||||
} else if (messageType === 'changed') {
|
||||
if (!col || !col.onChanged || col.onChanged(msg, updates)) {
|
||||
this._process_changed(msg, updates);
|
||||
}
|
||||
} else if (messageType === 'removed') {
|
||||
if (!col || !col.onRemoved || col.onRemoved(msg, updates)) {
|
||||
this._process_removed(msg, updates);
|
||||
}
|
||||
} else if (messageType === 'ready') {
|
||||
if (!col || !col.onReady || col.onReady(msg, updates)) {
|
||||
this._process_ready(msg, updates);
|
||||
}
|
||||
} else if (messageType === 'updated') {
|
||||
if (!col || !col.onUpdated || col.onUpdated(msg, updates)) {
|
||||
this._process_updated(msg, updates);
|
||||
}
|
||||
} else if (messageType === 'nosub') {
|
||||
// ignore this
|
||||
} else {
|
||||
Meteor._debug('discarding unknown livedata data message type', msg);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error when calling hooks', err);
|
||||
}
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Meetings from '/imports/ui/local-collections/meetings-collection/meetings';
|
||||
import Meetings from '/imports/api/meetings';
|
||||
|
||||
export default function getFromMeetingSettings(setting, defaultValue) {
|
||||
const prop = Meetings.findOne(
|
||||
|
Loading…
Reference in New Issue
Block a user