@webex/plugin-meetings 3.12.0-next.35 → 3.12.0-next.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,6 +15,7 @@ var _triggerProxy = _interopRequireDefault(require("../common/events/trigger-pro
15
15
  var _constants2 = _interopRequireDefault(require("../metrics/constants"));
16
16
  var _metrics = _interopRequireDefault(require("../metrics"));
17
17
  var _meetings = require("./meetings.types");
18
+ var _types = require("../locus-info/types");
18
19
  /* globals window */
19
20
 
20
21
  /**
@@ -274,6 +275,15 @@ MeetingsUtil.getThisDevice = function (newLocus, deviceUrl) {
274
275
  return null;
275
276
  };
276
277
 
278
+ /**
279
+ * Checks if the fullState indicates the meeting has fully ended (not just a breakout move).
280
+ * @param {Object} fullState locus fullState data
281
+ * @returns {boolean}
282
+ */
283
+ MeetingsUtil.isWholeMeetingEnded = function (fullState) {
284
+ return fullState.state === _constants.LOCUS.STATE.INACTIVE && fullState.endMeetingReason !== _types.EndMeetingReason.breakoutEnded;
285
+ };
286
+
277
287
  /**
278
288
  * Checks if the self state in a locus indicates a breakout move or breakout end.
279
289
  * Returns true when:
@@ -285,7 +295,7 @@ MeetingsUtil.getThisDevice = function (newLocus, deviceUrl) {
285
295
  MeetingsUtil.isSelfMovedOrBreakoutEnded = function (locus) {
286
296
  var _locus$self, _locus$self2, _locus$fullState, _locus$fullState2;
287
297
  var isSelfLeftMoved = (locus === null || locus === void 0 ? void 0 : (_locus$self = locus.self) === null || _locus$self === void 0 ? void 0 : _locus$self.state) === _constants._LEFT_ && (locus === null || locus === void 0 ? void 0 : (_locus$self2 = locus.self) === null || _locus$self2 === void 0 ? void 0 : _locus$self2.reason) === _constants._MOVED_;
288
- var isBreakoutEnded = (locus === null || locus === void 0 ? void 0 : (_locus$fullState = locus.fullState) === null || _locus$fullState === void 0 ? void 0 : _locus$fullState.state) === _constants.LOCUS.STATE.INACTIVE && (locus === null || locus === void 0 ? void 0 : (_locus$fullState2 = locus.fullState) === null || _locus$fullState2 === void 0 ? void 0 : _locus$fullState2.endMeetingReason) === _constants._BREAKOUT_ENDED_;
298
+ var isBreakoutEnded = (locus === null || locus === void 0 ? void 0 : (_locus$fullState = locus.fullState) === null || _locus$fullState === void 0 ? void 0 : _locus$fullState.state) === _constants.LOCUS.STATE.INACTIVE && (locus === null || locus === void 0 ? void 0 : (_locus$fullState2 = locus.fullState) === null || _locus$fullState2 === void 0 ? void 0 : _locus$fullState2.endMeetingReason) === _types.EndMeetingReason.breakoutEnded;
289
299
  return isSelfLeftMoved || isBreakoutEnded;
290
300
  };
291
301
 
@@ -1 +1 @@
1
- {"version":3,"names":["_constants","require","_loggerProxy","_interopRequireDefault","_triggerProxy","_constants2","_metrics","_meetings","MeetingsUtil","getMeetingAddedType","type","DESTINATION_TYPE","LOCUS_ID","_INCOMING_","_CREATED_","handleRoapMercury","envelope","meetingCollection","data","eventType","LOCUSEVENT","MESSAGE_ROAP","meeting","getByKey","MEETING_KEY","CORRELATION_ID","correlationId","_data$message","message","seq","messageType","tieBreaker","errorType","errorCause","Metrics","sendBehavioralMetric","BEHAVIORAL_METRICS","ROAP_MERCURY_EVENT_RECEIVED","correlation_id","message_type","error_type","error_cause","ROAP","ROAP_TYPES","TURN_DISCOVERY_RESPONSE","roap","turnDiscovery","handleTurnDiscoveryResponse","_data$message$sdps","roapMessage","sdp","sdps","length","undefined","roapMessageReceived","getMediaServer","mediaServer","split","find","line","startsWith","shift","replace","toLowerCase","_unused","getMediaServerIp","mediaServerIp","_sdp$split$find$match","match","trim","_unused2","getCorrelationIdForDevice","deviceUrl","locusSelf","devices","foundDevice","device","url","parseDefaultSiteFromMeetingPreferences","userPreferences","_userPreferences$site","result","sites","defaultSite","site","default","siteUrl","hasH264Codec","_asyncToGenerator2","_regenerator","mark","_callee","hasCodec","pc","offer","_t","wrap","_context","prev","next","window","RTCPeerConnection","createOffer","offerToReceiveVideo","sent","close","LoggerProxy","logger","warn","abrupt","stop","checkH264Support","_checkH264Support","_callee2","options","_this","_ref2","firstChecked","disableNotifications","delay","maxDuration","shouldTrigger","shouldStopChecking","_context2","_now","Trigger","trigger","file","function","EVENT_TRIGGERS","MEDIA_CODEC_LOADED","log","error","MEDIA_CODEC_MISSING","setTimeout","timestamp","call","_x","apply","arguments","getThisDevice","newLocus","_newLocus$self","_newLocus$self$device","self","isSelfMovedOrBreakoutEnded","locus","_locus$self","_locus$self2","_locus$fullState","_locus$fullState2","isSelfLeftMoved","state","_LEFT_","reason","_MOVED_","isBreakoutEnded","fullState","LOCUS","STATE","INACTIVE","endMeetingReason","_BREAKOUT_ENDED_","joinedOnThisDevice","thisDevice","_JOINED_","isBreakoutLocusDTO","_newLocus$controls","_newLocus$controls$br","_newLocus$info","controls","breakout","sessionType","BREAKOUTS","SESSION_TYPES","BREAKOUT","info","isBreakout","isValidBreakoutLocus","_locus$fullState3","_locus$self3","inActiveStatus","isLocusAsBreakout","selfJoined","isMainAssociatedWithBreakout","mainLocus","breakoutLocus","_mainLocus$controls","_mainLocus$controls$b","_mainLocus$controls2","_mainLocus$controls2$","_breakoutLocus$contro","_breakoutLocus$contro2","_breakoutLocus$self","_MeetingsUtil$getThis","_MeetingsUtil$getThis2","replaceInfo","replaces","locusUrl","_default","exports"],"sources":["util.ts"],"sourcesContent":["/* globals window */\n\nimport {\n _CREATED_,\n _INCOMING_,\n _JOINED_,\n _LEFT_,\n DESTINATION_TYPE,\n _MOVED_,\n _BREAKOUT_ENDED_,\n BREAKOUTS,\n EVENT_TRIGGERS,\n LOCUS,\n LOCUSEVENT,\n ROAP,\n} from '../constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport Trigger from '../common/events/trigger-proxy';\nimport BEHAVIORAL_METRICS from '../metrics/constants';\nimport Metrics from '../metrics';\nimport {MEETING_KEY} from './meetings.types';\n\n/**\n * Meetings Media Codec Missing Event\n * Emitted when H.264 codec is not\n * found in the browser.\n * @event media:codec:missing\n * @instance\n * @memberof MeetingsUtil\n */\n\n/**\n * Meetings Media Codec Loaded Event\n * Emitted when H.264 codec has been\n * loaded in the browser.\n * @event media:codec:loaded\n * @instance\n * @memberof MeetingsUtil\n */\n\nconst MeetingsUtil: any = {};\n\nMeetingsUtil.getMeetingAddedType = (type: DESTINATION_TYPE) =>\n type === DESTINATION_TYPE.LOCUS_ID ? _INCOMING_ : _CREATED_;\n\nMeetingsUtil.handleRoapMercury = (envelope, meetingCollection) => {\n const {data} = envelope;\n const {eventType} = data;\n\n if (eventType === LOCUSEVENT.MESSAGE_ROAP) {\n const meeting = meetingCollection.getByKey(MEETING_KEY.CORRELATION_ID, data.correlationId);\n\n if (meeting) {\n const {seq, messageType, tieBreaker, errorType, errorCause} = data.message;\n\n Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ROAP_MERCURY_EVENT_RECEIVED, {\n correlation_id: data.correlationId,\n seq,\n message_type: messageType,\n error_type: errorType,\n error_cause: errorCause,\n });\n\n if (messageType === ROAP.ROAP_TYPES.TURN_DISCOVERY_RESPONSE) {\n // turn discovery is not part of normal roap protocol and so we are not handling it\n // through the usual roap state machine\n meeting.roap.turnDiscovery.handleTurnDiscoveryResponse(data.message, 'from mercury');\n } else {\n const roapMessage = {\n seq,\n messageType,\n sdp: data.message.sdps?.length > 0 ? data.message.sdps[0] : undefined,\n tieBreaker,\n errorType,\n errorCause,\n };\n\n meeting.roapMessageReceived(roapMessage);\n }\n }\n }\n};\n\nMeetingsUtil.getMediaServer = (sdp) => {\n let mediaServer;\n\n // Attempt to collect the media server from the roap message.\n try {\n mediaServer = sdp\n .split('\\r\\n')\n .find((line) => line.startsWith('o='))\n .split(' ')\n .shift()\n .replace('o=', '')\n .toLowerCase();\n } catch {\n mediaServer = undefined;\n }\n\n return mediaServer;\n};\n\nMeetingsUtil.getMediaServerIp = (sdp) => {\n let mediaServerIp;\n\n // Attempt to collect the media server from the roap message.\n try {\n mediaServerIp = sdp\n .split('\\r\\n')\n .find((line) => line.startsWith('o='))\n .match(/o=\\S+ \\d+ \\d+ IN IP4 ([\\d.]+)/)?.[1]\n .toLowerCase()\n .trim();\n } catch {\n mediaServerIp = undefined;\n }\n\n return mediaServerIp;\n};\n\n/**\n * Finds correlationId of a device from locus self devices array\n * that matches the given deviceUrl\n * @param {string} deviceUrl\n * @param {object} locusSelf\n * @returns {string|false} correlationId or false if not found\n */\nMeetingsUtil.getCorrelationIdForDevice = (deviceUrl: string, locusSelf: any) => {\n if (locusSelf?.devices) {\n const foundDevice = locusSelf?.devices.find((device) => device.url === deviceUrl);\n\n if (foundDevice && foundDevice.correlationId) {\n return foundDevice.correlationId;\n }\n }\n\n return false;\n};\n\nMeetingsUtil.parseDefaultSiteFromMeetingPreferences = (userPreferences) => {\n let result = '';\n\n if (userPreferences?.sites?.length) {\n const defaultSite = userPreferences.sites.find((site) => site.default);\n\n if (defaultSite) {\n result = defaultSite.siteUrl;\n } else {\n result = userPreferences.sites[0].siteUrl;\n }\n }\n\n return result;\n};\n\n/**\n * Will check to see if the H.264 media codec is supported.\n * @async\n * @private\n * @returns {Promise<boolean>}\n */\nMeetingsUtil.hasH264Codec = async () => {\n let hasCodec = false;\n\n try {\n const pc = new window.RTCPeerConnection();\n const offer = await pc.createOffer({offerToReceiveVideo: true});\n\n if (offer.sdp.match(/^a=rtpmap:\\d+\\s+H264\\/\\d+/m)) {\n hasCodec = true;\n }\n pc.close();\n } catch (error) {\n LoggerProxy.logger.warn(\n 'Meetings:util#hasH264Codec --> Error creating peerConnection for H.264 test.'\n );\n }\n\n return hasCodec;\n};\n\n/**\n * Notifies the user whether or not the H.264\n * codec is present. Will continuously check\n * until max duration.\n * @async\n * @private\n * @param {object} options\n * @param {Number} options.firstChecked Timestamp in milliseconds\n * @param {boolean} options.disableNotifications Default is false. Boolean to enable/disable notification and events\n * @returns {undefined}\n */\nMeetingsUtil.checkH264Support = async function checkH264Support(options: {\n firstChecked: number;\n disableNotifications: boolean;\n}) {\n const {hasH264Codec} = MeetingsUtil;\n const {firstChecked, disableNotifications} = options || {};\n const delay = 5e3; // ms\n const maxDuration = 3e5; // ms\n const shouldTrigger = firstChecked === undefined;\n const shouldStopChecking = firstChecked && Date.now() - firstChecked >= maxDuration;\n\n // Disable notifications and start H.264 download only\n if (disableNotifications) {\n hasH264Codec();\n\n return;\n }\n\n // Codec loaded trigger event notification\n if (await hasH264Codec()) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_LOADED\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec loaded successfully.');\n\n return;\n }\n\n // Stop checking if past the timelimit\n if (shouldStopChecking) {\n LoggerProxy.logger.error(\n 'Meetings:util#checkH264Support --> Timed out waiting for H264 codec to load.'\n );\n\n return;\n }\n\n // Trigger only once\n if (shouldTrigger) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_MISSING\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec is missing.');\n }\n\n // Keep checking in intervals to see if codec loaded\n window.setTimeout(() => {\n const timestamp = firstChecked || Date.now();\n\n MeetingsUtil.checkH264Support.call(this, {firstChecked: timestamp});\n }, delay);\n};\n\n/**\n * get device from locus data\n * @param {Object} newLocus new locus data\n * @param {String} deviceUrl current device url\n * @returns {Object}\n */\nMeetingsUtil.getThisDevice = (newLocus: any, deviceUrl: string) => {\n if (newLocus?.self?.devices?.length > 0) {\n return newLocus.self.devices.find((device) => device.url === deviceUrl);\n }\n\n return null;\n};\n\n/**\n * Checks if the self state in a locus indicates a breakout move or breakout end.\n * Returns true when:\n * - self state is LEFT with reason MOVED (regular breakout move), OR\n * - fullState is INACTIVE with endMeetingReason BREAKOUT_ENDED (breakout session ended)\n * @param {Object} locus locus data\n * @returns {boolean}\n */\nMeetingsUtil.isSelfMovedOrBreakoutEnded = (locus: any): boolean => {\n const isSelfLeftMoved = locus?.self?.state === _LEFT_ && locus?.self?.reason === _MOVED_;\n const isBreakoutEnded =\n locus?.fullState?.state === LOCUS.STATE.INACTIVE &&\n locus?.fullState?.endMeetingReason === _BREAKOUT_ENDED_;\n\n return isSelfLeftMoved || isBreakoutEnded;\n};\n\n/**\n * get self device joined status from locus data\n * @param {Object} meeting current meeting data\n * @param {Object} newLocus new locus data\n * @param {String} deviceUrl current device url\n * @returns {Object}\n */\nMeetingsUtil.joinedOnThisDevice = (meeting: any, newLocus: any, deviceUrl: string) => {\n const thisDevice = MeetingsUtil.getThisDevice(newLocus, deviceUrl);\n if (thisDevice) {\n if (!thisDevice.correlationId || meeting?.correlationId === thisDevice.correlationId) {\n return (\n thisDevice.state === _JOINED_ ||\n (thisDevice.state === _LEFT_ && thisDevice.reason === _MOVED_)\n );\n }\n }\n\n return false;\n};\n\n/**\n * check the new locus is breakout session's one or not\n * @param {Object} newLocus new locus data\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isBreakoutLocusDTO = (newLocus: any) => {\n return (\n newLocus?.controls?.breakout?.sessionType === BREAKOUTS.SESSION_TYPES.BREAKOUT ||\n !!newLocus?.info?.isBreakout\n );\n};\n\n/**\n * check the locus is valid breakout locus or not\n * @param {Object} locus\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isValidBreakoutLocus = (locus: any) => {\n const inActiveStatus = locus?.fullState?.state === LOCUS.STATE.INACTIVE;\n const isLocusAsBreakout = MeetingsUtil.isBreakoutLocusDTO(locus);\n const selfJoined = locus.self?.state === _JOINED_;\n\n return isLocusAsBreakout && !inActiveStatus && selfJoined;\n};\n/**\n * check if the breakout locus is associated with the main locus by comparing the breakout control url or the replaces info in self device\n * @param {Object} mainLocus main locus data\n * @param {Object} breakoutLocus breakout locus data\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isMainAssociatedWithBreakout = (mainLocus: any, breakoutLocus: any) => {\n if (\n mainLocus.controls?.breakout?.url &&\n mainLocus.controls?.breakout?.url === breakoutLocus.controls?.breakout?.url\n ) {\n return true;\n }\n const deviceUrl = breakoutLocus?.self?.deviceUrl;\n const replaceInfo = MeetingsUtil.getThisDevice(breakoutLocus, deviceUrl)?.replaces?.[0];\n if (replaceInfo?.locusUrl && replaceInfo.locusUrl === mainLocus.url) {\n return true;\n }\n\n return false;\n};\nexport default MeetingsUtil;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_constants","require","_loggerProxy","_interopRequireDefault","_triggerProxy","_constants2","_metrics","_meetings","_types","MeetingsUtil","getMeetingAddedType","type","DESTINATION_TYPE","LOCUS_ID","_INCOMING_","_CREATED_","handleRoapMercury","envelope","meetingCollection","data","eventType","LOCUSEVENT","MESSAGE_ROAP","meeting","getByKey","MEETING_KEY","CORRELATION_ID","correlationId","_data$message","message","seq","messageType","tieBreaker","errorType","errorCause","Metrics","sendBehavioralMetric","BEHAVIORAL_METRICS","ROAP_MERCURY_EVENT_RECEIVED","correlation_id","message_type","error_type","error_cause","ROAP","ROAP_TYPES","TURN_DISCOVERY_RESPONSE","roap","turnDiscovery","handleTurnDiscoveryResponse","_data$message$sdps","roapMessage","sdp","sdps","length","undefined","roapMessageReceived","getMediaServer","mediaServer","split","find","line","startsWith","shift","replace","toLowerCase","_unused","getMediaServerIp","mediaServerIp","_sdp$split$find$match","match","trim","_unused2","getCorrelationIdForDevice","deviceUrl","locusSelf","devices","foundDevice","device","url","parseDefaultSiteFromMeetingPreferences","userPreferences","_userPreferences$site","result","sites","defaultSite","site","default","siteUrl","hasH264Codec","_asyncToGenerator2","_regenerator","mark","_callee","hasCodec","pc","offer","_t","wrap","_context","prev","next","window","RTCPeerConnection","createOffer","offerToReceiveVideo","sent","close","LoggerProxy","logger","warn","abrupt","stop","checkH264Support","_checkH264Support","_callee2","options","_this","_ref2","firstChecked","disableNotifications","delay","maxDuration","shouldTrigger","shouldStopChecking","_context2","_now","Trigger","trigger","file","function","EVENT_TRIGGERS","MEDIA_CODEC_LOADED","log","error","MEDIA_CODEC_MISSING","setTimeout","timestamp","call","_x","apply","arguments","getThisDevice","newLocus","_newLocus$self","_newLocus$self$device","self","isWholeMeetingEnded","fullState","state","LOCUS","STATE","INACTIVE","endMeetingReason","EndMeetingReason","breakoutEnded","isSelfMovedOrBreakoutEnded","locus","_locus$self","_locus$self2","_locus$fullState","_locus$fullState2","isSelfLeftMoved","_LEFT_","reason","_MOVED_","isBreakoutEnded","joinedOnThisDevice","thisDevice","_JOINED_","isBreakoutLocusDTO","_newLocus$controls","_newLocus$controls$br","_newLocus$info","controls","breakout","sessionType","BREAKOUTS","SESSION_TYPES","BREAKOUT","info","isBreakout","isValidBreakoutLocus","_locus$fullState3","_locus$self3","inActiveStatus","isLocusAsBreakout","selfJoined","isMainAssociatedWithBreakout","mainLocus","breakoutLocus","_mainLocus$controls","_mainLocus$controls$b","_mainLocus$controls2","_mainLocus$controls2$","_breakoutLocus$contro","_breakoutLocus$contro2","_breakoutLocus$self","_MeetingsUtil$getThis","_MeetingsUtil$getThis2","replaceInfo","replaces","locusUrl","_default","exports"],"sources":["util.ts"],"sourcesContent":["/* globals window */\n\nimport {\n _CREATED_,\n _INCOMING_,\n _JOINED_,\n _LEFT_,\n DESTINATION_TYPE,\n _MOVED_,\n BREAKOUTS,\n EVENT_TRIGGERS,\n LOCUS,\n LOCUSEVENT,\n ROAP,\n} from '../constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport Trigger from '../common/events/trigger-proxy';\nimport BEHAVIORAL_METRICS from '../metrics/constants';\nimport Metrics from '../metrics';\nimport {MEETING_KEY} from './meetings.types';\nimport {EndMeetingReason, LocusFullState} from '../locus-info/types';\n\n/**\n * Meetings Media Codec Missing Event\n * Emitted when H.264 codec is not\n * found in the browser.\n * @event media:codec:missing\n * @instance\n * @memberof MeetingsUtil\n */\n\n/**\n * Meetings Media Codec Loaded Event\n * Emitted when H.264 codec has been\n * loaded in the browser.\n * @event media:codec:loaded\n * @instance\n * @memberof MeetingsUtil\n */\n\nconst MeetingsUtil: any = {};\n\nMeetingsUtil.getMeetingAddedType = (type: DESTINATION_TYPE) =>\n type === DESTINATION_TYPE.LOCUS_ID ? _INCOMING_ : _CREATED_;\n\nMeetingsUtil.handleRoapMercury = (envelope, meetingCollection) => {\n const {data} = envelope;\n const {eventType} = data;\n\n if (eventType === LOCUSEVENT.MESSAGE_ROAP) {\n const meeting = meetingCollection.getByKey(MEETING_KEY.CORRELATION_ID, data.correlationId);\n\n if (meeting) {\n const {seq, messageType, tieBreaker, errorType, errorCause} = data.message;\n\n Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ROAP_MERCURY_EVENT_RECEIVED, {\n correlation_id: data.correlationId,\n seq,\n message_type: messageType,\n error_type: errorType,\n error_cause: errorCause,\n });\n\n if (messageType === ROAP.ROAP_TYPES.TURN_DISCOVERY_RESPONSE) {\n // turn discovery is not part of normal roap protocol and so we are not handling it\n // through the usual roap state machine\n meeting.roap.turnDiscovery.handleTurnDiscoveryResponse(data.message, 'from mercury');\n } else {\n const roapMessage = {\n seq,\n messageType,\n sdp: data.message.sdps?.length > 0 ? data.message.sdps[0] : undefined,\n tieBreaker,\n errorType,\n errorCause,\n };\n\n meeting.roapMessageReceived(roapMessage);\n }\n }\n }\n};\n\nMeetingsUtil.getMediaServer = (sdp) => {\n let mediaServer;\n\n // Attempt to collect the media server from the roap message.\n try {\n mediaServer = sdp\n .split('\\r\\n')\n .find((line) => line.startsWith('o='))\n .split(' ')\n .shift()\n .replace('o=', '')\n .toLowerCase();\n } catch {\n mediaServer = undefined;\n }\n\n return mediaServer;\n};\n\nMeetingsUtil.getMediaServerIp = (sdp) => {\n let mediaServerIp;\n\n // Attempt to collect the media server from the roap message.\n try {\n mediaServerIp = sdp\n .split('\\r\\n')\n .find((line) => line.startsWith('o='))\n .match(/o=\\S+ \\d+ \\d+ IN IP4 ([\\d.]+)/)?.[1]\n .toLowerCase()\n .trim();\n } catch {\n mediaServerIp = undefined;\n }\n\n return mediaServerIp;\n};\n\n/**\n * Finds correlationId of a device from locus self devices array\n * that matches the given deviceUrl\n * @param {string} deviceUrl\n * @param {object} locusSelf\n * @returns {string|false} correlationId or false if not found\n */\nMeetingsUtil.getCorrelationIdForDevice = (deviceUrl: string, locusSelf: any) => {\n if (locusSelf?.devices) {\n const foundDevice = locusSelf?.devices.find((device) => device.url === deviceUrl);\n\n if (foundDevice && foundDevice.correlationId) {\n return foundDevice.correlationId;\n }\n }\n\n return false;\n};\n\nMeetingsUtil.parseDefaultSiteFromMeetingPreferences = (userPreferences) => {\n let result = '';\n\n if (userPreferences?.sites?.length) {\n const defaultSite = userPreferences.sites.find((site) => site.default);\n\n if (defaultSite) {\n result = defaultSite.siteUrl;\n } else {\n result = userPreferences.sites[0].siteUrl;\n }\n }\n\n return result;\n};\n\n/**\n * Will check to see if the H.264 media codec is supported.\n * @async\n * @private\n * @returns {Promise<boolean>}\n */\nMeetingsUtil.hasH264Codec = async () => {\n let hasCodec = false;\n\n try {\n const pc = new window.RTCPeerConnection();\n const offer = await pc.createOffer({offerToReceiveVideo: true});\n\n if (offer.sdp.match(/^a=rtpmap:\\d+\\s+H264\\/\\d+/m)) {\n hasCodec = true;\n }\n pc.close();\n } catch (error) {\n LoggerProxy.logger.warn(\n 'Meetings:util#hasH264Codec --> Error creating peerConnection for H.264 test.'\n );\n }\n\n return hasCodec;\n};\n\n/**\n * Notifies the user whether or not the H.264\n * codec is present. Will continuously check\n * until max duration.\n * @async\n * @private\n * @param {object} options\n * @param {Number} options.firstChecked Timestamp in milliseconds\n * @param {boolean} options.disableNotifications Default is false. Boolean to enable/disable notification and events\n * @returns {undefined}\n */\nMeetingsUtil.checkH264Support = async function checkH264Support(options: {\n firstChecked: number;\n disableNotifications: boolean;\n}) {\n const {hasH264Codec} = MeetingsUtil;\n const {firstChecked, disableNotifications} = options || {};\n const delay = 5e3; // ms\n const maxDuration = 3e5; // ms\n const shouldTrigger = firstChecked === undefined;\n const shouldStopChecking = firstChecked && Date.now() - firstChecked >= maxDuration;\n\n // Disable notifications and start H.264 download only\n if (disableNotifications) {\n hasH264Codec();\n\n return;\n }\n\n // Codec loaded trigger event notification\n if (await hasH264Codec()) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_LOADED\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec loaded successfully.');\n\n return;\n }\n\n // Stop checking if past the timelimit\n if (shouldStopChecking) {\n LoggerProxy.logger.error(\n 'Meetings:util#checkH264Support --> Timed out waiting for H264 codec to load.'\n );\n\n return;\n }\n\n // Trigger only once\n if (shouldTrigger) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_MISSING\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec is missing.');\n }\n\n // Keep checking in intervals to see if codec loaded\n window.setTimeout(() => {\n const timestamp = firstChecked || Date.now();\n\n MeetingsUtil.checkH264Support.call(this, {firstChecked: timestamp});\n }, delay);\n};\n\n/**\n * get device from locus data\n * @param {Object} newLocus new locus data\n * @param {String} deviceUrl current device url\n * @returns {Object}\n */\nMeetingsUtil.getThisDevice = (newLocus: any, deviceUrl: string) => {\n if (newLocus?.self?.devices?.length > 0) {\n return newLocus.self.devices.find((device) => device.url === deviceUrl);\n }\n\n return null;\n};\n\n/**\n * Checks if the fullState indicates the meeting has fully ended (not just a breakout move).\n * @param {Object} fullState locus fullState data\n * @returns {boolean}\n */\nMeetingsUtil.isWholeMeetingEnded = (fullState: LocusFullState): boolean => {\n return (\n fullState.state === LOCUS.STATE.INACTIVE &&\n fullState.endMeetingReason !== EndMeetingReason.breakoutEnded\n );\n};\n\n/**\n * Checks if the self state in a locus indicates a breakout move or breakout end.\n * Returns true when:\n * - self state is LEFT with reason MOVED (regular breakout move), OR\n * - fullState is INACTIVE with endMeetingReason BREAKOUT_ENDED (breakout session ended)\n * @param {Object} locus locus data\n * @returns {boolean}\n */\nMeetingsUtil.isSelfMovedOrBreakoutEnded = (locus: any): boolean => {\n const isSelfLeftMoved = locus?.self?.state === _LEFT_ && locus?.self?.reason === _MOVED_;\n const isBreakoutEnded =\n locus?.fullState?.state === LOCUS.STATE.INACTIVE &&\n locus?.fullState?.endMeetingReason === EndMeetingReason.breakoutEnded;\n\n return isSelfLeftMoved || isBreakoutEnded;\n};\n\n/**\n * get self device joined status from locus data\n * @param {Object} meeting current meeting data\n * @param {Object} newLocus new locus data\n * @param {String} deviceUrl current device url\n * @returns {Object}\n */\nMeetingsUtil.joinedOnThisDevice = (meeting: any, newLocus: any, deviceUrl: string) => {\n const thisDevice = MeetingsUtil.getThisDevice(newLocus, deviceUrl);\n if (thisDevice) {\n if (!thisDevice.correlationId || meeting?.correlationId === thisDevice.correlationId) {\n return (\n thisDevice.state === _JOINED_ ||\n (thisDevice.state === _LEFT_ && thisDevice.reason === _MOVED_)\n );\n }\n }\n\n return false;\n};\n\n/**\n * check the new locus is breakout session's one or not\n * @param {Object} newLocus new locus data\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isBreakoutLocusDTO = (newLocus: any) => {\n return (\n newLocus?.controls?.breakout?.sessionType === BREAKOUTS.SESSION_TYPES.BREAKOUT ||\n !!newLocus?.info?.isBreakout\n );\n};\n\n/**\n * check the locus is valid breakout locus or not\n * @param {Object} locus\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isValidBreakoutLocus = (locus: any) => {\n const inActiveStatus = locus?.fullState?.state === LOCUS.STATE.INACTIVE;\n const isLocusAsBreakout = MeetingsUtil.isBreakoutLocusDTO(locus);\n const selfJoined = locus.self?.state === _JOINED_;\n\n return isLocusAsBreakout && !inActiveStatus && selfJoined;\n};\n/**\n * check if the breakout locus is associated with the main locus by comparing the breakout control url or the replaces info in self device\n * @param {Object} mainLocus main locus data\n * @param {Object} breakoutLocus breakout locus data\n * @returns {boolean}\n * @private\n */\nMeetingsUtil.isMainAssociatedWithBreakout = (mainLocus: any, breakoutLocus: any) => {\n if (\n mainLocus.controls?.breakout?.url &&\n mainLocus.controls?.breakout?.url === breakoutLocus.controls?.breakout?.url\n ) {\n return true;\n }\n const deviceUrl = breakoutLocus?.self?.deviceUrl;\n const replaceInfo = MeetingsUtil.getThisDevice(breakoutLocus, deviceUrl)?.replaces?.[0];\n if (replaceInfo?.locusUrl && replaceInfo.locusUrl === mainLocus.url) {\n return true;\n }\n\n return false;\n};\nexport default MeetingsUtil;\n"],"mappings":"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","ignoreList":[]}
@@ -73,7 +73,6 @@ export declare const _JOINED_ = "JOINED";
73
73
  export declare const _LOCUS_ID_ = "LOCUS_ID";
74
74
  export declare const _LEFT_ = "LEFT";
75
75
  export declare const _MOVED_ = "MOVED";
76
- export declare const _BREAKOUT_ENDED_ = "BREAKOUT_ENDED";
77
76
  export declare const _ON_HOLD_LOBBY_ = "ON_HOLD_LOBBY";
78
77
  export declare const _MEETING_LINK_ = "MEETING_LINK";
79
78
  export declare const _MEETING_UUID_ = "MEETING_UUID";
@@ -129,6 +129,7 @@ export default class LocusInfo extends EventsScope {
129
129
  private createHashTreeParser;
130
130
  /**
131
131
  * @param {Object} data - data to initialize locus info with. It may be from a join or GET /loci response or from a Mercury event that triggers a creation of meeting object
132
+ * @param {Function} [onLocusSynced] - optional callback that will be called at the end of initial setup, when locus info is fully synced. It will be called with the full locus snapshot as an argument (which may be null if we haven't received any full locus DTOs during the initial setup, for example in case we receive only hash tree messages without full locus DTOs)
132
133
  * @returns {undefined}
133
134
  * @memberof LocusInfo
134
135
  */
@@ -144,7 +145,13 @@ export default class LocusInfo extends EventsScope {
144
145
  } | {
145
146
  trigger: 'get-loci-response';
146
147
  locus?: LocusDTO;
147
- }): Promise<void>;
148
+ }, onLocusSynced?: (locus: LocusDTO) => void): Promise<void>;
149
+ /**
150
+ * Builds a full locus DTO snapshot from current internal locus state.
151
+ *
152
+ * @returns {LocusDTO}
153
+ */
154
+ private getCurrentLocusSnapshot;
148
155
  /**
149
156
  * Handles HTTP response from Locus API call.
150
157
  * @param {Meeting} meeting meeting object
@@ -1,14 +1,30 @@
1
+ import { Enum } from '../constants';
1
2
  import { HtMeta } from '../hashTree/types';
3
+ export declare const EndMeetingReason: {
4
+ readonly maxMeetingDuration: "MAX_MEETING_DURATION";
5
+ readonly allParticipantsLeft: "ALL_PARTICIPANTS_LEFT";
6
+ readonly sipHostLeft: "SIP_HOST_LEFT";
7
+ readonly noHost: "NO_HOST";
8
+ readonly waitingForMpsEndMeetingTimeout: "WAITING_FOR_MPS_END_MEETING_TIMEOUT";
9
+ readonly fraudDetection: "FRAUD_DETECTION";
10
+ readonly meetingEndedByHost: "MEETING_ENDED_BY_HOST";
11
+ readonly meetingUpdated: "MEETING_UPDATED";
12
+ readonly meetingCancelled: "MEETING_CANCELLED";
13
+ readonly autoEndWithSingleParticipant: "AUTO_END_WITH_SINGLE_PARTICIPANT";
14
+ readonly breakoutEnded: "BREAKOUT_ENDED";
15
+ };
16
+ export type EndMeetingReason = Enum<typeof EndMeetingReason>;
2
17
  export type LocusFullState = {
3
18
  active: boolean;
4
19
  count: number;
5
20
  lastActive: string;
6
21
  locked: boolean;
7
22
  sessionId: string;
8
- seessionIds: string[];
23
+ sessionIds: string[];
9
24
  startTime: number;
10
25
  state: string;
11
26
  type: string;
27
+ endMeetingReason?: EndMeetingReason;
12
28
  };
13
29
  export type Links = {
14
30
  services: Record<'breakout' | 'record', {
@@ -374,7 +374,7 @@ export default class Meeting extends StatelessWebexPlugin {
374
374
  webinar: any;
375
375
  conversationUrl: string;
376
376
  callStateForMetrics: CallStateForMetrics;
377
- destination: string;
377
+ destination: string | LocusDTO;
378
378
  destinationType: DESTINATION_TYPE;
379
379
  deviceUrl: string;
380
380
  hostId: string;
@@ -1051,6 +1051,13 @@ export default class Meeting extends StatelessWebexPlugin {
1051
1051
  * @memberof Meeting
1052
1052
  */
1053
1053
  setSipUri(sipUri: string): void;
1054
+ /**
1055
+ * After initial locus setup, refreshes destination with synced locus data and optionally
1056
+ * performs deferred meeting info fetch when initial locus was incomplete.
1057
+ * @param {LocusDTO} locus
1058
+ * @returns {void}
1059
+ */
1060
+ finalizeMeetingAfterInitialLocusSetup(locus: LocusDTO): Promise<void>;
1054
1061
  /**
1055
1062
  * Set the locus info the class instance. Should be called with the parsed locus
1056
1063
  * we got in the join response.
@@ -723,7 +723,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
723
723
  }, _callee1);
724
724
  }))();
725
725
  },
726
- version: "3.12.0-next.35"
726
+ version: "3.12.0-next.37"
727
727
  });
728
728
  var _default = exports.default = Webinar;
729
729
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -94,5 +94,5 @@
94
94
  "//": [
95
95
  "TODO: upgrade jwt-decode when moving to node 18"
96
96
  ],
97
- "version": "3.12.0-next.35"
97
+ "version": "3.12.0-next.37"
98
98
  }
package/src/constants.ts CHANGED
@@ -103,7 +103,6 @@ export const _JOINED_ = 'JOINED';
103
103
  export const _LOCUS_ID_ = 'LOCUS_ID';
104
104
  export const _LEFT_ = 'LEFT';
105
105
  export const _MOVED_ = 'MOVED';
106
- export const _BREAKOUT_ENDED_ = 'BREAKOUT_ENDED';
107
106
  export const _ON_HOLD_LOBBY_ = 'ON_HOLD_LOBBY';
108
107
  export const _MEETING_LINK_ = 'MEETING_LINK';
109
108
  export const _MEETING_UUID_ = 'MEETING_UUID';
@@ -418,7 +417,7 @@ export const HEADERS = {
418
417
  // Meeting actually ended
419
418
  export const MEETING_REMOVED_REASON = {
420
419
  SELF_REMOVED: 'SELF_REMOVED', // server or host removed you from the meeting
421
- MEETING_INACTIVE_TERMINATING: 'MEETING_INACTIVE_TERMINATING', // Meeting got ended or everyone left the meeting
420
+ MEETING_INACTIVE_TERMINATING: 'MEETING_INACTIVE_TERMINATING', // Meeting got ended or everyone left the meeting (historically was sent on Locus TERMINATING or INACTIVE, but now only on INACTIVE as that's the final state)
422
421
  CLIENT_LEAVE_REQUEST: 'CLIENT_LEAVE_REQUEST', // You triggered leave meeting
423
422
  CLIENT_LEAVE_REQUEST_TAB_CLOSED: 'CLIENT_LEAVE_REQUEST_TAB_CLOSED', // You triggered leave meeting, such as closing the browser tab directly
424
423
  USER_ENDED_SHARE_STREAMS: 'USER_ENDED_SHARE_STREAMS', // user triggered stop share
@@ -582,6 +582,7 @@ export default class LocusInfo extends EventsScope {
582
582
 
583
583
  /**
584
584
  * @param {Object} data - data to initialize locus info with. It may be from a join or GET /loci response or from a Mercury event that triggers a creation of meeting object
585
+ * @param {Function} [onLocusSynced] - optional callback that will be called at the end of initial setup, when locus info is fully synced. It will be called with the full locus snapshot as an argument (which may be null if we haven't received any full locus DTOs during the initial setup, for example in case we receive only hash tree messages without full locus DTOs)
585
586
  * @returns {undefined}
586
587
  * @memberof LocusInfo
587
588
  */
@@ -601,8 +602,10 @@ export default class LocusInfo extends EventsScope {
601
602
  | {
602
603
  trigger: 'get-loci-response';
603
604
  locus?: LocusDTO;
604
- }
605
+ },
606
+ onLocusSynced?: (locus: LocusDTO) => void
605
607
  ) {
608
+ let initialFullLocus: LocusDTO | null = null;
606
609
  switch (data.trigger) {
607
610
  case 'locus-message':
608
611
  if (data.hashTreeMessage) {
@@ -650,6 +653,7 @@ export default class LocusInfo extends EventsScope {
650
653
  case 'join-response':
651
654
  this.updateLocusCache(data.locus);
652
655
  this.onFullLocus('join response', data.locus, undefined, data.dataSets, data.metadata);
656
+ initialFullLocus = data.locus;
653
657
  break;
654
658
  case 'get-loci-response':
655
659
  if (data.locus?.links?.resources?.visibleDataSets?.url) {
@@ -672,12 +676,47 @@ export default class LocusInfo extends EventsScope {
672
676
  // "classic" Locus case, no hash trees involved
673
677
  this.updateLocusCache(data.locus);
674
678
  this.onFullLocus('classic get-loci-response', data.locus, undefined);
679
+ initialFullLocus = data.locus || null;
675
680
  }
676
681
  }
682
+
683
+ if (onLocusSynced) {
684
+ try {
685
+ onLocusSynced(initialFullLocus || this.getCurrentLocusSnapshot());
686
+ } catch (error) {
687
+ LoggerProxy.logger.warn(
688
+ `Locus-info:index#initialSetup --> onLocusSynced callback failed: ${error}`
689
+ );
690
+ }
691
+ }
692
+
677
693
  // Change it to true after it receives it first locus object
678
694
  this.emitChange = true;
679
695
  }
680
696
 
697
+ /**
698
+ * Builds a full locus DTO snapshot from current internal locus state.
699
+ *
700
+ * @returns {LocusDTO}
701
+ */
702
+ private getCurrentLocusSnapshot(): LocusDTO {
703
+ const locus: Record<string, any> = {};
704
+
705
+ LocusDtoTopLevelKeys.forEach((key) => {
706
+ const value = (this as Record<string, any>)[key];
707
+
708
+ if (value !== undefined && value !== null) {
709
+ locus[key] = cloneDeep(value);
710
+ }
711
+ });
712
+
713
+ if (!Array.isArray(locus.participants)) {
714
+ locus.participants = [];
715
+ }
716
+
717
+ return locus as LocusDTO;
718
+ }
719
+
681
720
  /**
682
721
  * Handles HTTP response from Locus API call.
683
722
  * @param {Meeting} meeting meeting object
@@ -1781,14 +1820,9 @@ export default class LocusInfo extends EventsScope {
1781
1820
  );
1782
1821
  }
1783
1822
  } else if (this.parsedLocus.fullState?.type === _MEETING_) {
1784
- if (
1785
- this.fullState &&
1786
- (this.fullState.state === LOCUS.STATE.INACTIVE ||
1787
- // @ts-ignore
1788
- this.fullState.state === LOCUS.STATE.TERMINATING)
1789
- ) {
1823
+ if (this.fullState && MeetingsUtil.isWholeMeetingEnded(this.fullState)) {
1790
1824
  LoggerProxy.logger.warn(
1791
- 'Locus-info:index#isMeetingActive --> Meeting is ending due to inactive or terminating'
1825
+ 'Locus-info:index#isMeetingActive --> Meeting is ending due to inactive'
1792
1826
  );
1793
1827
 
1794
1828
  // @ts-ignore
@@ -1,15 +1,33 @@
1
+ import {Enum} from '../constants';
1
2
  import {HtMeta} from '../hashTree/types';
2
3
 
4
+ export const EndMeetingReason = {
5
+ maxMeetingDuration: 'MAX_MEETING_DURATION',
6
+ allParticipantsLeft: 'ALL_PARTICIPANTS_LEFT',
7
+ sipHostLeft: 'SIP_HOST_LEFT',
8
+ noHost: 'NO_HOST',
9
+ waitingForMpsEndMeetingTimeout: 'WAITING_FOR_MPS_END_MEETING_TIMEOUT',
10
+ fraudDetection: 'FRAUD_DETECTION',
11
+ meetingEndedByHost: 'MEETING_ENDED_BY_HOST',
12
+ meetingUpdated: 'MEETING_UPDATED', // Locus code has comment about EndMeetingIfPossible reason for this one
13
+ meetingCancelled: 'MEETING_CANCELLED', // Locus code has comment about EndMeetingIfPossible reason for this one
14
+ autoEndWithSingleParticipant: 'AUTO_END_WITH_SINGLE_PARTICIPANT',
15
+ breakoutEnded: 'BREAKOUT_ENDED', // indicates that only a breakout session ended, not the whole meeting
16
+ } as const;
17
+
18
+ export type EndMeetingReason = Enum<typeof EndMeetingReason>;
19
+
3
20
  export type LocusFullState = {
4
21
  active: boolean;
5
22
  count: number;
6
23
  lastActive: string;
7
24
  locked: boolean;
8
25
  sessionId: string;
9
- seessionIds: string[];
26
+ sessionIds: string[];
10
27
  startTime: number;
11
28
  state: string;
12
29
  type: string;
30
+ endMeetingReason?: EndMeetingReason;
13
31
  };
14
32
 
15
33
  export type Links = {
@@ -612,7 +612,7 @@ export default class Meeting extends StatelessWebexPlugin {
612
612
  webinar: any;
613
613
  conversationUrl: string;
614
614
  callStateForMetrics: CallStateForMetrics;
615
- destination: string;
615
+ destination: string | LocusDTO;
616
616
  destinationType: DESTINATION_TYPE;
617
617
  deviceUrl: string;
618
618
  hostId: string;
@@ -4659,6 +4659,33 @@ export default class Meeting extends StatelessWebexPlugin {
4659
4659
  this.sipUri = sipUri;
4660
4660
  }
4661
4661
 
4662
+ /**
4663
+ * After initial locus setup, refreshes destination with synced locus data and optionally
4664
+ * performs deferred meeting info fetch when initial locus was incomplete.
4665
+ * @param {LocusDTO} locus
4666
+ * @returns {void}
4667
+ */
4668
+ public async finalizeMeetingAfterInitialLocusSetup(locus: LocusDTO): Promise<void> {
4669
+ if (locus && this?.destinationType === DESTINATION_TYPE.LOCUS_ID) {
4670
+ // destination is initialized from the initial locus snapshot in constructor,
4671
+ // so refresh it after locus sync to avoid stale partial hash-tree data.
4672
+ this.destination = locus;
4673
+ }
4674
+ if (
4675
+ (!this.meetingInfo || isEmpty(this.meetingInfo)) &&
4676
+ (this.destination as LocusDTO)?.info &&
4677
+ !this.fetchMeetingInfoTimeoutId
4678
+ ) {
4679
+ try {
4680
+ await this.fetchMeetingInfo({});
4681
+ } catch (error: any) {
4682
+ LoggerProxy.logger.info(
4683
+ `Meeting:index#finalizeMeetingAfterInitialLocusSetup --> deferred fetchMeetingInfo failed: ${error.message}`
4684
+ );
4685
+ }
4686
+ }
4687
+ }
4688
+
4662
4689
  /**
4663
4690
  * Set the locus info the class instance. Should be called with the parsed locus
4664
4691
  * we got in the join response.
@@ -584,17 +584,21 @@ export default class Meetings extends WebexPlugin {
584
584
  this.create(data.locus, DESTINATION_TYPE.LOCUS_ID, useRandomDelayForInfo)
585
585
  .then(async (newMeeting) => {
586
586
  meeting = newMeeting;
587
-
588
587
  try {
589
588
  // It's a new meeting so initialize the locus data
590
- await meeting.locusInfo.initialSetup({
591
- trigger:
592
- data.eventType === LOCUSEVENT.SDK_LOCUS_FROM_SYNC_MEETINGS
593
- ? 'get-loci-response'
594
- : 'locus-message',
595
- locus: data.locus,
596
- hashTreeMessage: data.stateElementsMessage,
597
- });
589
+ await meeting.locusInfo.initialSetup(
590
+ {
591
+ trigger:
592
+ data.eventType === LOCUSEVENT.SDK_LOCUS_FROM_SYNC_MEETINGS
593
+ ? 'get-loci-response'
594
+ : 'locus-message',
595
+ locus: data.locus,
596
+ hashTreeMessage: data.stateElementsMessage,
597
+ },
598
+ (locus: LocusDTO) => {
599
+ meeting.finalizeMeetingAfterInitialLocusSetup(locus);
600
+ }
601
+ );
598
602
  } catch (error) {
599
603
  LoggerProxy.logger.warn(
600
604
  `Meetings:index#handleLocusEvent --> Error initializing locus data: ${error.message}`
@@ -602,6 +606,7 @@ export default class Meetings extends WebexPlugin {
602
606
  // @ts-ignore
603
607
  this.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
604
608
  }
609
+
605
610
  this.checkHandleBreakoutLocus(data.locus);
606
611
  })
607
612
  .catch((e) => {
@@ -1762,6 +1767,7 @@ export default class Meetings extends WebexPlugin {
1762
1767
  extraParams: infoExtraParams,
1763
1768
  sendCAevents: !!callStateForMetrics?.correlationId, // if client sends correlation id as argument of public create(), then it means that this meeting creation is part of a pre-join intent from user
1764
1769
  };
1770
+ const shouldDeferMeetingInfoFetch = type === DESTINATION_TYPE.LOCUS_ID && !destination?.info;
1765
1771
 
1766
1772
  if (meetingInfo) {
1767
1773
  meeting.injectMeetingInfo(meetingInfo, meetingInfoOptions, meetingLookupUrl);
@@ -1773,8 +1779,12 @@ export default class Meetings extends WebexPlugin {
1773
1779
  waitingTime
1774
1780
  );
1775
1781
  meeting.parseMeetingInfo(undefined, destination);
1776
- } else {
1782
+ } else if (!shouldDeferMeetingInfoFetch) {
1777
1783
  await meeting.fetchMeetingInfo(meetingInfoOptions);
1784
+ } else {
1785
+ LoggerProxy.logger.info(
1786
+ 'Meetings:index#createMeeting --> defer fetchMeetingInfo for incomplete locus, will do it after locus initialSetup'
1787
+ );
1778
1788
  }
1779
1789
  }
1780
1790
  } catch (err) {
@@ -7,7 +7,6 @@ import {
7
7
  _LEFT_,
8
8
  DESTINATION_TYPE,
9
9
  _MOVED_,
10
- _BREAKOUT_ENDED_,
11
10
  BREAKOUTS,
12
11
  EVENT_TRIGGERS,
13
12
  LOCUS,
@@ -19,6 +18,7 @@ import Trigger from '../common/events/trigger-proxy';
19
18
  import BEHAVIORAL_METRICS from '../metrics/constants';
20
19
  import Metrics from '../metrics';
21
20
  import {MEETING_KEY} from './meetings.types';
21
+ import {EndMeetingReason, LocusFullState} from '../locus-info/types';
22
22
 
23
23
  /**
24
24
  * Meetings Media Codec Missing Event
@@ -267,6 +267,18 @@ MeetingsUtil.getThisDevice = (newLocus: any, deviceUrl: string) => {
267
267
  return null;
268
268
  };
269
269
 
270
+ /**
271
+ * Checks if the fullState indicates the meeting has fully ended (not just a breakout move).
272
+ * @param {Object} fullState locus fullState data
273
+ * @returns {boolean}
274
+ */
275
+ MeetingsUtil.isWholeMeetingEnded = (fullState: LocusFullState): boolean => {
276
+ return (
277
+ fullState.state === LOCUS.STATE.INACTIVE &&
278
+ fullState.endMeetingReason !== EndMeetingReason.breakoutEnded
279
+ );
280
+ };
281
+
270
282
  /**
271
283
  * Checks if the self state in a locus indicates a breakout move or breakout end.
272
284
  * Returns true when:
@@ -279,7 +291,7 @@ MeetingsUtil.isSelfMovedOrBreakoutEnded = (locus: any): boolean => {
279
291
  const isSelfLeftMoved = locus?.self?.state === _LEFT_ && locus?.self?.reason === _MOVED_;
280
292
  const isBreakoutEnded =
281
293
  locus?.fullState?.state === LOCUS.STATE.INACTIVE &&
282
- locus?.fullState?.endMeetingReason === _BREAKOUT_ENDED_;
294
+ locus?.fullState?.endMeetingReason === EndMeetingReason.breakoutEnded;
283
295
 
284
296
  return isSelfLeftMoved || isBreakoutEnded;
285
297
  };