@reactoo/watchtogether-sdk-js 2.5.67 → 2.5.70

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.
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * @reactoo/watchtogether-sdk-js
3
- * @version 2.5.67
3
+ * @version 2.5.70
4
4
  */
5
5
  (function webpackUniversalModuleDefinition(root, factory) {
6
6
  if(typeof exports === 'object' && typeof module === 'object')
@@ -9211,7 +9211,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _mod
9211
9211
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
9212
9212
 
9213
9213
  "use strict";
9214
- eval("__webpack_require__.r(__webpack_exports__);\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n getUserStream() {\n let {\n hasVideo,\n isHd,\n aDeviceId,\n vDeviceId,\n lfps,\n autoGainControl = false,\n muteAudio = false,\n muteVideo = false\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n let fullConstraints = {\n audio: { ...(aDeviceId && {\n deviceId: {\n exact: aDeviceId\n }\n }),\n autoGainControl,\n echoCancellation: true,\n noiseSuppression: true,\n channelCount: 1\n },\n video: { ...(vDeviceId && {\n deviceId: {\n exact: vDeviceId\n }\n }),\n facingMode: {\n ideal: \"user\"\n },\n ...(lfps ? {\n frameRate: {\n ideal: 10,\n max: 30\n }\n } : {\n frameRate: {\n ideal: 24,\n max: 30\n }\n }),\n width: {\n ideal: isHd ? 1280 : 320\n },\n height: {\n ideal: isHd ? 720 : 240\n }\n }\n };\n let audioOnlyConstraints = {\n audio: { ...(aDeviceId && {\n deviceId: {\n exact: aDeviceId\n }\n }),\n autoGainControl,\n echoCancellation: true,\n noiseSuppression: true,\n channelCount: 1\n }\n };\n return navigator.mediaDevices.getUserMedia(hasVideo ? fullConstraints : audioOnlyConstraints).then(stream => {\n if (muteAudio) {\n stream.getAudioTracks().forEach(track => track.enabled = false);\n }\n\n if (muteVideo) {\n stream.getVideoTracks().forEach(track => track.enabled = false);\n }\n\n return stream;\n });\n }\n\n});\n\n//# sourceURL=webpack://WatchTogetherSDK/./src/models/utils.js?");
9214
+ eval("__webpack_require__.r(__webpack_exports__);\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n getUserStream() {\n let {\n hasVideo,\n isHd,\n aDeviceId,\n vDeviceId,\n lfps,\n autoGainControl = false,\n echoCancellation = true,\n noiseSuppression = true,\n channelCount = 1,\n muteAudio = false,\n muteVideo = false\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n let fullConstraints = {\n audio: { ...(aDeviceId && {\n deviceId: {\n exact: aDeviceId\n }\n }),\n autoGainControl,\n echoCancellation,\n noiseSuppression,\n channelCount\n },\n video: { ...(vDeviceId && {\n deviceId: {\n exact: vDeviceId\n }\n }),\n facingMode: {\n ideal: \"user\"\n },\n ...(lfps ? {\n frameRate: {\n ideal: 10,\n max: 30\n }\n } : {\n frameRate: {\n ideal: 24,\n max: 30\n }\n }),\n width: {\n ideal: isHd ? 1280 : 320\n },\n height: {\n ideal: isHd ? 720 : 240\n }\n }\n };\n let audioOnlyConstraints = {\n audio: { ...(aDeviceId && {\n deviceId: {\n exact: aDeviceId\n }\n }),\n autoGainControl,\n echoCancellation: true,\n noiseSuppression: true,\n channelCount: 1\n }\n };\n return navigator.mediaDevices.getUserMedia(hasVideo ? fullConstraints : audioOnlyConstraints).then(stream => {\n if (muteAudio) {\n stream.getAudioTracks().forEach(track => track.enabled = false);\n }\n\n if (muteVideo) {\n stream.getVideoTracks().forEach(track => track.enabled = false);\n }\n\n return stream;\n });\n }\n\n});\n\n//# sourceURL=webpack://WatchTogetherSDK/./src/models/utils.js?");
9215
9215
 
9216
9216
  /***/ }),
9217
9217
 
@@ -9307,7 +9307,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _wt_
9307
9307
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
9308
9308
 
9309
9309
  "use strict";
9310
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _wt_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../wt-utils */ \"./src/modules/wt-utils.js\");\n/* harmony import */ var _wt_emitter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../wt-emitter */ \"./src/modules/wt-emitter.js\");\n\n\n\nconst syncModule = function () {\n let {\n room,\n emitter\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n //SYNC VARS\n let _emitter = Object(_wt_emitter__WEBPACK_IMPORTED_MODULE_1__[\"default\"])();\n\n let _playerInterface = null;\n let _propagateMaster = false;\n let _playerInterfaceOptions = {\n type: 'none',\n ignoreBufferedTimeRanges: true,\n disableFastSeek: false\n };\n const syncDefaultWaitTime = 60000;\n const syncShortWaitTime = 10000;\n const maxSyncThreshold = 0.5;\n const maxSyncTries = 3;\n const waitForPlayingEventAfterSeek = 5000;\n const fastForwardThreshold = 4;\n let currentSyncRetry = 0;\n let syncWaitId = null;\n let syncNextWaitTime = null;\n let stopFlag = false;\n let isSyncing = false;\n let playbackRate = 2;\n let isPlaying = false;\n let isPreloading = true;\n let isProgrammaticallySeeked = false;\n\n const startSyncLoop = () => {\n if (!isConnected()) {\n room._log('--- Sync loop will not start due to user not connected yet ---');\n\n return;\n }\n\n if (syncWaitId) {\n room._log('--- Sync loop already running ---');\n\n return;\n }\n\n room._log('--- Sync enabled ---');\n\n stopFlag = false;\n\n const loop = () => {\n isSyncing = true;\n emitter.emit('playerSyncing', true);\n sync().finally(() => {\n isSyncing = false;\n emitter.emit('playerSyncing', false);\n\n if (isConnected() && !stopFlag) {\n syncWaitId = setTimeout(loop, syncNextWaitTime);\n } else {\n room._log('--- Automatic stop due to user not connected or stop flag enabled ---');\n\n stopSyncLoop();\n }\n });\n };\n\n loop();\n };\n\n const stopSyncLoop = doNotResetRetryCount => {\n room._log('--- Sync disabled ---');\n\n clearTimeout(syncWaitId);\n syncWaitId = null;\n\n if (!doNotResetRetryCount) {\n currentSyncRetry = 0;\n }\n\n stopFlag = true;\n };\n\n const restartSyncLoop = () => {\n room._log('--- Sync restarting ---');\n\n stopSyncLoop();\n startSyncLoop();\n };\n\n const setNextWaitTime = function () {\n let didSyncFail = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n if (!didSyncFail) {\n syncNextWaitTime = syncDefaultWaitTime;\n currentSyncRetry = 0;\n } else {\n currentSyncRetry++;\n\n if (currentSyncRetry > maxSyncTries) {\n syncNextWaitTime = syncDefaultWaitTime;\n currentSyncRetry = 0;\n } else {\n syncNextWaitTime = syncShortWaitTime;\n }\n }\n\n room._log('--- Next sync will occur in ' + syncNextWaitTime / 1000 + ' seconds ---');\n };\n\n const sync = () => {\n return getSyncData().then(syncData => {\n if (syncData.isMaster) {\n if (_playerInterface.isPaused) _playerInterface.play();\n setNextWaitTime(false);\n return Promise.resolve();\n } else if (_propagateMaster) {\n setNextWaitTime(false);\n return propagateMasterFunc();\n } else {\n const syncStartTime = Date.now();\n const {\n position,\n realPosition,\n isBufferSufficient\n } = _playerInterface.getTimeDifference ? _playerInterface.getTimeDifference(syncData.masterFragmentSn, syncData.masterFragmentPos, syncData.ping) : getTimeDifference(syncData.masterFragmentSn, syncData.masterFragmentPos, syncData.ping);\n\n if (position && Math.abs(position) <= maxSyncThreshold) {\n room._log(\"We're within max sync threshold, no need to resync now\");\n\n setNextWaitTime(false);\n return Promise.resolve();\n }\n\n if (position !== null && !isNaN(position)) {\n return seekBy(position).then(() => {\n const seekDuration = Date.now() - syncStartTime;\n const {\n position,\n realPosition,\n isBufferSufficient\n } = _playerInterface.getTimeDifference ? _playerInterface.getTimeDifference(syncData.masterFragmentSn, syncData.masterFragmentPos + seekDuration, syncData.ping) : getTimeDifference(syncData.masterFragmentSn, syncData.masterFragmentPos + seekDuration, syncData.ping);\n const syncPrecision = Math.abs(realPosition);\n\n room._log(\"Insufficient buffer: \", !isBufferSufficient);\n\n room._log(\"Seek duration is \".concat(seekDuration / 1000, \" seconds\"));\n\n room._log(\"Sync precision should be \".concat(syncPrecision));\n\n const didSyncFail = syncPrecision > maxSyncThreshold;\n setNextWaitTime(didSyncFail);\n return Promise.resolve();\n }).catch(e => {\n room._log(\"Seek failed: \", e);\n\n setNextWaitTime(true);\n return Promise.reject(e);\n });\n } else {\n room._log(\"Position in not a number: \", position);\n\n setNextWaitTime(true);\n return Promise.reject();\n }\n }\n }).catch(e => {\n room._log(\"getSyncData() failed: \", e);\n\n setNextWaitTime(true);\n return Promise.reject();\n });\n };\n\n const handleAddLocalParticipant = () => {\n if (_propagateMaster) {\n propagateMasterFunc();\n }\n\n if (_playerInterface.isPaused === false) {\n _emitter.once('timeupdate', restartSyncLoop);\n }\n };\n\n const handleAddRemoteParticipant = () => {\n if (_propagateMaster) {\n propagateMasterFunc();\n }\n };\n\n const isConnected = () => {\n return room._isDataChannelOpen && room.isConnected;\n };\n\n const parseDataEvents = function () {\n let msg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n if (msg.videoroom === 'sync_request') {\n roomSyncSend(msg.sync_slave_id).catch(() => {});\n }\n };\n\n const getCurrentPlayerPosition = () => {\n let position = _playerInterface.currentTime;\n return isNaN(position) ? 0 : position * 1000;\n };\n\n const getTimeDifference = (fragmentSn, fragmentPos, ping) => {\n let seekRanges = _playerInterface.buffered;\n let position = (fragmentPos + ping / 2) / 1000;\n let currentPlayerPosition = getCurrentPlayerPosition() / 1000;\n\n if (seekRanges && !_playerInterfaceOptions.ignoreBufferedTimeRanges) {\n let seekRange = {};\n\n for (let i = 0; i < seekRanges.length; i++) {\n let _c_start = seekRanges.start(i);\n\n let _c_end = seekRanges.end(i);\n\n if (!seekRange.start || _c_start < seekRange.start) {\n seekRange.start = _c_start;\n }\n\n if (!seekRange.end || _c_end > seekRange.end) {\n seekRange.end = _c_end;\n }\n }\n\n if (position > seekRange.start && position < seekRange.end) {\n return {\n position: position - currentPlayerPosition,\n realPosition: position - currentPlayerPosition,\n isBufferSufficient: true\n };\n } else if (position < seekRange.start) {\n room._log(\"Syncing to \".concat(seekRange.start, \" instead of \").concat(position, \" due to lack of buffered data\"));\n\n return {\n position: seekRange.start + 0.5 - currentPlayerPosition,\n realPosition: position - currentPlayerPosition,\n isBufferSufficient: false\n };\n } else if (position > seekRange.end) {\n room._log(\"Syncing to \".concat(seekRange.end, \" instead of \").concat(position, \" due to lack of buffered data\"));\n\n return {\n position: seekRange.end - 0.5 - currentPlayerPosition,\n realPosition: position - currentPlayerPosition,\n isBufferSufficient: false\n };\n } else return {\n position: null,\n isBufferSufficient: false\n };\n } else {\n return {\n position: position - currentPlayerPosition,\n realPosition: position - currentPlayerPosition,\n isBufferSufficient: true\n };\n }\n };\n\n const seekBy = time => {\n return new Promise((resolve, reject) => {\n if (_playerInterface.currentTime !== time) {\n if (time > 0 && time < fastForwardThreshold && !_playerInterfaceOptions.disableFastSeek) {\n room._log(\"Fast forward to seek...\");\n\n let wasPaused = false;\n\n let _handleFailed = () => {\n if (wasPaused) {\n _playerInterface.pause();\n }\n\n _playerInterface.setPlaybackRate(1);\n\n isProgrammaticallySeeked = false;\n reject('Stalled');\n };\n\n let _fastForward = () => {\n isProgrammaticallySeeked = true;\n Object(_wt_utils__WEBPACK_IMPORTED_MODULE_0__[\"setExactTimeout\"])(() => {\n _emitter.off('stalled', _handleFailed);\n\n if (wasPaused && _playerInterface.isVod) {\n _playerInterface.pause();\n }\n\n _playerInterface.setPlaybackRate(1);\n\n isProgrammaticallySeeked = false;\n resolve();\n }, time * 1000 / (playbackRate - 1), 20);\n\n _playerInterface.setPlaybackRate(playbackRate);\n };\n\n _emitter.once('stalled', _handleFailed);\n\n if (_playerInterface.isPaused) {\n wasPaused = true;\n\n _playerInterface.play().then(() => {\n _fastForward();\n }).catch(_handleFailed);\n } else {\n _fastForward();\n }\n } else {\n room._log(\"Jump to seek...\");\n\n let currentTimestamp = Date.now();\n let __failsafeId = null;\n\n let _resolve = () => {\n clearTimeout(__failsafeId);\n __failsafeId = null;\n isProgrammaticallySeeked = false;\n\n room._log(\"It took the player \".concat((Date.now() - currentTimestamp) / 1000, \" seconds to seek \"));\n\n resolve();\n };\n\n isProgrammaticallySeeked = true; // we need to ignore stall events since those are false alarm\n\n _emitter.once('playing', _resolve);\n\n __failsafeId = setTimeout(_resolve, waitForPlayingEventAfterSeek);\n\n _playerInterface.seek(_playerInterface.currentTime + time);\n }\n } else resolve();\n });\n };\n\n const seekTo = time => {\n return new Promise((resolve, reject) => {\n if (_playerInterface.currentTime !== time) {\n let diff = time - _playerInterface.currentTime;\n\n if (_playerInterface.currentTime < time && diff < fastForwardThreshold && !_playerInterfaceOptions.disableFastSeek) {\n room._log(\"Fast forward to seek...\");\n\n let wasPaused = false;\n\n let _handleFailed = () => {\n if (wasPaused) {\n _playerInterface.pause();\n }\n\n _playerInterface.setPlaybackRate(1);\n\n isProgrammaticallySeeked = false;\n reject('Stalled');\n };\n\n let _fastForward = () => {\n isProgrammaticallySeeked = true;\n Object(_wt_utils__WEBPACK_IMPORTED_MODULE_0__[\"setExactTimeout\"])(() => {\n _emitter.off('stalled', _handleFailed);\n\n if (wasPaused && _playerInterface.isVod) {\n _playerInterface.pause();\n }\n\n _playerInterface.setPlaybackRate(1);\n\n isProgrammaticallySeeked = false;\n resolve();\n }, diff * 1000 / (playbackRate - 1), 20);\n\n _playerInterface.setPlaybackRate(playbackRate);\n };\n\n _emitter.once('stalled', _handleFailed);\n\n if (_playerInterface.isPaused) {\n wasPaused = true;\n\n _playerInterface.play().then(() => {\n _fastForward();\n }).catch(_handleFailed);\n } else {\n _fastForward();\n }\n } else {\n room._log(\"Jump to seek...\");\n\n let currentTimestamp = Date.now();\n let __failsafeId = null;\n\n let _resolve = () => {\n clearTimeout(__failsafeId);\n __failsafeId = null;\n isProgrammaticallySeeked = false;\n\n room._log(\"It took the player \".concat((Date.now() - currentTimestamp) / 1000, \" seconds to seek \"));\n\n resolve();\n };\n\n isProgrammaticallySeeked = true; // we need to ignore stall events since those are false alarm\n\n _emitter.once('playing', _resolve);\n\n __failsafeId = setTimeout(_resolve, waitForPlayingEventAfterSeek);\n\n _playerInterface.seek(time);\n }\n } else resolve();\n });\n };\n\n const handlePlaying = () => {\n if (!isProgrammaticallySeeked) {\n room._log('Handle playing');\n\n startSyncLoop();\n }\n\n isProgrammaticallySeeked = false;\n isPreloading = _playerInterface.isPaused;\n isPlaying = !_playerInterface.isPaused;\n };\n\n const handlePause = () => {\n stopSyncLoop();\n clientPaused().catch(() => {});\n isPlaying = !_playerInterface.isPaused;\n };\n\n const handleBuffering = () => {\n room._log('handleBuffering');\n\n if (!isProgrammaticallySeeked) {\n stopSyncLoop(true);\n clientPaused().catch(() => {});\n isPreloading = _playerInterface.isPaused;\n }\n };\n\n const roomSyncSend = slaveId => {\n var _playerInterface2;\n\n if (!_playerInterface) {\n room._log(\"I've been asked for position even if we don't have player attached.\\n Does it mean I'm the master?\");\n\n return Promise.resolve();\n }\n\n var fragmentData = ((_playerInterface2 = _playerInterface) === null || _playerInterface2 === void 0 ? void 0 : _playerInterface2.currentFragment) || {\n fragment: String(\"0\"),\n fragment_pos: Number(parseInt(getCurrentPlayerPosition()))\n };\n\n room._log(\"Sending my position to \".concat(slaveId));\n\n room._log(\"Current time: \".concat(fragmentData.fragment, \" # \").concat(fragmentData.fragment_pos));\n\n return room.sendMessage(room.handleId, {\n body: {\n request: \"sync_response\",\n room: room.roomId,\n timestamp: new Date().getTime(),\n slave_id: room.webrtcVersion > 1000 ? String(slaveId) : Number(slaveId),\n ...fragmentData\n }\n });\n };\n\n const getSyncData = () => {\n var _playerInterface3;\n\n room._log('Sending roomSync request');\n\n let roomId = room.roomId;\n var fragmentData = ((_playerInterface3 = _playerInterface) === null || _playerInterface3 === void 0 ? void 0 : _playerInterface3.currentFragment) || {\n fragment: String(\"0\"),\n fragment_pos: Number(parseInt(getCurrentPlayerPosition()))\n };\n return new Promise((resolve, reject) => {\n let now = new Date().getTime();\n let ping = null;\n let sid = setTimeout(() => {\n room.off('data', fn, this);\n reject('Timeout');\n }, 3000);\n let body = {\n request: \"sync\",\n room: roomId,\n timestamp: new Date().getTime(),\n ...fragmentData\n };\n\n let fn = msg => {\n if (msg.videoroom && ['sync', 'sync_response'].includes(msg.videoroom)) {\n if (msg.sync_master_await) {\n room._log('Waiting for master position');\n\n if (!ping) {\n ping = new Date().getTime() - now;\n }\n } else if (msg.sync_master_fragment || msg.sync_master_fragment_pos) {\n room._log('Got master position data');\n\n if (!ping) {\n ping = new Date().getTime() - now;\n }\n\n room._log(\"I'm master: \".concat(!!msg.sync_master_self));\n\n room._log(\"Ping: \".concat(ping));\n\n room._log(\"Master fragment: \".concat(msg.sync_master_fragment));\n\n room._log(\"Master fragment position: \".concat(msg.sync_master_fragment_pos));\n\n room.off('data', fn, this);\n clearTimeout(sid);\n resolve({\n isMaster: !!msg.sync_master_self,\n ping: ping,\n masterFragmentPos: parseInt(msg.sync_master_fragment_pos),\n masterFragmentSn: parseInt(msg.sync_master_fragment)\n });\n } else {\n clearTimeout(sid);\n reject('Master lost connection');\n }\n }\n };\n\n room.on('data', fn, this);\n room.sendMessage(room.handleId, {\n body\n }).then(fn).catch(e => {\n room.off('data', fn, this);\n clearTimeout(sid);\n reject(e);\n });\n });\n };\n\n const clientPaused = () => {\n room._log('Sending client paused');\n\n if (!isConnected()) {\n return Promise.resolve();\n }\n\n return room.sendMessage(room.handleId, {\n body: {\n request: \"sync_paused\",\n room: room.roomId,\n timestamp: new Date().getTime(),\n fragment: '0',\n fragment_pos: 0\n }\n });\n };\n\n const propagateMasterFunc = () => {\n room._log('Propagating master');\n\n if (!isConnected()) {\n return Promise.resolve();\n }\n\n return room.sendMessage(room.handleId, {\n body: {\n request: \"sync_source_set\",\n room: room.roomId,\n timestamp: new Date().getTime(),\n wt_channel_id: \"\",\n fragment: \"0\",\n fragment_pos: 0\n }\n });\n };\n\n return {\n __events: ['playerSyncing'],\n initialize: function () {\n let {\n playerInterface,\n propagateMaster = false\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _playerInterface = playerInterface;\n _playerInterfaceOptions = { ..._playerInterfaceOptions,\n ...(_playerInterface.syncSettings || {})\n };\n _propagateMaster = propagateMaster;\n\n room._log('Interface options passed: ', _playerInterface.syncSettings || {});\n\n room._log('All interface options: ', _playerInterfaceOptions);\n\n if (_playerInterfaceOptions.type === 'none') {\n room._log('Sync module has been disabled via type:none');\n\n return;\n }\n\n if (_playerInterfaceOptions.type === 'push') {\n room._log('Push sync is not implemented in this sync module yet');\n\n return;\n }\n\n if (_playerInterface.isVod) {\n room._log('VOD sync is not implemented in this sync module yet');\n\n return;\n }\n\n playerInterface.addHandlers({\n handlePause: event => {\n room._log('handlePause');\n\n _emitter.emit('pause', event);\n },\n handlePlaying: event => {\n room._log('handlePlaying');\n\n _emitter.emit('playing', event);\n },\n handleBuffering: event => {\n room._log('handleBuffering');\n\n _emitter.emit('buffering', event);\n\n _emitter.emit('stalled', event);\n },\n handleTimeupdate: event => {\n room._log('handleTimeupdate');\n\n _emitter.emit('timeupdate', event);\n }\n });\n isPlaying = _playerInterface.isPaused === false;\n room.on('disconnect', stopSyncLoop);\n room.on('removeLocalParticipant', stopSyncLoop);\n room.on('addLocalParticipant', handleAddLocalParticipant);\n room.on('addRemoteParticipant', handleAddRemoteParticipant);\n room.on('data', parseDataEvents);\n\n if (_propagateMaster) {\n propagateMasterFunc().catch(() => {});\n }\n\n if (_playerInterface.isPaused === false) {\n _emitter.once('timeupdate', restartSyncLoop);\n }\n\n _emitter.on('buffering', handleBuffering);\n\n _emitter.on('playing', handlePlaying);\n\n _emitter.on('pause', handlePause);\n },\n destroy: () => {\n stopSyncLoop();\n room.off('disconnect', stopSyncLoop);\n room.off('removeLocalParticipant', stopSyncLoop);\n room.off('addLocalParticipant', handleAddLocalParticipant);\n room.off('addRemoteParticipant', handleAddRemoteParticipant);\n room.off('data', parseDataEvents);\n _playerInterface = null;\n\n _emitter.clear();\n }\n };\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (syncModule);\n\n//# sourceURL=webpack://WatchTogetherSDK/./src/modules/sync-modules/sync-module.js?");
9310
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _wt_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../wt-utils */ \"./src/modules/wt-utils.js\");\n/* harmony import */ var _wt_emitter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../wt-emitter */ \"./src/modules/wt-emitter.js\");\n\n\n\nconst syncModule = function () {\n let {\n room,\n emitter\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n //SYNC VARS\n let _emitter = Object(_wt_emitter__WEBPACK_IMPORTED_MODULE_1__[\"default\"])();\n\n let _playerInterface = null;\n let _propagateMaster = false;\n let _playerInterfaceOptions = {\n type: 'none',\n ignoreBufferedTimeRanges: true,\n disableFastSeek: false\n };\n const syncDefaultWaitTime = 60000;\n const syncShortWaitTime = 10000;\n const maxSyncThreshold = 0.5;\n const maxSyncTries = 3;\n const waitForPlayingEventAfterSeek = 5000;\n const fastForwardThreshold = 4;\n let currentSyncRetry = 0;\n let syncWaitId = null;\n let syncNextWaitTime = null;\n let stopFlag = false;\n let isSyncing = false;\n let safeSpace = 2;\n let playbackRate = 2;\n let isPlaying = false;\n let isPreloading = true;\n let isProgrammaticallySeeked = false;\n\n const startSyncLoop = () => {\n if (!isConnected()) {\n room._log('--- Sync loop will not start due to user not connected yet ---');\n\n return;\n }\n\n if (syncWaitId) {\n room._log('--- Sync loop already running ---');\n\n return;\n }\n\n room._log('--- Sync enabled ---');\n\n stopFlag = false;\n\n if (!_playerInterfaceOptions.type === 'push') {\n const loop = () => {\n isSyncing = true;\n emitter.emit('playerSyncing', true);\n sync().finally(() => {\n isSyncing = false;\n emitter.emit('playerSyncing', false);\n\n if (isConnected() && !stopFlag) {\n syncWaitId = setTimeout(loop, syncNextWaitTime);\n } else {\n room._log('--- Automatic stop due to user not connected or stop flag enabled ---');\n\n stopSyncLoop();\n }\n });\n };\n\n loop();\n } else {\n const loop2 = () => {\n seekForward().then(() => {\n setNextWaitTime(false);\n }).catch(e => {\n setNextWaitTime(true);\n console.log('Sync failed', e);\n });\n syncWaitId = setTimeout(loop2, syncNextWaitTime);\n };\n\n loop2();\n } //TODO: push sync\n\n };\n\n const stopSyncLoop = doNotResetRetryCount => {\n room._log('--- Sync disabled ---');\n\n clearTimeout(syncWaitId);\n syncWaitId = null;\n\n if (!doNotResetRetryCount) {\n currentSyncRetry = 0;\n }\n\n stopFlag = true;\n };\n\n const restartSyncLoop = () => {\n room._log('--- Sync restarting ---');\n\n stopSyncLoop();\n startSyncLoop();\n };\n\n const setNextWaitTime = function () {\n let didSyncFail = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n if (!didSyncFail) {\n syncNextWaitTime = syncDefaultWaitTime;\n currentSyncRetry = 0;\n } else {\n currentSyncRetry++;\n\n if (currentSyncRetry > maxSyncTries) {\n syncNextWaitTime = syncDefaultWaitTime;\n currentSyncRetry = 0;\n } else {\n syncNextWaitTime = syncShortWaitTime;\n }\n }\n\n room._log('--- Next sync will occur in ' + syncNextWaitTime / 1000 + ' seconds ---');\n };\n\n const sync = () => {\n return getSyncData().then(syncData => {\n if (syncData.isMaster) {\n if (_playerInterface.isPaused) _playerInterface.play();\n setNextWaitTime(false);\n return Promise.resolve();\n } else if (_propagateMaster) {\n setNextWaitTime(false);\n return propagateMasterFunc();\n } else {\n const syncStartTime = Date.now();\n const {\n position,\n realPosition,\n isBufferSufficient\n } = _playerInterface.getTimeDifference ? _playerInterface.getTimeDifference(syncData.masterFragmentSn, syncData.masterFragmentPos, syncData.ping) : getTimeDifference(syncData.masterFragmentSn, syncData.masterFragmentPos, syncData.ping);\n\n if (position && Math.abs(position) <= maxSyncThreshold) {\n room._log(\"We're within max sync threshold, no need to resync now\");\n\n setNextWaitTime(false);\n return Promise.resolve();\n }\n\n if (position !== null && !isNaN(position)) {\n return seekBy(position).then(() => {\n const seekDuration = Date.now() - syncStartTime;\n const {\n position,\n realPosition,\n isBufferSufficient\n } = _playerInterface.getTimeDifference ? _playerInterface.getTimeDifference(syncData.masterFragmentSn, syncData.masterFragmentPos + seekDuration, syncData.ping) : getTimeDifference(syncData.masterFragmentSn, syncData.masterFragmentPos + seekDuration, syncData.ping);\n const syncPrecision = Math.abs(realPosition);\n\n room._log(\"Insufficient buffer: \", !isBufferSufficient);\n\n room._log(\"Seek duration is \".concat(seekDuration / 1000, \" seconds\"));\n\n room._log(\"Sync precision should be \".concat(syncPrecision));\n\n const didSyncFail = syncPrecision > maxSyncThreshold;\n setNextWaitTime(didSyncFail);\n return Promise.resolve();\n }).catch(e => {\n room._log(\"Seek failed: \", e);\n\n setNextWaitTime(true);\n return Promise.reject(e);\n });\n } else {\n room._log(\"Position in not a number: \", position);\n\n setNextWaitTime(true);\n return Promise.reject();\n }\n }\n }).catch(e => {\n room._log(\"getSyncData() failed: \", e);\n\n setNextWaitTime(true);\n return Promise.reject();\n });\n };\n\n const handleAddLocalParticipant = () => {\n if (_propagateMaster) {\n propagateMasterFunc();\n }\n\n if (_playerInterface.isPaused === false) {\n _emitter.once('timeupdate', restartSyncLoop);\n }\n };\n\n const handleAddRemoteParticipant = () => {\n if (_propagateMaster) {\n propagateMasterFunc();\n }\n };\n\n const isConnected = () => {\n return room._isDataChannelOpen && room.isConnected;\n };\n\n const parseDataEvents = function () {\n let msg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n if (msg.videoroom === 'sync_request') {\n roomSyncSend(msg.sync_slave_id).catch(() => {});\n }\n };\n\n const getCurrentPlayerPosition = () => {\n let position = _playerInterface.currentTime;\n return isNaN(position) ? 0 : position * 1000;\n };\n\n const getTimeDifference = (fragmentSn, fragmentPos, ping) => {\n let seekRanges = _playerInterface.buffered;\n let position = (fragmentPos + ping / 2) / 1000;\n let currentPlayerPosition = getCurrentPlayerPosition() / 1000;\n\n if (seekRanges && !_playerInterfaceOptions.ignoreBufferedTimeRanges) {\n let seekRange = {};\n\n for (let i = 0; i < seekRanges.length; i++) {\n let _c_start = seekRanges.start(i);\n\n let _c_end = seekRanges.end(i);\n\n if (!seekRange.start || _c_start < seekRange.start) {\n seekRange.start = _c_start;\n }\n\n if (!seekRange.end || _c_end > seekRange.end) {\n seekRange.end = _c_end;\n }\n }\n\n if (position > seekRange.start && position < seekRange.end) {\n return {\n position: position - currentPlayerPosition,\n realPosition: position - currentPlayerPosition,\n isBufferSufficient: true\n };\n } else if (position < seekRange.start) {\n room._log(\"Syncing to \".concat(seekRange.start, \" instead of \").concat(position, \" due to lack of buffered data\"));\n\n return {\n position: seekRange.start + 0.5 - currentPlayerPosition,\n realPosition: position - currentPlayerPosition,\n isBufferSufficient: false\n };\n } else if (position > seekRange.end) {\n room._log(\"Syncing to \".concat(seekRange.end, \" instead of \").concat(position, \" due to lack of buffered data\"));\n\n return {\n position: seekRange.end - 0.5 - currentPlayerPosition,\n realPosition: position - currentPlayerPosition,\n isBufferSufficient: false\n };\n } else return {\n position: null,\n isBufferSufficient: false\n };\n } else {\n return {\n position: position - currentPlayerPosition,\n realPosition: position - currentPlayerPosition,\n isBufferSufficient: true\n };\n }\n };\n\n const seekForward = () => {\n return new Promise((resolve, reject) => {\n let diff = _playerInterface.buffered.end(0) - _playerInterface.currentTime;\n\n let diff_target = diff - safeSpace;\n\n let __ = () => {\n _playerInterface.setPlaybackRate(1);\n\n isProgrammaticallySeeked = false;\n isSyncing = false;\n reject('Stalled');\n };\n\n console.log('Users stream is behind behind live by:', diff);\n\n if (diff_target > 0) {\n _emitter.once('stalled', __);\n\n Object(_wt_utils__WEBPACK_IMPORTED_MODULE_0__[\"setExactTimeout\"])(() => {\n _playerInterface.setPlaybackRate(1);\n\n isProgrammaticallySeeked = false;\n isSyncing = false;\n\n _emitter.off('stalled', __);\n\n resolve();\n }, diff_target * 1000 / playbackRate, 20);\n isProgrammaticallySeeked = true;\n isSyncing = true;\n\n _playerInterface.setPlaybackRate(playbackRate);\n } else {\n resolve();\n }\n });\n };\n\n const seekBy = time => {\n return new Promise((resolve, reject) => {\n if (_playerInterface.currentTime !== time) {\n if (time > 0 && time < fastForwardThreshold && !_playerInterfaceOptions.disableFastSeek) {\n room._log(\"Fast forward to seek...\");\n\n let wasPaused = false;\n\n let _handleFailed = () => {\n if (wasPaused) {\n _playerInterface.pause();\n }\n\n _playerInterface.setPlaybackRate(1);\n\n isProgrammaticallySeeked = false;\n reject('Stalled');\n };\n\n let _fastForward = () => {\n isProgrammaticallySeeked = true;\n Object(_wt_utils__WEBPACK_IMPORTED_MODULE_0__[\"setExactTimeout\"])(() => {\n _emitter.off('stalled', _handleFailed);\n\n if (wasPaused && _playerInterface.isVod) {\n _playerInterface.pause();\n }\n\n _playerInterface.setPlaybackRate(1);\n\n isProgrammaticallySeeked = false;\n resolve();\n }, time * 1000 / (playbackRate - 1), 20);\n\n _playerInterface.setPlaybackRate(playbackRate);\n };\n\n _emitter.once('stalled', _handleFailed);\n\n if (_playerInterface.isPaused) {\n wasPaused = true;\n\n _playerInterface.play().then(() => {\n _fastForward();\n }).catch(_handleFailed);\n } else {\n _fastForward();\n }\n } else {\n room._log(\"Jump to seek...\");\n\n let currentTimestamp = Date.now();\n let __failsafeId = null;\n\n let _resolve = () => {\n clearTimeout(__failsafeId);\n __failsafeId = null;\n isProgrammaticallySeeked = false;\n\n room._log(\"It took the player \".concat((Date.now() - currentTimestamp) / 1000, \" seconds to seek \"));\n\n resolve();\n };\n\n isProgrammaticallySeeked = true; // we need to ignore stall events since those are false alarm\n\n _emitter.once('playing', _resolve);\n\n __failsafeId = setTimeout(_resolve, waitForPlayingEventAfterSeek);\n\n _playerInterface.seek(_playerInterface.currentTime + time);\n }\n } else resolve();\n });\n };\n\n const seekTo = time => {\n return new Promise((resolve, reject) => {\n if (_playerInterface.currentTime !== time) {\n let diff = time - _playerInterface.currentTime;\n\n if (_playerInterface.currentTime < time && diff < fastForwardThreshold && !_playerInterfaceOptions.disableFastSeek) {\n room._log(\"Fast forward to seek...\");\n\n let wasPaused = false;\n\n let _handleFailed = () => {\n if (wasPaused) {\n _playerInterface.pause();\n }\n\n _playerInterface.setPlaybackRate(1);\n\n isProgrammaticallySeeked = false;\n reject('Stalled');\n };\n\n let _fastForward = () => {\n isProgrammaticallySeeked = true;\n Object(_wt_utils__WEBPACK_IMPORTED_MODULE_0__[\"setExactTimeout\"])(() => {\n _emitter.off('stalled', _handleFailed);\n\n if (wasPaused && _playerInterface.isVod) {\n _playerInterface.pause();\n }\n\n _playerInterface.setPlaybackRate(1);\n\n isProgrammaticallySeeked = false;\n resolve();\n }, diff * 1000 / (playbackRate - 1), 20);\n\n _playerInterface.setPlaybackRate(playbackRate);\n };\n\n _emitter.once('stalled', _handleFailed);\n\n if (_playerInterface.isPaused) {\n wasPaused = true;\n\n _playerInterface.play().then(() => {\n _fastForward();\n }).catch(_handleFailed);\n } else {\n _fastForward();\n }\n } else {\n room._log(\"Jump to seek...\");\n\n let currentTimestamp = Date.now();\n let __failsafeId = null;\n\n let _resolve = () => {\n clearTimeout(__failsafeId);\n __failsafeId = null;\n isProgrammaticallySeeked = false;\n\n room._log(\"It took the player \".concat((Date.now() - currentTimestamp) / 1000, \" seconds to seek \"));\n\n resolve();\n };\n\n isProgrammaticallySeeked = true; // we need to ignore stall events since those are false alarm\n\n _emitter.once('playing', _resolve);\n\n __failsafeId = setTimeout(_resolve, waitForPlayingEventAfterSeek);\n\n _playerInterface.seek(time);\n }\n } else resolve();\n });\n };\n\n const handlePlaying = () => {\n if (!isProgrammaticallySeeked) {\n room._log('Handle playing');\n\n startSyncLoop();\n }\n\n isProgrammaticallySeeked = false;\n isPreloading = _playerInterface.isPaused;\n isPlaying = !_playerInterface.isPaused;\n };\n\n const handlePause = () => {\n stopSyncLoop();\n clientPaused().catch(() => {});\n isPlaying = !_playerInterface.isPaused;\n };\n\n const handleBuffering = () => {\n room._log('handleBuffering');\n\n if (!isProgrammaticallySeeked) {\n stopSyncLoop(true);\n clientPaused().catch(() => {});\n isPreloading = _playerInterface.isPaused;\n }\n };\n\n const roomSyncSend = slaveId => {\n var _playerInterface2;\n\n if (!_playerInterface) {\n room._log(\"I've been asked for position even if we don't have player attached.\\n Does it mean I'm the master?\");\n\n return Promise.resolve();\n }\n\n var fragmentData = ((_playerInterface2 = _playerInterface) === null || _playerInterface2 === void 0 ? void 0 : _playerInterface2.currentFragment) || {\n fragment: String(\"0\"),\n fragment_pos: Number(parseInt(getCurrentPlayerPosition()))\n };\n\n room._log(\"Sending my position to \".concat(slaveId));\n\n room._log(\"Current time: \".concat(fragmentData.fragment, \" # \").concat(fragmentData.fragment_pos));\n\n return room.sendMessage(room.handleId, {\n body: {\n request: \"sync_response\",\n room: room.roomId,\n timestamp: new Date().getTime(),\n slave_id: room.webrtcVersion > 1000 ? String(slaveId) : Number(slaveId),\n ...fragmentData\n }\n });\n };\n\n const getSyncData = () => {\n var _playerInterface3;\n\n room._log('Sending roomSync request');\n\n let roomId = room.roomId;\n var fragmentData = ((_playerInterface3 = _playerInterface) === null || _playerInterface3 === void 0 ? void 0 : _playerInterface3.currentFragment) || {\n fragment: String(\"0\"),\n fragment_pos: Number(parseInt(getCurrentPlayerPosition()))\n };\n return new Promise((resolve, reject) => {\n let now = new Date().getTime();\n let ping = null;\n let sid = setTimeout(() => {\n room.off('data', fn, this);\n reject('Timeout');\n }, 3000);\n let body = {\n request: \"sync\",\n room: roomId,\n timestamp: new Date().getTime(),\n ...fragmentData\n };\n\n let fn = msg => {\n if (msg.videoroom && ['sync', 'sync_response'].includes(msg.videoroom)) {\n if (msg.sync_master_await) {\n room._log('Waiting for master position');\n\n if (!ping) {\n ping = new Date().getTime() - now;\n }\n } else if (msg.sync_master_fragment || msg.sync_master_fragment_pos) {\n room._log('Got master position data');\n\n if (!ping) {\n ping = new Date().getTime() - now;\n }\n\n room._log(\"I'm master: \".concat(!!msg.sync_master_self));\n\n room._log(\"Ping: \".concat(ping));\n\n room._log(\"Master fragment: \".concat(msg.sync_master_fragment));\n\n room._log(\"Master fragment position: \".concat(msg.sync_master_fragment_pos));\n\n room.off('data', fn, this);\n clearTimeout(sid);\n resolve({\n isMaster: !!msg.sync_master_self,\n ping: ping,\n masterFragmentPos: parseInt(msg.sync_master_fragment_pos),\n masterFragmentSn: parseInt(msg.sync_master_fragment)\n });\n } else {\n clearTimeout(sid);\n reject('Master lost connection');\n }\n }\n };\n\n room.on('data', fn, this);\n room.sendMessage(room.handleId, {\n body\n }).then(fn).catch(e => {\n room.off('data', fn, this);\n clearTimeout(sid);\n reject(e);\n });\n });\n };\n\n const clientPaused = () => {\n room._log('Sending client paused');\n\n if (!isConnected()) {\n return Promise.resolve();\n }\n\n return room.sendMessage(room.handleId, {\n body: {\n request: \"sync_paused\",\n room: room.roomId,\n timestamp: new Date().getTime(),\n fragment: '0',\n fragment_pos: 0\n }\n });\n };\n\n const propagateMasterFunc = () => {\n room._log('Propagating master');\n\n if (!isConnected()) {\n return Promise.resolve();\n }\n\n return room.sendMessage(room.handleId, {\n body: {\n request: \"sync_source_set\",\n room: room.roomId,\n timestamp: new Date().getTime(),\n wt_channel_id: \"\",\n fragment: \"0\",\n fragment_pos: 0\n }\n });\n };\n\n return {\n __events: ['playerSyncing'],\n initialize: function () {\n let {\n playerInterface,\n propagateMaster = false\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _playerInterface = playerInterface;\n _playerInterfaceOptions = { ..._playerInterfaceOptions,\n ...(_playerInterface.syncSettings || {})\n };\n _propagateMaster = propagateMaster;\n\n room._log('Interface options passed: ', _playerInterface.syncSettings || {});\n\n room._log('All interface options: ', _playerInterfaceOptions);\n\n if (_playerInterfaceOptions.type === 'none') {\n room._log('Sync module has been disabled via type:none');\n\n return;\n } // if(_playerInterfaceOptions.type === 'push') {\n // \troom._log('Push sync is not implemented in this sync module yet');\n // \treturn;\n // }\n\n\n if (_playerInterface.isVod) {\n room._log('VOD sync is not implemented in this sync module yet');\n\n return;\n }\n\n playerInterface.addHandlers({\n handlePause: event => {\n room._log('handlePause');\n\n _emitter.emit('pause', event);\n },\n handlePlaying: event => {\n room._log('handlePlaying');\n\n _emitter.emit('playing', event);\n },\n handleBuffering: event => {\n room._log('handleBuffering');\n\n _emitter.emit('buffering', event);\n\n _emitter.emit('stalled', event);\n },\n handleTimeupdate: event => {\n room._log('handleTimeupdate');\n\n _emitter.emit('timeupdate', event);\n }\n });\n isPlaying = _playerInterface.isPaused === false;\n room.on('disconnect', stopSyncLoop);\n room.on('removeLocalParticipant', stopSyncLoop);\n room.on('addLocalParticipant', handleAddLocalParticipant);\n room.on('addRemoteParticipant', handleAddRemoteParticipant);\n room.on('data', parseDataEvents);\n\n if (_propagateMaster) {\n propagateMasterFunc().catch(() => {});\n }\n\n if (_playerInterface.isPaused === false) {\n _emitter.once('timeupdate', restartSyncLoop);\n }\n\n _emitter.on('buffering', handleBuffering);\n\n _emitter.on('playing', handlePlaying);\n\n _emitter.on('pause', handlePause);\n },\n destroy: () => {\n stopSyncLoop();\n room.off('disconnect', stopSyncLoop);\n room.off('removeLocalParticipant', stopSyncLoop);\n room.off('addLocalParticipant', handleAddLocalParticipant);\n room.off('addRemoteParticipant', handleAddRemoteParticipant);\n room.off('data', parseDataEvents);\n _playerInterface = null;\n\n _emitter.clear();\n }\n };\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (syncModule);\n\n//# sourceURL=webpack://WatchTogetherSDK/./src/modules/sync-modules/sync-module.js?");
9311
9311
 
9312
9312
  /***/ }),
9313
9313
 
@@ -9415,7 +9415,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */
9415
9415
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
9416
9416
 
9417
9417
  "use strict";
9418
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var aws_iot_device_sdk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! aws-iot-device-sdk */ \"./node_modules/aws-iot-device-sdk/index.js\");\n/* harmony import */ var aws_iot_device_sdk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(aws_iot_device_sdk__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _wt_emitter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./wt-emitter */ \"./src/modules/wt-emitter.js\");\n/* harmony import */ var _wt_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./wt-utils */ \"./src/modules/wt-utils.js\");\n\n\n\n\nclass Iot {\n constructor(enableDebugFlag) {\n Object.assign(this, Object(_wt_emitter__WEBPACK_IMPORTED_MODULE_1__[\"default\"])());\n this.device = null;\n this.decoder = new TextDecoder('utf-8');\n this.connectionActive = false;\n this.log = Iot.noop;\n this.debugFlag = enableDebugFlag;\n this.credentialsExpirationCheckIntervalId = null;\n this.currentCredentialsExpirationStamp = null;\n\n if (enableDebugFlag) {\n this.enableDebug();\n }\n }\n\n static noop() {}\n\n enableDebug() {\n this.log = console.log.bind(console);\n }\n\n startCredentialsExpirationCheck(expiration) {\n this.stopCredentialsExpirationCheck();\n this.currentCredentialsExpirationStamp = new Date(expiration).getTime();\n this.credentialsExpirationCheckIntervalId = setInterval(() => {\n const curentTimeStamp = new Date().getTime();\n\n if (this.currentCredentialsExpirationStamp - curentTimeStamp <= 300000) {\n this.emit('updateCredentials');\n }\n }, 5000);\n }\n\n stopCredentialsExpirationCheck() {\n clearInterval(this.credentialsExpirationCheckIntervalId);\n this.credentialsExpirationCheckIntervalId = null;\n }\n\n updateWebSocketCredentials(accessKeyId, secretAccessKey, sessionToken, expiration) {\n if (this.device) {\n this.device.updateWebSocketCredentials(accessKeyId, secretAccessKey, sessionToken);\n this.startCredentialsExpirationCheck(expiration);\n }\n }\n\n connect(apiMqttUrl, apiMqttClientId, region, accessKeyId, secretAccessKey, sessionToken, expiration) {\n let forceDisconnect = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;\n return this.disconnect(forceDisconnect).then(() => {\n return new Promise((resolve, reject) => {\n this.device = Object(aws_iot_device_sdk__WEBPACK_IMPORTED_MODULE_0__[\"device\"])({\n protocol: 'wss',\n clientId: apiMqttClientId,\n region,\n host: apiMqttUrl,\n accessKeyId: accessKeyId,\n secretKey: secretAccessKey,\n sessionToken: sessionToken,\n keepalive: 15,\n maximumReconnectTimeMs: 8000,\n enableMetrics: false,\n debug: this.debugFlag,\n autoResubscribe: true\n });\n this.startCredentialsExpirationCheck(expiration);\n\n let __s = () => {\n var _this$device, _this$device2;\n\n (_this$device = this.device) === null || _this$device === void 0 ? void 0 : _this$device.off('connect', __s);\n (_this$device2 = this.device) === null || _this$device2 === void 0 ? void 0 : _this$device2.off('error', __e);\n resolve(this.device);\n };\n\n let __e = e => {\n var _this$device3, _this$device4;\n\n (_this$device3 = this.device) === null || _this$device3 === void 0 ? void 0 : _this$device3.off('connect', __s);\n (_this$device4 = this.device) === null || _this$device4 === void 0 ? void 0 : _this$device4.off('error', __e);\n reject(e);\n };\n\n this.device.once('connect', __s);\n this.device.once('error', __e);\n this.device.on('message', this.__messageCb.bind(this));\n this.device.on('connect', this.__connectCb.bind(this));\n this.device.on('reconnect', this.__reconnectCb.bind(this));\n this.device.on('error', this.__failureCb.bind(this));\n this.device.on('close', this.__closeCb.bind(this));\n this.device.on('offline', this.__offlineCb.bind(this));\n });\n });\n }\n\n disconnect() {\n let force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n this.stopCredentialsExpirationCheck();\n return new Promise((resolve, reject) => {\n if (!this.device) {\n resolve();\n return;\n }\n\n let __i = null;\n\n let __c = () => {\n clearTimeout(__i);\n this.device = null;\n resolve();\n };\n\n __i = setTimeout(__c, 4000);\n this.device.off('message', this.__messageCb.bind(this));\n this.device.off('connect', this.__connectCb.bind(this));\n this.device.off('reconnect', this.__reconnectCb.bind(this));\n this.device.off('error', this.__failureCb.bind(this));\n this.device.off('close', this.__closeCb.bind(this));\n this.device.off('offline', this.__offlineCb.bind(this));\n this.device.end(force, __c);\n });\n }\n\n isConnected() {\n return this.connectionActive;\n }\n\n subscribe(topic) {\n return this.device && this.device.subscribe(topic);\n }\n\n unsubscribe(topic) {\n return this.device && this.device.unsubscribe(topic);\n }\n\n send(topic, message) {\n let msg = typeof message === 'object' ? JSON.stringify(message) : message;\n return this.device && this.device.publish(topic, msg);\n }\n\n __reconnectCb() {\n this.emit('reconnect');\n }\n\n __connectCb() {\n this.connectionActive = true;\n this.emit('connect');\n }\n\n __failureCb(err) {\n this.emit('error', err);\n }\n\n __closeCb(responseObject) {\n this.connectionActive = false;\n this.emit('close');\n }\n\n __offlineCb(responseObject) {\n this.emit('offline');\n }\n\n __messageCb(t, message, packet) {\n const topic = t.split('/');\n let payload = JSON.parse(this.decoder.decode(message));\n\n if (payload.display) {\n const decodedDisplay = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(payload.display);\n\n if (decodedDisplay.userId) {\n payload = { ...payload,\n userId: decodedDisplay.userId,\n role: decodedDisplay.role\n };\n }\n }\n\n if (topic[0] === 'user') {\n // user\n const userId = topic[1].replace(\"_\", ':');\n this.emit('message', {\n userId,\n ...payload,\n event: payload.event ? \"user:\".concat(payload.event) : 'user'\n });\n } else if (topic[0] === 'wt') {\n const event = payload.event;\n const roomId = topic[2];\n\n if (topic[1] === 'room') {\n // room\n if (event === 'message' || event === 'template_updated' || event === 'record_start' || event === 'record_stop' || event === 'record_configured' || event === 'record_livestream_available' || event === 'record_livestream_kick' || event === 'user_update_displayname' || event === 'user_update_avatar' || event === 'user_update_customattributes' || event === 'user_update_privateattributes' || event === 'channel_changed' || event === \"instance_homepage_changed\" || event === \"instance_settings_changed\" || event === \"externalmix_changed\" || event === \"video_uploaded\" || event === \"change_user_devices\" || event === \"queue\" || event === \"title_changed\") {\n this.emit('message', {\n event,\n ...payload,\n roomId\n });\n } else if (event === 'joined' || event === 'leaving') {\n this.emit('message', {\n event,\n ...payload,\n isObserver: !!payload.isObserver,\n roomId\n });\n } else if (event === 'left' || //user removed room a.k.a. left the room\n event === 'kicked' || event === 'banned' || event === 'unbanned' || event === 'approved' || event === 'muted' || event === 'unmuted' || event === 'messageRemoved' || event === 'messageReported' || event === 'chatClear' || event === 'handRaised' || event === 'handLowered' || event === 'handsCleared') {\n this.emit('message', {\n event,\n ...payload\n });\n } else if (event === 'volume_set') {\n this.emit('message', {\n event,\n ...payload\n });\n }\n } else if (topic[1] === 'instanceroom') {\n // instance\n if (event === 'add_room' || event === 'remove_room' || event === 'set_room' || event === \"instance_homepage_changed\" || event === 'instance_settings_changed') {\n this.emit('message', {\n event,\n ...payload\n });\n }\n } else if (topic[1] === 'externalmix') {\n const event = payload.event;\n this.emit('message', {\n event,\n ...payload\n });\n }\n } else if (topic[0] === 'wtr') {\n const recorderId = topic[1];\n const sessionId = topic[2];\n\n if (topic[3] === 'control') {\n this.emit('message', {\n event: 'recorder_control',\n ...payload,\n recorderId,\n sessionId\n });\n } // recorder control\n else if (topic[3] === 'monitor') {\n this.emit('message', {\n event: 'recorder_monitor',\n ...payload,\n recorderId,\n sessionId\n });\n } // recorder monitor\n\n }\n }\n\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Iot);\n\n//# sourceURL=webpack://WatchTogetherSDK/./src/modules/wt-iot.js?");
9418
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var aws_iot_device_sdk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! aws-iot-device-sdk */ \"./node_modules/aws-iot-device-sdk/index.js\");\n/* harmony import */ var aws_iot_device_sdk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(aws_iot_device_sdk__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _wt_emitter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./wt-emitter */ \"./src/modules/wt-emitter.js\");\n/* harmony import */ var _wt_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./wt-utils */ \"./src/modules/wt-utils.js\");\n\n\n\n\nclass Iot {\n constructor(enableDebugFlag) {\n Object.assign(this, Object(_wt_emitter__WEBPACK_IMPORTED_MODULE_1__[\"default\"])());\n this.device = null;\n this.decoder = new TextDecoder('utf-8');\n this.connectionActive = false;\n this.log = Iot.noop;\n this.debugFlag = enableDebugFlag;\n this.credentialsExpirationCheckIntervalId = null;\n this.currentCredentialsExpirationStamp = null;\n\n if (enableDebugFlag) {\n this.enableDebug();\n }\n }\n\n static noop() {}\n\n enableDebug() {\n this.log = console.log.bind(console);\n }\n\n startCredentialsExpirationCheck(expiration) {\n this.stopCredentialsExpirationCheck();\n this.currentCredentialsExpirationStamp = new Date(expiration).getTime();\n this.credentialsExpirationCheckIntervalId = setInterval(() => {\n const curentTimeStamp = new Date().getTime();\n\n if (this.currentCredentialsExpirationStamp - curentTimeStamp <= 300000) {\n this.emit('updateCredentials');\n }\n }, 5000);\n }\n\n stopCredentialsExpirationCheck() {\n clearInterval(this.credentialsExpirationCheckIntervalId);\n this.credentialsExpirationCheckIntervalId = null;\n }\n\n updateWebSocketCredentials(accessKeyId, secretAccessKey, sessionToken, expiration) {\n if (this.device) {\n this.device.updateWebSocketCredentials(accessKeyId, secretAccessKey, sessionToken);\n this.startCredentialsExpirationCheck(expiration);\n }\n }\n\n connect(apiMqttUrl, apiMqttClientId, region, accessKeyId, secretAccessKey, sessionToken, expiration) {\n let forceDisconnect = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;\n return this.disconnect(forceDisconnect).then(() => {\n return new Promise((resolve, reject) => {\n this.device = Object(aws_iot_device_sdk__WEBPACK_IMPORTED_MODULE_0__[\"device\"])({\n protocol: 'wss',\n clientId: apiMqttClientId,\n region,\n host: apiMqttUrl,\n accessKeyId: accessKeyId,\n secretKey: secretAccessKey,\n sessionToken: sessionToken,\n keepalive: 15,\n maximumReconnectTimeMs: 8000,\n enableMetrics: false,\n debug: this.debugFlag,\n autoResubscribe: true\n });\n this.startCredentialsExpirationCheck(expiration);\n\n let __s = () => {\n var _this$device, _this$device2;\n\n (_this$device = this.device) === null || _this$device === void 0 ? void 0 : _this$device.off('connect', __s);\n (_this$device2 = this.device) === null || _this$device2 === void 0 ? void 0 : _this$device2.off('error', __e);\n resolve(this.device);\n };\n\n let __e = e => {\n var _this$device3, _this$device4;\n\n (_this$device3 = this.device) === null || _this$device3 === void 0 ? void 0 : _this$device3.off('connect', __s);\n (_this$device4 = this.device) === null || _this$device4 === void 0 ? void 0 : _this$device4.off('error', __e);\n reject(e);\n };\n\n this.device.once('connect', __s);\n this.device.once('error', __e);\n this.device.on('message', this.__messageCb.bind(this));\n this.device.on('connect', this.__connectCb.bind(this));\n this.device.on('reconnect', this.__reconnectCb.bind(this));\n this.device.on('error', this.__failureCb.bind(this));\n this.device.on('close', this.__closeCb.bind(this));\n this.device.on('offline', this.__offlineCb.bind(this));\n });\n });\n }\n\n disconnect() {\n let force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n this.stopCredentialsExpirationCheck();\n return new Promise((resolve, reject) => {\n if (!this.device) {\n resolve();\n return;\n }\n\n let __i = null;\n\n let __c = () => {\n clearTimeout(__i);\n this.device = null;\n resolve();\n };\n\n __i = setTimeout(__c, 4000);\n this.device.off('message', this.__messageCb.bind(this));\n this.device.off('connect', this.__connectCb.bind(this));\n this.device.off('reconnect', this.__reconnectCb.bind(this));\n this.device.off('error', this.__failureCb.bind(this));\n this.device.off('close', this.__closeCb.bind(this));\n this.device.off('offline', this.__offlineCb.bind(this));\n this.device.end(force, __c);\n });\n }\n\n isConnected() {\n return this.connectionActive;\n }\n\n subscribe(topic) {\n return this.device && this.device.subscribe(topic);\n }\n\n unsubscribe(topic) {\n return this.device && this.device.unsubscribe(topic);\n }\n\n send(topic, message) {\n let msg = typeof message === 'object' ? JSON.stringify(message) : message;\n return this.device && this.device.publish(topic, msg);\n }\n\n __reconnectCb() {\n this.emit('reconnect');\n }\n\n __connectCb() {\n this.connectionActive = true;\n this.emit('connect');\n }\n\n __failureCb(err) {\n this.emit('error', err);\n }\n\n __closeCb(responseObject) {\n this.connectionActive = false;\n this.emit('close');\n }\n\n __offlineCb(responseObject) {\n this.emit('offline');\n }\n\n __messageCb(t, message, packet) {\n const topic = t.split('/');\n let payload = JSON.parse(this.decoder.decode(message));\n\n if (payload.display) {\n const decodedDisplay = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(payload.display);\n\n if (decodedDisplay.userId) {\n payload = { ...payload,\n userId: decodedDisplay.userId,\n role: decodedDisplay.role,\n start: decodedDisplay.start\n };\n }\n }\n\n if (topic[0] === 'user') {\n // user\n const userId = topic[1].replace(\"_\", ':');\n this.emit('message', {\n userId,\n ...payload,\n event: payload.event ? \"user:\".concat(payload.event) : 'user'\n });\n } else if (topic[0] === 'wt') {\n const event = payload.event;\n const roomId = topic[2];\n\n if (topic[1] === 'room') {\n // room\n if (event === 'message' || event === 'template_updated' || event === 'record_start' || event === 'record_stop' || event === 'record_configured' || event === 'record_livestream_available' || event === 'record_livestream_kick' || event === 'user_update_displayname' || event === 'user_update_avatar' || event === 'user_update_customattributes' || event === 'user_update_privateattributes' || event === 'channel_changed' || event === \"instance_homepage_changed\" || event === \"instance_settings_changed\" || event === \"externalmix_changed\" || event === \"video_uploaded\" || event === \"change_user_devices\" || event === \"queue\" || event === \"title_changed\") {\n this.emit('message', {\n event,\n ...payload,\n roomId\n });\n } else if (event === 'joined' || event === 'leaving') {\n this.emit('message', {\n event,\n ...payload,\n isObserver: !!payload.isObserver,\n roomId\n });\n } else if (event === 'left' || //user removed room a.k.a. left the room\n event === 'kicked' || event === 'banned' || event === 'unbanned' || event === 'approved' || event === 'muted' || event === 'unmuted' || event === 'messageRemoved' || event === 'messageReported' || event === 'chatClear' || event === 'handRaised' || event === 'handLowered' || event === 'handsCleared') {\n this.emit('message', {\n event,\n ...payload\n });\n } else if (event === 'volume_set') {\n this.emit('message', {\n event,\n ...payload\n });\n }\n } else if (topic[1] === 'instanceroom') {\n // instance\n if (event === 'add_room' || event === 'remove_room' || event === 'set_room' || event === \"instance_homepage_changed\" || event === 'instance_settings_changed') {\n this.emit('message', {\n event,\n ...payload\n });\n }\n } else if (topic[1] === 'externalmix') {\n const event = payload.event;\n this.emit('message', {\n event,\n ...payload\n });\n }\n } else if (topic[0] === 'wtr') {\n const recorderId = topic[1];\n const sessionId = topic[2];\n\n if (topic[3] === 'control') {\n this.emit('message', {\n event: 'recorder_control',\n ...payload,\n recorderId,\n sessionId\n });\n } // recorder control\n else if (topic[3] === 'monitor') {\n this.emit('message', {\n event: 'recorder_monitor',\n ...payload,\n recorderId,\n sessionId\n });\n } // recorder monitor\n\n }\n }\n\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Iot);\n\n//# sourceURL=webpack://WatchTogetherSDK/./src/modules/wt-iot.js?");
9419
9419
 
9420
9420
  /***/ }),
9421
9421