@clickview/lite 0.103.0-rc.0 → 0.103.1
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.
- package/dist/.vite/manifest.json +447 -447
- package/dist/bundles.json +1 -1
- package/dist/en.json +1 -1
- package/dist/scripts/{BXosUOUS.chunk.js → 14z5Gy8L.chunk.js} +2 -2
- package/dist/scripts/{BXosUOUS.chunk.js.map → 14z5Gy8L.chunk.js.map} +1 -1
- package/dist/scripts/{BqkK_0Jk2.chunk.js → B4AZn1xm2.chunk.js} +2 -2
- package/dist/scripts/{BqkK_0Jk2.chunk.js.map → B4AZn1xm2.chunk.js.map} +1 -1
- package/dist/scripts/{_wBbQ-0z2.chunk.js → BBndy2td2.chunk.js} +2 -2
- package/dist/scripts/{_wBbQ-0z2.chunk.js.map → BBndy2td2.chunk.js.map} +1 -1
- package/dist/scripts/{DBdkd4Ag2.chunk.js → BFH_tnSb2.chunk.js} +3 -3
- package/dist/scripts/{DBdkd4Ag2.chunk.js.map → BFH_tnSb2.chunk.js.map} +1 -1
- package/dist/scripts/{BhgNNQjX.chunk.js → BOQck-Qs.chunk.js} +2 -2
- package/dist/scripts/{BhgNNQjX.chunk.js.map → BOQck-Qs.chunk.js.map} +1 -1
- package/dist/scripts/{_eRiDJm1.chunk.js → Ba4uGz_V.chunk.js} +2 -2
- package/dist/scripts/{_eRiDJm1.chunk.js.map → Ba4uGz_V.chunk.js.map} +1 -1
- package/dist/scripts/{Bx6qaXLc.chunk.js → Bdbe2u0R.chunk.js} +2 -2
- package/dist/scripts/{Bx6qaXLc.chunk.js.map → Bdbe2u0R.chunk.js.map} +1 -1
- package/dist/scripts/{C4CuJJXy2.chunk.js → BeW5XQTb2.chunk.js} +2 -2
- package/dist/scripts/{C4CuJJXy2.chunk.js.map → BeW5XQTb2.chunk.js.map} +1 -1
- package/dist/scripts/{syYCrnUX.chunk.js → BgoVmaXQ.chunk.js} +2 -2
- package/dist/scripts/{syYCrnUX.chunk.js.map → BgoVmaXQ.chunk.js.map} +1 -1
- package/dist/scripts/{B5DWwtp0.chunk.js → BjA9XV5y.chunk.js} +2 -2
- package/dist/scripts/{B5DWwtp0.chunk.js.map → BjA9XV5y.chunk.js.map} +1 -1
- package/dist/scripts/{BYMMqtaN.chunk.js → BqdHoEFM.chunk.js} +2 -2
- package/dist/scripts/{BYMMqtaN.chunk.js.map → BqdHoEFM.chunk.js.map} +1 -1
- package/dist/scripts/{BIvmcqND2.chunk.js → CCUznsdX2.chunk.js} +2 -2
- package/dist/scripts/{BIvmcqND2.chunk.js.map → CCUznsdX2.chunk.js.map} +1 -1
- package/dist/scripts/{BsNCh4UD.chunk.js → CFqL2Hm5.chunk.js} +3 -3
- package/dist/scripts/{BsNCh4UD.chunk.js.map → CFqL2Hm5.chunk.js.map} +1 -1
- package/dist/scripts/{BE8Ze3Fa2.chunk.js → CHmbcl4Y2.chunk.js} +2 -2
- package/dist/scripts/{BE8Ze3Fa2.chunk.js.map → CHmbcl4Y2.chunk.js.map} +1 -1
- package/dist/scripts/{Dp8z_udC.chunk.js → CIzlhCeS.chunk.js} +2 -2
- package/dist/scripts/{Dp8z_udC.chunk.js.map → CIzlhCeS.chunk.js.map} +1 -1
- package/dist/scripts/{CO8EIpI8.chunk.js → CXUrMkZu.chunk.js} +2 -2
- package/dist/scripts/{CO8EIpI8.chunk.js.map → CXUrMkZu.chunk.js.map} +1 -1
- package/dist/scripts/{DLqG-wwP.chunk.js → CYrelpYt.chunk.js} +2 -2
- package/dist/scripts/{DLqG-wwP.chunk.js.map → CYrelpYt.chunk.js.map} +1 -1
- package/dist/scripts/{wmwWqIeA.chunk.js → CfrfHGSh.chunk.js} +2 -2
- package/dist/scripts/{wmwWqIeA.chunk.js.map → CfrfHGSh.chunk.js.map} +1 -1
- package/dist/scripts/{B5M-3wpn.chunk.js → CjwT65ug.chunk.js} +2 -2
- package/dist/scripts/{B5M-3wpn.chunk.js.map → CjwT65ug.chunk.js.map} +1 -1
- package/dist/scripts/{B-aaIChO2.chunk.js → CsCjBSq62.chunk.js} +2 -2
- package/dist/scripts/{B-aaIChO2.chunk.js.map → CsCjBSq62.chunk.js.map} +1 -1
- package/dist/scripts/{ygwO7HPs2.chunk.js → DIaT_eGy2.chunk.js} +2 -2
- package/dist/scripts/{ygwO7HPs2.chunk.js.map → DIaT_eGy2.chunk.js.map} +1 -1
- package/dist/scripts/{DXRsxBJw.chunk.js → DTliAJ8L.chunk.js} +2 -2
- package/dist/scripts/{DXRsxBJw.chunk.js.map → DTliAJ8L.chunk.js.map} +1 -1
- package/dist/scripts/{DE5jvfAx2.chunk.js → D_t70KgV2.chunk.js} +2 -2
- package/dist/scripts/{DE5jvfAx2.chunk.js.map → D_t70KgV2.chunk.js.map} +1 -1
- package/dist/scripts/{Dc01PBv1.chunk.js → Dn2EPvQj.chunk.js} +2 -2
- package/dist/scripts/{Dc01PBv1.chunk.js.map → Dn2EPvQj.chunk.js.map} +1 -1
- package/dist/scripts/{RuVwpX36.chunk.js → Drh1bb9z.chunk.js} +2 -2
- package/dist/scripts/{RuVwpX36.chunk.js.map → Drh1bb9z.chunk.js.map} +1 -1
- package/dist/scripts/{YzhKditE.chunk.js → ESLgHTNq.chunk.js} +2 -2
- package/dist/scripts/{YzhKditE.chunk.js.map → ESLgHTNq.chunk.js.map} +1 -1
- package/dist/scripts/{DfSzsD3P.chunk.js → FysETOFv.chunk.js} +2 -2
- package/dist/scripts/{DfSzsD3P.chunk.js.map → FysETOFv.chunk.js.map} +1 -1
- package/dist/scripts/QVwuOts3.chunk.js +12 -0
- package/dist/scripts/QVwuOts3.chunk.js.map +1 -0
- package/dist/scripts/{OmYpHs7g.chunk.js → _Cm5O72d.chunk.js} +3 -3
- package/dist/scripts/{OmYpHs7g.chunk.js.map → _Cm5O72d.chunk.js.map} +1 -1
- package/dist/scripts/{app-BzCWmnrr.js → app-BHlllGhO.js} +4 -4
- package/dist/scripts/{app-BzCWmnrr.js.map → app-BHlllGhO.js.map} +1 -1
- package/dist/scripts/{C46080Xd.chunk.js → dxqgnrOi.chunk.js} +2 -2
- package/dist/scripts/{C46080Xd.chunk.js.map → dxqgnrOi.chunk.js.map} +1 -1
- package/dist/scripts/{BCTM3KG42.chunk.js → kLCNzxrH2.chunk.js} +2 -2
- package/dist/scripts/{BCTM3KG42.chunk.js.map → kLCNzxrH2.chunk.js.map} +1 -1
- package/dist/scripts/{CfVIZBcI2.chunk.js → wpRpI9h02.chunk.js} +2 -2
- package/dist/scripts/{CfVIZBcI2.chunk.js.map → wpRpI9h02.chunk.js.map} +1 -1
- package/package.json +1 -1
- package/dist/scripts/QrUfkwZX.chunk.js +0 -12
- package/dist/scripts/QrUfkwZX.chunk.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BhgNNQjX.chunk.js","names":[],"sources":["../../../player/src/plugins/create-clip-button-plugin/components/create-clip-button.scss","../../../player/src/plugins/create-clip-button-plugin/components/create-clip-button.ts","../../../player/src/plugins/create-clip-button-plugin/create-clip-button-plugin.ts","../../../player/src/plugins/picture-in-picture-plugin/components/picture-in-picture-toggle.ts","../../../player/src/plugins/picture-in-picture-plugin/picture-in-picture-plugin.ts","../../../player/src/plugins/points-of-interest-plugin/components/point-of-interest-indicator/point-of-interest-indicator.ts","../../../player/src/plugins/points-of-interest-plugin/components/points-of-interest-menu-item/points-of-interest-menu-item.ts","../../../player/src/plugins/points-of-interest-plugin/points-of-interest-plugin.ts","../../../player/src/plugins/range-indicator-plugin/components/range-indicator/range-indicator.ts","../../../player/src/plugins/range-indicator-plugin/components/replay-view-button/replay-view-button.ts","../../../player/src/plugins/range-indicator-plugin/components/replay-view/replay-view.ts","../../../player/src/plugins/range-indicator-plugin/range-indicator-plugin.ts","../../../player/src/utils/id-helper.ts","../../../player/src/players/player.ts","../../../player/src/plugins/devices-plugin/utils/resilient-web-socket.ts","../../../player/src/plugins/devices-plugin/clients/vivi/vivi-cast-session-state.ts","../../../player/src/plugins/devices-plugin/clients/vivi/vivi-interfaces.ts","../../../player/src/plugins/devices-plugin/clients/vivi/vivi-cast-session.ts","../../../player/src/plugins/devices-plugin/clients/vivi/vivi-client.ts","../../../player/src/plugins/devices-plugin/devices-session-manager.ts","../../../player/src/plugins/devices-plugin/components/device-menu-item/device-menu-item.ts","../../../player/src/plugins/devices-plugin/components/devices-menu/devices-menu.ts","../../../player/src/plugins/devices-plugin/components/devices-cta/devices-cta.tsx","../../../player/src/plugins/devices-plugin/components/devices-button/devices-button.ts","../../../player/src/plugins/devices-plugin/tech/devices-tech-ui/devices-tech-ui.ts","../../../player/src/plugins/devices-plugin/tech/devices-tech.ts","../../../player/src/plugins/devices-plugin/devices-plugin.ts","../../../player/src/plugins/resources-plugin/components/resource-menu-item/resource-menu-item.tsx","../../../player/src/plugins/resources-plugin/components/resources-button/resources-button.ts","../../../player/src/plugins/resources-plugin/resources-plugin.ts","../../../player/src/react/Player.tsx"],"sourcesContent":[".video-js {\n .cv-create-clip-button {\n width: 4em;\n padding: 0;\n\n .vjs-icon-placeholder::before {\n font-family: CVPlayer;\n /* Defined in font/icon-map.js */\n content: unquote(\"\\\"\\\\f10e\\\"\");\n }\n }\n}\n","import videojs from 'video.js';\n\nimport { CollapsibleComponent } from 'projects/player/interfaces/CollapsibleComponent';\n\nconst Button = videojs.getComponent('Button');\n\nimport './create-clip-button.scss';\n\nclass CreateClipButton extends Button implements CollapsibleComponent {\n public controlText_: string;\n\n public buildCSSClass(): string {\n return 'cv-create-clip-button';\n }\n\n /**\n * CollapsibleComponent interface implementation below\n */\n public alwaysCollapsed: boolean = false;\n\n public isCollapsed: boolean = false;\n\n public isCollabsible: boolean = true;\n\n public getCollabsibleName(): string {\n return this.controlText_;\n }\n \n public getCollabsibleValue(): string {\n return '';\n }\n \n public showInCollabsibleMenu(): boolean {\n return true;\n }\n \n public showCollapsibleMenu(): void {\n super.handleClick(null);\n }\n}\n\nCreateClipButton.prototype.controlText_ = 'Create clip';\n\nvideojs.registerComponent('CreateClipButton', CreateClipButton);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport 'projects/player/plugins/create-clip-button-plugin/components/create-clip-button';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface CreateClipButtonPluginOptions {\n onClick: () => void;\n}\n\nclass CreateClipButtonPlugin extends Plugin {\n private options: CreateClipButtonPluginOptions;\n\n constructor(player: VideoJsPlayer, options: CreateClipButtonPluginOptions) {\n super(player, options);\n\n this.options = options;\n\n player.ready(() => this.onReady());\n }\n\n private onReady(): void {\n const collapserator = this.player.getChild('collapserator');\n\n if (!collapserator)\n return;\n\n collapserator.addChild('CreateClipButton', {\n clickHandler: this.options.onClick\n });\n }\n}\n\nvideojs.registerPlugin('createClipButtonPlugin', CreateClipButtonPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n createClipButtonPlugin(options: CreateClipButtonPluginOptions): void;\n }\n}\n","import videojs from 'video.js';\n\nconst BasePictureInPictureToggle = videojs.getComponent('PictureInPictureToggle');\n\nclass PictureInPictureToggle extends BasePictureInPictureToggle {\n handlePictureInPictureEnabledChange() {\n (this as any).enable();\n }\n}\n\nvideojs.registerComponent('PictureInPictureToggle', PictureInPictureToggle);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport './picture-in-picture.scss';\n\nimport './components/picture-in-picture-toggle';\n\nconst PlayToggle = videojs.getComponent('PlayToggle');\n\nconst Plugin = videojs.getPlugin('plugin');\n\nconst MIN_WIDTH = 800;\n\ninterface PictureInPicturePluginOptions {\n onRequestPictureInPicture: (isPiP: boolean) => void;\n}\n\nclass PictureInPicturePlugin extends Plugin {\n private options: PictureInPicturePluginOptions;\n private playerRequestPictureInPictureFn: () => Promise<videojs.PictureInPictureWindow>;\n private playerExitPictureInPictureFn: () => Promise<void>;\n private playToggle: videojs.Component;\n private toggle: videojs.Button;\n\n constructor(player: VideoJsPlayer, options: PictureInPicturePluginOptions) {\n super(player, options);\n\n this.options = options;\n\n this.bindFunctions();\n player.ready(() => this.initialize());\n }\n\n private bindFunctions(): void {\n this.requestPictureInPicture = this.requestPictureInPicture.bind(this);\n this.exitPictureInPicture = this.exitPictureInPicture.bind(this);\n this.onPlayerResize = this.onPlayerResize.bind(this);\n \n this.playerRequestPictureInPictureFn = this.player.requestPictureInPicture;\n this.playerExitPictureInPictureFn = this.player.exitPictureInPicture;\n \n this.player.requestPictureInPicture = this.requestPictureInPicture;\n this.player.exitPictureInPicture = this.exitPictureInPicture;\n }\n\n public initialize(): void {\n const toggleParent = this.player.getChild('collapserator');\n\n this.toggle = toggleParent.addChild('pictureInPictureToggle', {}) as videojs.Button;\n\n /**\n * By default the toggle is initialised in a disabled state.\n */\n this.toggle.enable();\n\n this.player.on('playerresize', this.onPlayerResize);\n\n this.player.on('dispose', () => {\n this.player?.off('playerresize', this.onPlayerResize);\n });\n }\n\n public togglePictureInPicture(isInPictureInPicture: boolean): void {\n if (isInPictureInPicture === this.player.isInPictureInPicture())\n return;\n\n const event = isInPictureInPicture ?\n 'enterpictureinpicture' :\n 'leavepictureinpicture';\n\n this.player.isInPictureInPicture(isInPictureInPicture);\n this.player.trigger(event);\n\n isInPictureInPicture ? this.addPipStyles() : this.removePipStyles();\n }\n\n private onPlayerResize(): void {\n /**\n * Don't enable/disable PiP while in PiP.\n */\n if (this.player.isInPictureInPicture())\n return;\n\n const playerRect = this.player.el().getBoundingClientRect();\n\n /**\n * In case our update function runs before our\n * player has properly rendered within the DOM\n */\n if (playerRect.width === 0)\n return;\n\n if (playerRect.width < MIN_WIDTH)\n this.toggle?.hide();\n else\n this.toggle?.show();\n }\n\n private addPipStyles(): void {\n this.player.addClass('cv-picture-in-picture');\n this.playToggle = new PlayToggle(this.player);\n this.playToggle.addClass('cv-pip-play-toggle');\n this.player.addChild(this.playToggle);\n\n if (this.player.paused())\n (this.playToggle as any).handlePause();\n else\n (this.playToggle as any).handlePlay();\n }\n\n private removePipStyles(): void {\n this.player.removeClass('cv-picture-in-picture');\n this.player.removeChild(this.playToggle);\n delete this.playToggle;\n }\n \n private requestPictureInPicture(): Promise<videojs.PictureInPictureWindow> {\n this.togglePictureInPicture(true);\n\n if (typeof this.options?.onRequestPictureInPicture === 'function')\n this.options.onRequestPictureInPicture(true);\n\n return;\n }\n\n private async exitPictureInPicture(): Promise<void> {\n this.togglePictureInPicture(false);\n this.options.onRequestPictureInPicture(false);\n this.removePipStyles();\n }\n\n public dispose(): void {\n this.player.requestPictureInPicture = this.playerRequestPictureInPictureFn;\n this.player.exitPictureInPicture = this.playerExitPictureInPictureFn;\n super.dispose();\n }\n}\n\nvideojs.registerPlugin('pictureInPicture', PictureInPicturePlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n pictureInPicture(options?: PictureInPicturePluginOptions): PictureInPicturePlugin;\n isInPictureInPicture(isPiP?: boolean): boolean | void;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { EventsService, StaticEventsService } from 'libs/common/react/services/EventsService';\n\nimport { PointOfInterest } from 'libs/shared/interfaces';\n\nimport { MouseTimeDisplay } from 'projects/player/components/mouse-time-display/mouse-time-display';\nimport { TimeTooltip } from 'projects/player/components/time-tooltip/time-tooltip';\n\nimport './point-of-interest-indicator.scss';\n\nconst Component = videojs.getComponent('Component');\n\ninterface PointOfInterestIndicatorOptions extends videojs.ComponentOptions {\n pointOfInterest: PointOfInterest;\n}\n\nexport class PointOfInterestIndicator extends Component {\n private el_: HTMLElement;\n public options_: PointOfInterestIndicatorOptions;\n\n private eventsService: StaticEventsService;\n\n private pointOfInterest: PointOfInterest;\n private hasBuffered: boolean = false;\n private hasPlayed: boolean = false;\n\n constructor(player: VideoJsPlayer, options: PointOfInterestIndicatorOptions) {\n super(player, options);\n\n this.eventsService = EventsService;\n\n this.pointOfInterest = options.pointOfInterest;\n\n this.onMouseOver = this.onMouseOver.bind(this);\n this.onMouseLeave = this.onMouseLeave.bind(this);\n this.onGlancePointOfInterestMouseEnter = this.onGlancePointOfInterestMouseEnter.bind(this);\n this.onGlancePointOfInterestMouseLeave = this.onGlancePointOfInterestMouseLeave.bind(this);\n\n this.initialize();\n }\n\n public initialize(): void {\n this.setPosition();\n this.bindListeners();\n }\n\n public buildCSSClass(): string {\n return `cv-point-of-interest-indicator ${super.buildCSSClass()}`;\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n return super.createEl(tagName, {\n ...properties,\n className: this.buildCSSClass()\n }, attributes);\n }\n\n private bindListeners(): void {\n this.on('mouseover', this.onMouseOver);\n this.on('mouseleave', this.onMouseLeave);\n\n this.eventsService.subscribe('glance:poi:mouseover', this.onGlancePointOfInterestMouseEnter);\n this.eventsService.subscribe('glance:poi:mouseleave', this.onGlancePointOfInterestMouseLeave);\n }\n\n public dispose(): void {\n this.eventsService.unsubscribe('glance:poi:mouseover', this.onGlancePointOfInterestMouseEnter);\n this.eventsService.unsubscribe('glance:poi:mouseleave', this.onGlancePointOfInterestMouseLeave);\n }\n\n private getPointOfInterestTime(): number {\n return this.pointOfInterest.startTime;\n }\n\n private setPosition(): void {\n const duration = this.player().duration();\n this.el_.style.left = (this.getPointOfInterestTime() / duration * 100) + '%';\n }\n\n public updateBuffered(bufferEnd: number): void {\n const hasBuffered = this.getPointOfInterestTime() <= bufferEnd;\n\n if (hasBuffered === this.hasBuffered)\n return;\n\n this.hasBuffered = hasBuffered;\n\n const bufferedClassName = 'cv-point-of-interest-indicator-buffered';\n\n if (this.hasBuffered)\n this.addClass(bufferedClassName);\n else\n this.removeClass(bufferedClassName);\n }\n\n public updatePlaybackProgress(currentTime: number): void {\n const hasPlayed = this.getPointOfInterestTime() <= currentTime;\n\n if (hasPlayed === this.hasPlayed)\n return;\n\n this.hasPlayed = hasPlayed;\n\n const className = 'cv-point-of-interest-indicator-played';\n\n if (hasPlayed)\n this.addClass(className);\n else\n this.removeClass(className);\n }\n\n public toggleVisibility(visible: boolean): void {\n const visibilityClassName = 'cv-point-of-interest-indicator-hidden';\n\n if (visible)\n this.removeClass(visibilityClassName);\n else\n this.addClass(visibilityClassName);\n }\n\n /**\n * We want the POI description to be displayed in the TimeTooltip when the user\n * hovers over a POI.\n * Because we don't know the exact time range on the seekbar covered by a POI indicator,\n * TimeTooltip can't use the current time to determine the active POI cue the same way\n * that it does for chapters. So instead we use the mouse events on this component and\n * set it manually.\n */\n private onMouseOver(): void {\n this.setTimeTooltipText();\n this.eventsService.trigger('player:poi:mouseover', this.pointOfInterest);\n }\n\n private onMouseLeave(): void {\n this.clearTimeTooltipText();\n this.eventsService.trigger('player:poi:mouseleave');\n }\n\n private onGlancePointOfInterestMouseEnter(pointOfInterest: PointOfInterest): void {\n if (pointOfInterest.id !== this.pointOfInterest.id)\n return;\n\n this.addClass('cv-point-of-interest-indicator-highlight');\n this.setTimeTooltipTime();\n this.setTimeTooltipText();\n this.positionMouseTimeDisplay();\n this.showMouseTimeDisplay();\n }\n\n private onGlancePointOfInterestMouseLeave(): void {\n this.removeClass('cv-point-of-interest-indicator-highlight');\n this.hideMouseTimeDisplay();\n }\n\n private setTimeTooltipText(): void {\n this.getTimeTooltip()?.setCustomChapterText(this.pointOfInterest.description);\n }\n\n private clearTimeTooltipText(): void {\n this.getTimeTooltip()?.setCustomChapterText();\n }\n\n /**\n * We only need to call this when we're manually forcing the MouseTimeDisplay\n * to show. If it's being triggered natively using pointer events then the time\n * will be set automatically.\n */\n private setTimeTooltipTime(): void {\n const timeTooltip = this.getTimeTooltip();\n timeTooltip?.updateTime(this.getPointOfInterestTime());\n }\n\n private positionMouseTimeDisplay(): void {\n const seekBarEl = this.getSeekBar()?.el();\n\n if (!seekBarEl)\n return;\n\n const seekBarRect = videojs.dom.findPosition(seekBarEl) as ClientRect;\n const point = this.getPointOfInterestTime() / this.player().duration();\n\n this.getMouseTimeDisplay()?.update(seekBarRect, point);\n }\n\n private showMouseTimeDisplay(): void {\n this.getMouseTimeDisplay()?.forceShow();\n }\n\n private hideMouseTimeDisplay(): void {\n this.getMouseTimeDisplay()?.removeForceShow();\n }\n\n private getSeekBar(): videojs.SeekBar {\n return this.player().controlBar\n .getChild('ProgressControl')\n ?.getChild('SeekBar') as videojs.SeekBar;\n }\n\n private getMouseTimeDisplay(): MouseTimeDisplay {\n return this.getSeekBar()\n ?.getChild('MouseTimeDisplay') as MouseTimeDisplay;\n }\n\n private getTimeTooltip(): TimeTooltip {\n return this.getMouseTimeDisplay()\n ?.getChild('TimeTooltip') as TimeTooltip;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport './points-of-interest-menu-item.scss';\n\nconst MenuItem = videojs.getComponent('MenuItem');\n\ninterface PointsOfInterestMenuItemOptions extends videojs.MenuItemOptions {\n pointsOfInterestVisible: boolean;\n}\n\nexport class PointsOfInterestMenuItem extends MenuItem {\n private toggleEl: Element;\n private pointsOfInterestVisible: boolean;\n\n /**\n * Because we want to bind our listener in createEl\n * and createEl runs in super. We store if we've bounud\n * our handler, so we only call bind once and \n * the call to removeEventListener will still work\n */\n private handlerBound: boolean;\n\n constructor(player: VideoJsPlayer, options: PointsOfInterestMenuItemOptions) {\n super(player, options);\n\n this.pointsOfInterestVisible = options.pointsOfInterestVisible;\n this.toggle(this.pointsOfInterestVisible);\n }\n\n public handleToggle(): void {\n this.toggle(!this.pointsOfInterestVisible);\n }\n\n private toggle(state: boolean): void {\n state ? this.toggleOn() : this.toggleOff();\n }\n\n private toggleOn(): void {\n videojs.dom.addClass(this.toggleEl, 'on');\n videojs.dom.setAttribute(this.toggleEl, 'aria-checked', 'true');\n this.pointsOfInterestVisible = true;\n this.player().pointsOfInterestPlugin().togglePointsOfInterest(this.pointsOfInterestVisible);\n }\n\n private toggleOff(): void {\n videojs.dom.removeClass(this.toggleEl, 'on');\n videojs.dom.setAttribute(this.toggleEl, 'aria-checked', 'false');\n this.pointsOfInterestVisible = false;\n this.player().pointsOfInterestPlugin().togglePointsOfInterest(this.pointsOfInterestVisible);\n }\n\n /**\n * Because we extend MenuItem which will close the menu by default\n * we need to halt the event propogation here\n */\n public handleClick(event: videojs.EventTarget.Event): void {\n event.stopImmediatePropagation();\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): HTMLLIElement {\n /**\n * Bind our event listener only once\n * see the comment where handlerBound is defined\n */\n if (!this.handlerBound) {\n this.handleToggle = this.handleToggle.bind(this);\n this.handlerBound = true;\n }\n\n if (this.toggleEl)\n this.toggleEl.removeEventListener('click', this.handleToggle);\n\n this.toggleEl = videojs.dom.createEl('div', {\n className: `custom-toggle custom-toggle-info toggle-option float-end`,\n innerHTML: '<span class=\"handle\"></span></div>'\n });\n videojs.dom.setAttribute(this.toggleEl, 'id', 'poi-toggle');\n videojs.dom.setAttribute(this.toggleEl, 'role', 'switch');\n this.toggleEl.addEventListener('click', this.handleToggle);\n\n const innerHTML = `\n <span for=\"poi-toggle\" class=\"vjs-menu-item-text\">Points of Interest</span>\n <span class=\"cv-toggle-container\"></span>`;\n\n const el = super.createEl(tagName, {\n className: 'vjs-menu-item cv-cog-menu-item cv-poi-toggle',\n innerHTML\n }, attributes);\n\n /**\n * Indexing into the child this way is only safe to do because\n * we know that the el only has two children\n */\n el.children[1].appendChild(this.toggleEl);\n\n return el;\n }\n}\n\nvideojs.registerComponent('PointsOfInterestMenuItem', PointsOfInterestMenuItem);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { PointOfInterest } from 'libs/shared/interfaces';\n\nimport { CogButton } from 'projects/player/components/cog-button/cog-button';\nimport { getBufferedEnd } from 'projects/player/utils/getBufferedEnd';\nimport { LocalStorageHelper } from 'projects/player/utils/local-storage-helper';\n\nimport { PointOfInterestIndicator } from './components/point-of-interest-indicator/point-of-interest-indicator';\nimport { PointsOfInterestMenuItem } from './components/points-of-interest-menu-item/points-of-interest-menu-item';\n\nconst Plugin = videojs.getPlugin('plugin');\n\nconst POINTS_OF_INTEREST = 'cvplayer-points-of-interest';\n\ninterface PointsOfInterestPluginOptions {\n pointsOfInterest: PointOfInterest[];\n}\n\nexport class PointsOfInterestPlugin extends Plugin {\n private pointOfInterestIndicators: PointOfInterestIndicator[] = [];\n private pointsOfInterest?: PointOfInterest[];\n private enabled: boolean = true;\n\n constructor(player: VideoJsPlayer, options?: PointsOfInterestPluginOptions) {\n super(player);\n\n this.pointsOfInterest = options?.pointsOfInterest;\n \n this.initialize = this.initialize.bind(this);\n this.updateBuffered = this.updateBuffered.bind(this);\n this.updatePlaybackProgress = this.updatePlaybackProgress.bind(this);\n\n this.player.one('loadedmetadata', () => this.player.ready(this.initialize));\n }\n\n private initialize(): void {\n if (!this.pointsOfInterest)\n return;\n\n if (LocalStorageHelper.hasLocalStorage() && LocalStorageHelper.get(POINTS_OF_INTEREST) === 'false')\n this.enabled = false;\n\n this.setupTrack();\n this.createPointOfInterestIndicators();\n this.addMenuItem();\n this.bindListeners();\n }\n\n private bindListeners(): void {\n this.player.on('progress', this.updateBuffered);\n this.player.on('timeupdate', this.updatePlaybackProgress);\n\n this.player.on('dispose', () => {\n this.player?.off('progress', this.updateBuffered);\n this.player?.off('timeupdate', this.updatePlaybackProgress);\n });\n }\n\n public togglePointsOfInterest(visible: boolean): void {\n LocalStorageHelper.set(POINTS_OF_INTEREST, visible.toString());\n this.pointOfInterestIndicators.forEach(p => p.toggleVisibility(visible));\n }\n\n private setupTrack(): void {\n const track = this.player.addTextTrack('metadata', 'pointsofinterest') as any;\n\n this.pointsOfInterest.forEach(p => {\n track.addCue({\n startTime: p.startTime,\n endTime: p.endTime,\n text: p.description\n });\n });\n\n track.trigger({\n type: 'loadeddata',\n target: track\n });\n }\n\n private createPointOfInterestIndicators(): void {\n const seekBar = this.player.controlBar.getChild('ProgressControl')?.getChild('SeekBar');\n \n this.pointsOfInterest.forEach(pointOfInterest => {\n const component = new PointOfInterestIndicator(this.player, { pointOfInterest });\n this.pointOfInterestIndicators.push(component);\n seekBar.addChild(component);\n });\n }\n\n private addMenuItem(): void {\n /**\n * Check additionalItemOrder in cog-button.ts if you need to change the order. - Sha\n */\n const cogButton = this.player.getChild('collapserator')?.getChild('cogButton') as CogButton;\n cogButton.addItem({\n ctor: PointsOfInterestMenuItem,\n name: 'PointsOfInterestMenuItem',\n options: { pointsOfInterestVisible: this.enabled }\n });\n }\n\n private updateBuffered(): void {\n this.pointOfInterestIndicators.forEach(p => p.updateBuffered(getBufferedEnd(this.player)));\n }\n\n private updatePlaybackProgress(): void {\n this.pointOfInterestIndicators.forEach(p => p.updatePlaybackProgress(this.player.currentTime()));\n }\n}\n\nvideojs.registerPlugin('pointsOfInterestPlugin', PointsOfInterestPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n pointsOfInterestPlugin(options?: PointsOfInterestPluginOptions): PointsOfInterestPlugin;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport './range-indicator.scss';\n\nconst Component = videojs.getComponent('Component');\n\ninterface RangeIndicatorOptions extends videojs.ComponentOptions {\n time: number;\n}\n\nexport class RangeIndicator extends Component {\n private el_: HTMLElement;\n public options_: RangeIndicatorOptions;\n\n constructor(player: VideoJsPlayer, options: RangeIndicatorOptions) {\n super(player, options);\n\n this.initialize();\n }\n\n public initialize(): void {\n this.setPosition();\n }\n\n public buildCSSClass(): string {\n return `cv-range-indicator ${super.buildCSSClass()}`;\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n return super.createEl(tagName, {\n ...properties,\n className: this.buildCSSClass()\n }, attributes);\n }\n\n private setPosition(): void {\n const duration = this.player().duration();\n this.el_.style.left = (this.options_.time / duration * 100) + '%';\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport './replay-view-button.scss';\n\nconst ClickableComponent = videojs.getComponent('ClickableComponent');\n\ninterface ReplayViewButtonOptions extends videojs.ComponentOptions {\n onPress: () => void;\n label: string;\n iconClassName: 'cv-replay-icon' | 'cv-continue-icon';\n}\n\nexport class ReplayViewButton extends ClickableComponent {\n public options_: ReplayViewButtonOptions;\n\n constructor(player: VideoJsPlayer, options: ReplayViewButtonOptions) {\n super(player, options);\n }\n\n public buildCSSClass(): string {\n return `cv-replay-view-button ${super.buildCSSClass()}`;\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n const el = super.createEl(tagName, {\n ...properties,\n innerHTML: `<span class=\"${this.options_.iconClassName}\"></span><span>${this.options_.label}</span>`,\n className: this.buildCSSClass()\n }, attributes);\n\n return el;\n }\n\n public handleClick() {\n this.options_.onPress();\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { ReplayViewButton } from 'projects/player/plugins/range-indicator-plugin/components/replay-view-button/replay-view-button';\n\nimport './replay-view.scss';\n\nconst Component = videojs.getComponent('Component');\n\ninterface ReplayViewOptions extends videojs.ComponentOptions {\n onContinuePress: () => void;\n onReplayPress: () => void;\n}\n\nexport class ReplayView extends Component {\n public options_: ReplayViewOptions;\n\n constructor(player: VideoJsPlayer, options: ReplayViewOptions) {\n super(player, options);\n }\n\n public buildCSSClass(): string {\n return `cv-replay-view ${super.buildCSSClass()}`;\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n const el = super.createEl(tagName, {\n ...properties,\n className: this.buildCSSClass()\n }, attributes);\n\n const heading = videojs.dom.createEl('h5', {\n innerHTML: this.localize('This clip has finished'),\n className: 'cv-replay-heading'\n });\n\n const buttonContainer = videojs.dom.createEl('div', {\n className: 'cv-button-container'\n });\n\n const replayButton = new ReplayViewButton(this.player_, {\n label: this.localize('Replay clip'),\n iconClassName: 'cv-replay-icon',\n onPress: this.options_.onReplayPress\n });\n\n const continueButton = new ReplayViewButton(this.player_, {\n label: this.localize('Continue watching'),\n iconClassName: 'cv-continue-icon',\n onPress: this.options_.onContinuePress\n });\n\n el.appendChild(heading);\n el.appendChild(buttonContainer);\n \n buttonContainer.appendChild(replayButton.el());\n buttonContainer.appendChild(continueButton.el());\n \n return el;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { RangeIndicator } from './components/range-indicator/range-indicator';\nimport { ReplayView } from './components/replay-view/replay-view';\n\nimport './range-indicator-plugin.scss';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface RangeIndicatorPluginOptions {\n startTime: number;\n endTime: number;\n}\n\nclass RangeIndicatorPlugin extends Plugin {\n private startTime: number;\n private endTime: number;\n private dismissed: boolean;\n private startTimeIndicator?: RangeIndicator;\n private endTimeIndicator?: RangeIndicator;\n private replayView?: ReplayView;\n\n constructor(player: VideoJsPlayer, options: RangeIndicatorPluginOptions) {\n super(player, options);\n\n this.startTime = parseFloat(options.startTime.toPrecision(4));\n this.endTime = parseFloat(options.endTime.toPrecision(4));\n this.dismissed = false;\n \n if (this.startTime > this.endTime)\n throw Error('Range start cannot be greater than range end');\n\n this.bindFunctions();\n this.initialize();\n }\n\n private bindFunctions(): void {\n this.onReady = this.onReady.bind(this);\n this.onTimeUpdateOrSeeked = this.onTimeUpdateOrSeeked.bind(this);\n this.onReplayPress = this.onReplayPress.bind(this);\n this.onContinuePress = this.onContinuePress.bind(this);\n }\n\n private initialize(): void {\n this.player.one('loadedmetadata', () => this.player.ready(this.onReady));\n this.player.on('timeupdate', this.onTimeUpdateOrSeeked);\n this.player.on('seeked', this.onTimeUpdateOrSeeked);\n }\n\n private onReady(): void {\n this.addCssClasses();\n this.showRangeIndicators();\n this.addMaskToProgressBar();\n }\n\n private onTimeUpdateOrSeeked(): void {\n if (this.dismissed) return;\n\n const currentTime = this.player.currentTime();\n\n if (currentTime < this.startTime) {\n this.player.currentTime(this.startTime);\n\n return;\n }\n\n if (currentTime > this.endTime) {\n this.showReplayView();\n this.disablePlayToggle();\n this.player.pause();\n this.player.currentTime(this.endTime);\n\n return;\n }\n }\n\n private onReplayPress(): void {\n this.player.currentTime(this.startTime);\n this.player.play();\n this.hideReplayView();\n this.enablePlayToggle();\n }\n\n private onContinuePress(): void {\n this.dismissed = true;\n this.player.play();\n this.hideRangeIndicators();\n this.removeMaskFromProgressBar();\n this.hideReplayView();\n this.enablePlayToggle();\n this.removeCssClasses();\n }\n\n private showRangeIndicators(): void {\n const seekBar = this.player.controlBar.getChild('ProgressControl')?.getChild('SeekBar');\n\n if (!this.startTimeIndicator) {\n this.startTimeIndicator = new RangeIndicator(this.player, { time: this.startTime });\n seekBar?.addChild(this.startTimeIndicator);\n }\n\n if (!this.endTimeIndicator) {\n this.endTimeIndicator = new RangeIndicator(this.player, { time: this.endTime });\n seekBar?.addChild(this.endTimeIndicator);\n }\n }\n\n private hideRangeIndicators(): void {\n this.startTimeIndicator?.hide();\n this.endTimeIndicator?.hide();\n }\n\n private addMaskToProgressBar(): void {\n const seekBar = this.player.controlBar.getChild('ProgressControl')?.getChild('SeekBar');\n const elements = seekBar?.el().getElementsByClassName('cv-chapter-bar-items');\n\n if (elements && elements.length) {\n const progressBar = elements[0] as HTMLElement;\n const duration = this.player.duration();\n const leftInset = this.startTime / duration * 100;\n const rightInset = 100 - (this.endTime / duration * 100);\n const verticalInset = -5; // Increase the mask vertically to account for the thumbtack during scrubbing\n\n progressBar.style.clipPath = `inset(${verticalInset}em ${rightInset}% ${verticalInset}em ${leftInset}%)`;\n }\n }\n\n private removeMaskFromProgressBar(): void {\n const seekBar = this.player.controlBar.getChild('ProgressControl')?.getChild('SeekBar');\n const elements = seekBar?.el().getElementsByClassName('cv-chapter-bar-items');\n\n if (elements && elements.length) {\n const progressBar = elements[0] as HTMLElement;\n\n progressBar.style.clipPath = '';\n }\n }\n\n private showReplayView(): void {\n if (!this.replayView) {\n this.replayView = new ReplayView(this.player, {\n onContinuePress: this.onContinuePress,\n onReplayPress: this.onReplayPress\n });\n \n this.player.addChild(this.replayView);\n }\n\n this.replayView.show();\n }\n\n private hideReplayView(): void {\n this.replayView?.hide();\n }\n\n private getPlayToggle(): videojs.Button | undefined {\n const collapserator = this.player.getChild('collapserator');\n return collapserator?.getChild('PlayToggle') as videojs.Button;\n }\n\n private enablePlayToggle(): void {\n const playToggle = this.getPlayToggle();\n \n if (playToggle)\n playToggle.enable();\n }\n\n private disablePlayToggle(): void {\n const playToggle = this.getPlayToggle();\n \n if (playToggle)\n playToggle.disable();\n }\n\n private addCssClasses(): void {\n this.player.addClass('cv-range-indicator-plugin');\n }\n\n private removeCssClasses(): void {\n this.player.removeClass('cv-range-indicator-plugin');\n }\n\n public dispose(): void {\n this.removeCssClasses();\n\n this.player.off('timeupdate', this.onTimeUpdateOrSeeked);\n this.player.off('seeked', this.onTimeUpdateOrSeeked);\n \n this.startTimeIndicator?.dispose();\n this.endTimeIndicator?.dispose();\n this.replayView?.dispose();\n\n super.dispose();\n }\n}\n\nvideojs.registerPlugin('rangeIndicatorPlugin', RangeIndicatorPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n rangeIndicatorPlugin(options: RangeIndicatorPluginOptions): void;\n }\n}\n","export const IdHelper = {\n generateRandomId: () => {\n return (window.crypto as any)?.randomUUID?.() ?? Math.random().toString();\n }\n};\n","/* eslint simple-import-sort/imports: 0 */\n\nimport { VideoJsPlayerOptions } from 'video.js';\nimport { BasePlayer, BasePlayerOptions } from './base-player';\n\nimport { PointOfInterest } from 'libs/shared/interfaces';\nimport { ShareActivityStatus } from 'libs/shared/enums/ShareActivityStatus';\nimport 'projects/player/plugins/clip-plugin/clip-plugin';\n\nimport 'projects/player/plugins/create-clip-button-plugin/create-clip-button-plugin';\n\nimport 'projects/player/plugins/picture-in-picture-plugin/picture-in-picture-plugin';\nimport 'projects/player/plugins/points-of-interest-plugin/points-of-interest-plugin';\nimport 'projects/player/plugins/activity-status-plugin/activity-status-plugin';\nimport 'projects/player/plugins/range-indicator-plugin/range-indicator-plugin';\nimport 'projects/player/plugins/theatre-mode-plugin/theatre-mode-plugin';\nimport 'projects/player/plugins/loop-video-plugin/loop-video-plugin';\n\nimport { PlaybackObject } from 'projects/player/interfaces/models/PlaybackObject';\nimport { ClipData } from 'projects/player/interfaces/models/ClipData';\nimport { NextVideo } from 'projects/player/interfaces/NextVideo';\n\nimport { IdHelper } from '../utils/id-helper';\nimport { TrackHelper } from 'projects/player/utils/track-helper';\n\nexport interface PlayerOptions extends BasePlayerOptions {\n showResources?: boolean;\n pointsOfInterest?: PointOfInterest[];\n}\n\nexport class Player extends BasePlayer {\n declare protected options: PlayerOptions;\n\n constructor(id: string | Element, options: PlayerOptions) {\n super(id, options);\n }\n\n protected getPlayerOptions(): VideoJsPlayerOptions {\n const options = super.getPlayerOptions();\n\n if (this.options.allowTranscript) {\n options.allowTranscript = true;\n }\n\n if (options.devicesConfig?.canUserCastToDevices) {\n return {\n ...options,\n techOrder: [ 'devices', ...options.techOrder ],\n devices: {\n instanceId: IdHelper.generateRandomId()\n }\n };\n }\n\n return options;\n }\n\n protected configurePlugins(): void {\n try {\n if (this.options.onClickCreateClip) {\n this.player.createClipButtonPlugin({\n onClick: this.options.onClickCreateClip\n });\n }\n\n if (this.options.onRequestPictureInPicture) {\n this.player.pictureInPicture({\n onRequestPictureInPicture: this.options.onRequestPictureInPicture\n });\n }\n\n if (this.options.pointsOfInterest?.length) {\n this.player.pointsOfInterestPlugin({\n pointsOfInterest: this.options.pointsOfInterest\n });\n }\n\n this.player.loopVideoPlugin({ allowLoop: this.options.allowLoop });\n } catch (ex) {\n console.log('failed to register plugins', ex);\n }\n }\n\n public setNextVideo(nextVideo: NextVideo, playNext: boolean, onPlayNext: () => void): void {\n /**\n * Next video plugin needs to be imported separately to be used \n * This is because it uses react components.\n * We want to keep react out of our main player bundle. - Sha\n */\n if (!this.player.nextVideoPlugin)\n return;\n\n const plugin = this.player.nextVideoPlugin();\n plugin.setNextVideo(nextVideo, playNext, onPlayNext);\n }\n\n public togglePictureInPicture(isInPictureInPicture: boolean): void {\n const plugin = this.player.pictureInPicture();\n\n if (plugin)\n plugin.togglePictureInPicture(isInPictureInPicture);\n }\n\n public toggleTheatreMode(status?: boolean): void {\n const plugin = this.player.theatreModePlugin();\n\n if (plugin)\n plugin.toggleTheatreMode(status, { shouldLog: true });\n }\n\n public toggleTranscript(status?: boolean): void {\n if (!this.player.viewTranscriptPlugin)\n return;\n\n const plugin = this.player.viewTranscriptPlugin();\n\n if (plugin)\n plugin.toggleTranscript(status);\n }\n\n public hasStarted(): boolean {\n return this.player.hasStarted();\n }\n\n protected async additionalSetup(playbackObject: PlaybackObject): Promise<void> {\n // instantiate before calling super\n // ensure the theatreMode is set up first before theatre mode registerAnalytics is called\n if (this.options.onRequestTheatreMode && this.options.allowTheatreMode && this.player.theatreModePlugin) {\n this.player.theatreModePlugin({\n onRequestTheatreMode: this.options.onRequestTheatreMode,\n theatreMode: this.options.theatreMode,\n playbackObject\n });\n }\n\n super.additionalSetup(playbackObject);\n\n /**\n * Resources plugin needs to be imported seperately to be used \n * This is because it uses react components.\n * We want to keep react out of our main player bundle. - Sha\n */\n if (this.options.showResources && playbackObject.resources && this.player.resourcesPlugin) {\n this.player.resourcesPlugin({\n resources: playbackObject.resources.list,\n imageCdnUrl: this.options.imageCdnUrl\n });\n }\n\n if (playbackObject.mediaType === 'MasterClip') {\n const clipData = playbackObject.additionalData as ClipData;\n\n if (clipData === null)\n throw Error('Invalid clip data');\n\n this.player.clipPlugin({\n startTime: clipData.startTime,\n endTime: clipData.endTime\n });\n }\n\n /**\n * The range indicator plugin is only applicable when watching videos\n */\n if (playbackObject.mediaType === 'MasterVideo' && this.options.startTime && this.options.endTime) {\n this.player.rangeIndicatorPlugin({\n startTime: this.options.startTime,\n endTime: this.options.endTime\n });\n }\n }\n\n protected setupAnalyticsDependentPlugins(playbackObject: PlaybackObject): void {\n super.setupAnalyticsDependentPlugins(playbackObject);\n\n if (this.options.allowTranscript) {\n this.player.viewTranscriptPlugin().registerAnalytics(\n this.analyticsService,\n playbackObject\n );\n }\n\n if (this.options.onRequestTheatreMode && this.options.allowTheatreMode && this.player.theatreModePlugin) {\n this.player.theatreModePlugin().registerAnalytics(\n this.analyticsService\n );\n }\n\n /**\n * The devices plugin needs to be imported separately to be used \n * This is because it uses react components.\n * We want to keep react out of our main player bundle. - Sha\n */\n if (this.options.devicesConfig?.canUserCastToDevices && this.player.devicesPlugin) {\n this.player.devicesPlugin({\n ...this.options.devicesConfig,\n userId: parseInt(playbackObject.viewerId),\n title: playbackObject.title,\n analyticsService: this.analyticsService\n });\n }\n }\n\n public setActivityStatus(status: ShareActivityStatus, onToggle: () => void): void {\n const plugin = this.player.activityStatusPlugin();\n plugin.setActivityStatus(status, onToggle);\n }\n\n public useCurrentTranscript(callback: (track: TextTrack) => void, language?: string): void {\n // eslint-disable-next-line react-hooks/rules-of-hooks \n TrackHelper.useMetadataTracks(this.player, 'transcript', callback, language);\n }\n\n public useChapters(callback: (track: TextTrack) => void): void {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n TrackHelper.useChapters(this.player, callback);\n }\n}\n","/**\n * Inspired by https://github.com/marchaos/resilient-websocket\n */\n\nimport { Scheduler } from './scheduler';\n\ntype MessageData = string | ArrayBufferLike | Blob | ArrayBufferView;\n\ninterface ResilientWebSocketOptions {\n reconnectIntervalInMilliseconds?: number;\n heartbeatEnabled?: boolean;\n heartbeatIntervalInMillseconds?: number;\n heartbeatMessage?: MessageData;\n}\n\nconst defaultOptions: ResilientWebSocketOptions = {\n reconnectIntervalInMilliseconds: 3000,\n heartbeatEnabled: false,\n heartbeatIntervalInMillseconds: 10000,\n heartbeatMessage: ''\n};\n\nexport class ResilientWebSocket {\n private readonly url: string;\n private readonly options: ResilientWebSocketOptions;\n \n private webSocket: WebSocket;\n private heartbeat: Scheduler;\n\n public onOpen?: (event: Event) => void;\n public onClose?: (event?: CloseEvent) => void;\n public onMessage?: (event: MessageEvent) => void;\n public onError?: (event: Event) => void;\n \n constructor(url: string, options: ResilientWebSocketOptions = defaultOptions) {\n this.bindFunctions();\n\n this.url = url;\n this.options = { ...defaultOptions, ...options };\n this.webSocket = this.connect();\n this.heartbeat = new Scheduler()\n .schedule(() => this.send(this.options.heartbeatMessage))\n .every(this.options.heartbeatIntervalInMillseconds);\n }\n\n private bindFunctions(): void {\n this.cleanup = this.cleanup.bind(this);\n this.handleOpen = this.handleOpen.bind(this);\n this.handleMessage = this.handleMessage.bind(this);\n this.handleClose = this.handleClose.bind(this);\n this.handleError = this.handleError.bind(this);\n this.connect = this.connect.bind(this);\n this.send = this.send.bind(this);\n this.dipose = this.dipose.bind(this);\n }\n\n private cleanup(): void {\n this.heartbeat.stop();\n\n this.webSocket.removeEventListener('error', this.handleError);\n this.webSocket.removeEventListener('message', this.handleMessage);\n this.webSocket.removeEventListener('open', this.handleOpen);\n this.webSocket.removeEventListener('close', this.handleClose);\n }\n\n private handleOpen(event?: Event): void {\n this.onOpen?.(event);\n\n if (this.options.heartbeatEnabled)\n this.heartbeat.start();\n }\n\n private handleMessage(event: MessageEvent): void {\n this.onMessage?.(event);\n }\n\n private handleClose(event?: CloseEvent): void {\n this.onClose?.(event);\n\n this.cleanup();\n\n setTimeout(() => {\n this.webSocket = this.connect();\n }, this.options.reconnectIntervalInMilliseconds);\n }\n\n private handleError(event: Event): void {\n this.onError?.(event);\n this.handleClose();\n }\n\n public connect(): WebSocket {\n const socket = new WebSocket(this.url);\n \n socket.addEventListener('open', this.handleOpen);\n socket.addEventListener('message', this.handleMessage);\n socket.addEventListener('close', this.handleClose);\n socket.addEventListener('error', this.handleError);\n\n return socket;\n }\n\n public send(data: MessageData): void {\n this.webSocket.send(data);\n }\n\n public dipose(): void {\n this.cleanup();\n this.webSocket.close();\n }\n}\n","import { Device } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\nimport { ProxyHelper } from 'projects/player/plugins/devices-plugin/utils/proxy-helper';\n\nconst PROPERTY_SETTER_DEBOUNCE_DURATION_IN_MILLISECONDS = 2000;\n\nexport class ViviCastSessionState {\n public duration: number | undefined;\n public mute: boolean;\n public videoSource: string;\n public subtitleSource: string;\n public subtitles: boolean;\n public volume: number;\n public title: string;\n public device: Device;\n public ready: boolean;\n public playbackFinished: boolean;\n public debounced: ViviCastSessionState;\n\n private _position: number;\n private _playing: boolean;\n private _timerStartedAt: number = 0;\n\n constructor(title: string, device: Device) {\n this.position = 0;\n this.duration = undefined;\n this.playing = false;\n this.mute = false;\n this.videoSource = '';\n this.subtitleSource = '';\n this.subtitles = false;\n this.volume = 0;\n this.title = title;\n this.device = device;\n this.ready = false;\n this.playbackFinished = false;\n this.debounced = ProxyHelper.withDebouncedSetters(this, PROPERTY_SETTER_DEBOUNCE_DURATION_IN_MILLISECONDS);\n \n return ProxyHelper.withTimestampedSetters(this);\n }\n\n public get position() {\n return this._position + this.getTimerDurationInSeconds();\n }\n \n public set position(val: number) {\n this._position = val;\n this.restartTimer();\n }\n\n public get playing() {\n return this._playing;\n }\n \n public set playing(val: boolean) {\n this._playing = val;\n\n if (val) {\n this.restartTimer();\n } else {\n this._position += this.getTimerDurationInSeconds();\n this.stopTimer();\n }\n }\n\n private restartTimer() {\n this._timerStartedAt = Date.now();\n }\n\n private stopTimer() {\n this._timerStartedAt = 0;\n }\n\n private getTimerDurationInSeconds() {\n if (this._timerStartedAt) {\n const duration = Date.now() - this._timerStartedAt;\n return duration / 1000;\n }\n\n return 0;\n }\n}\n","import { HashObject } from 'libs/common/react/interfaces';\n\nimport { ClientEvents } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\n\nexport interface ViviUrl {\n id?: string;\n url: string;\n title: string;\n suburl: string;\n}\n\nexport interface ViviRoom {\n id: string;\n name: string;\n organisation: string;\n location?: string;\n}\n\nexport interface ViviPlayState {\n duration: number;\n position: number;\n playing: boolean;\n volume: number;\n mute: boolean;\n chapter: number;\n subtitles: boolean;\n}\n\nexport interface ViviOutgoingIdentifyMessage {\n destination: 'relay';\n message: {\n type: 'identify_video_api',\n token: string\n };\n}\n\nexport interface ViviOutgoingRoomsMessage {\n destination: 'relay';\n message: {\n type: 'video_api_rooms'\n };\n}\n\nexport interface ViviOutgoingJoinRoomMessage {\n destination: 'relay';\n message: {\n type: 'connect',\n destination_type: 'box',\n new_destination: string,\n token: string\n };\n}\n\nexport interface ViviOutgoingQueryMessage {\n destination: string;\n message: {\n type: 'message_with_ack',\n name: 'query',\n ack_id: string\n };\n}\n\nexport interface ViviOutgoingQueueLoadMessage {\n destination: string;\n message: {\n type: 'message_with_ack',\n name: 'queue_load',\n ack_id: string,\n payload: {\n urls: ViviUrl[]\n }\n };\n}\n\nexport interface ViviOutgoingPlayMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'video_play',\n payload: HashObject // Yep, we need to send an empty object here\n };\n}\n\nexport interface ViviOutgoingPauseMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'video_pause'\n };\n}\n\nexport interface ViviOutgoingStopMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'video_stop'\n };\n}\n\nexport interface ViviOutgoingSeekMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'video_seek',\n payload: {\n position: number\n }\n };\n}\n\nexport interface ViviOutgoingVolumeMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'set_volume',\n payload: {\n volume: number\n }\n };\n}\n\nexport interface ViviOutgoingMuteMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'set_mute',\n payload: {\n mute: boolean\n }\n };\n}\n\nexport interface ViviOutgoingSubtitleMessage {\n destination: string;\n message: {\n type: 'message_with_ack',\n name: 'set_subtitles',\n ack_id: string,\n payload: {\n subtitles: boolean\n }\n };\n}\n\nexport enum ViviEventName {\n Update = 'update',\n Volume = 'volume',\n Playing = 'playing',\n Paused = 'paused',\n NewChapter = 'new_chapter',\n Stopped = 'stopped',\n Ready = 'ready',\n Mute = 'mute',\n Finished = 'finished',\n Subtitles = 'subtitles'\n}\n\nexport type ViviOutgoingMessage =\n ViviOutgoingIdentifyMessage |\n ViviOutgoingRoomsMessage |\n ViviOutgoingJoinRoomMessage |\n ViviOutgoingQueryMessage |\n ViviOutgoingQueueLoadMessage |\n ViviOutgoingPlayMessage |\n ViviOutgoingPauseMessage |\n ViviOutgoingStopMessage |\n ViviOutgoingSeekMessage |\n ViviOutgoingVolumeMessage |\n ViviOutgoingMuteMessage |\n ViviOutgoingSubtitleMessage;\n\nexport interface ViviIncomingMessageParams {\n level?: number;\n chapter?: number;\n duration?: number;\n position?: number;\n playing?: boolean;\n mute?: boolean;\n subtitles?: boolean;\n queue?: ViviUrl[];\n}\n\nexport interface ViviIncomingMessagePayload {\n play_state?: ViviPlayState;\n urls?: ViviUrl[];\n event?: ViviEventName;\n params?: ViviIncomingMessageParams;\n}\n\nexport interface ViviIncomingMessage {\n source: string;\n message: {\n type: string,\n payload?: ViviIncomingMessagePayload,\n error_type?: string,\n ack_id?: string,\n rooms?: ViviRoom[]\n };\n}\n\nexport interface ViviLoadQueueRequest {\n roomId: string;\n title: string;\n videoSource: string;\n subtitleSource?: string;\n}\n\nexport interface ViviClientEventMap extends ClientEvents {\n message: ViviIncomingMessage;\n connected: void;\n}\n","import { CastSession, Device, SessionConfig, SessionEvents } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\nimport { Event, EventBus } from 'projects/player/plugins/devices-plugin/utils/event-bus';\n\nimport { ViviCastSessionState } from './vivi-cast-session-state';\nimport { ViviClient } from './vivi-client';\nimport { ViviEventName, ViviIncomingMessage, ViviIncomingMessageParams } from './vivi-interfaces';\n\nexport class ViviCastSession extends EventBus<SessionEvents> implements CastSession {\n private client: ViviClient;\n private localState: ViviCastSessionState;\n\n constructor(client: ViviClient, config: SessionConfig) {\n super();\n\n this.client = client;\n this.localState = new ViviCastSessionState(config.title, config.device);\n\n this.bindFunctions();\n this.initialize();\n }\n\n private bindFunctions(): void {\n this.initialize = this.initialize.bind(this);\n this.dispose = this.dispose.bind(this);\n \n this.handleClientConnected = this.handleClientConnected.bind(this);\n this.handleDisconnectMessage = this.handleDisconnectMessage.bind(this);\n this.handleAllVideoMessages = this.handleAllVideoMessages.bind(this);\n this.handleUpdateMessage = this.handleUpdateMessage.bind(this);\n this.handleVolumeMessage = this.handleVolumeMessage.bind(this);\n this.handlePlayingMessage = this.handlePlayingMessage.bind(this);\n this.handlePausedMessage = this.handlePausedMessage.bind(this);\n this.handleFinishedMessage = this.handleFinishedMessage.bind(this);\n this.handleNewChapterMessage = this.handleNewChapterMessage.bind(this);\n this.handleStoppedMessage = this.handleStoppedMessage.bind(this);\n\n this.loadSource = this.loadSource.bind(this);\n this.play = this.play.bind(this);\n this.pause = this.pause.bind(this);\n this.seek = this.seek.bind(this);\n this.setVolume = this.setVolume.bind(this);\n this.isPlaying = this.isPlaying.bind(this);\n this.getPosition = this.getPosition.bind(this);\n this.getDuration = this.getDuration.bind(this);\n this.getVolume = this.getVolume.bind(this);\n }\n\n private initialize(): void {\n // Subscribe to client diposed messages\n this.client.on('dispose', this.dispose);\n\n // Subscribe to client connected messages\n this.client.on('connected', this.handleClientConnected);\n\n // Subscribe to device disconnect messages\n this.client\n .on('message', this.handleDisconnectMessage)\n .filter(msg =>\n msg.source === this.getDevice().id &&\n msg.message.type === 'disconnect');\n\n // Subscribe to device video messages\n this.client\n .on('message', this.handleAllVideoMessages)\n .filter(msg =>\n msg.source === this.getDevice().id &&\n msg.message.type === 'video_event');\n }\n\n public dispose(): void {\n // Cleanup the subscriptions from the initialize function\n this.client.off('dispose', this.dispose);\n this.client.off('connected', this.handleClientConnected);\n this.client.off('message', this.handleDisconnectMessage);\n this.client.off('message', this.handleAllVideoMessages);\n\n // Do our best to signal to the device that we're done with it\n this.client.stop(this.getDevice().id).catch(err => console.error(err));\n\n // Trigger the dispose event\n super.dispose();\n }\n\n private async handleClientConnected(): Promise<void> {\n try {\n await this.client.joinRoom(this.getDevice().id);\n } catch (error) {\n this.trigger('error', error);\n }\n }\n\n private handleDisconnectMessage(): void {\n this.dispose();\n }\n\n private handleAllVideoMessages(msg: ViviIncomingMessage): void {\n const localState = this.localState.debounced;\n const remoteState = msg.message.payload.params || {};\n\n switch (msg.message.payload.event) {\n case ViviEventName.Update:\n this.handleUpdateMessage(localState, remoteState);\n break;\n\n case ViviEventName.NewChapter:\n this.handleNewChapterMessage(localState, remoteState);\n break;\n \n case ViviEventName.Volume:\n this.handleVolumeMessage(localState, remoteState);\n break;\n\n case ViviEventName.Playing:\n this.handlePlayingMessage(localState);\n break;\n\n case ViviEventName.Paused:\n this.handlePausedMessage(localState);\n break;\n\n case ViviEventName.Finished:\n this.handleFinishedMessage(localState);\n break;\n \n case ViviEventName.Stopped:\n this.handleStoppedMessage();\n break;\n }\n }\n\n private handleUpdateMessage(localState: ViviCastSessionState, remoteState: ViviIncomingMessageParams): void {\n if (localState.duration !== remoteState.duration) {\n localState.duration = remoteState.duration;\n this.trigger('durationchange', Event.void);\n }\n\n if (localState.position !== remoteState.position) {\n localState.position = remoteState.position;\n this.trigger('positionchange', Event.void);\n }\n\n if (localState.subtitles !== remoteState.subtitles) {\n localState.subtitles = remoteState.subtitles;\n this.trigger('subtitleschange', Event.void);\n }\n }\n\n private handleVolumeMessage(localState: ViviCastSessionState, remoteState: ViviIncomingMessageParams): void {\n if (localState.volume !== remoteState.level) {\n localState.volume = remoteState.level;\n localState.mute = remoteState.level === 0;\n this.trigger('volumechange', Event.void);\n }\n }\n\n private handlePlayingMessage(localState: ViviCastSessionState): void {\n if (localState.playing !== true) {\n localState.playing = true;\n localState.playbackFinished = false;\n this.trigger('playingchange', Event.void);\n }\n }\n\n private handlePausedMessage(localState: ViviCastSessionState): void {\n if (localState.playing !== false) {\n localState.playing = false;\n this.trigger('playingchange', Event.void);\n }\n }\n\n private handleFinishedMessage(localState: ViviCastSessionState): void {\n if (localState.playbackFinished !== true) {\n localState.playing = false;\n localState.playbackFinished = true;\n this.trigger('playingchange', Event.void);\n }\n }\n\n private handleNewChapterMessage(localState: ViviCastSessionState, remoteState: ViviIncomingMessageParams): void {\n const remoteUrls = remoteState.queue ?? [];\n const remoteChapter = remoteUrls.find(x => x.url === localState.videoSource);\n\n if (!remoteChapter) {\n console.info(`The device is no longer playing the source we loaded - disposing the session`);\n this.dispose();\n return;\n }\n\n if (localState.subtitleSource !== remoteChapter.suburl) {\n localState.subtitleSource = remoteChapter.suburl;\n this.trigger('subtitleschange', Event.void);\n }\n }\n\n private handleStoppedMessage(): void {\n this.dispose();\n }\n\n public async loadSource(videoSource: string, subtitleSource?: string): Promise<void> {\n if (this.localState.videoSource === videoSource && this.localState.subtitleSource === subtitleSource)\n return;\n\n try {\n // Prepare some handy variables\n const roomId = this.getDevice().id;\n const currentPosition = this.getPosition();\n \n // Set the sources\n this.localState.videoSource = videoSource;\n this.localState.subtitleSource = subtitleSource;\n\n // Mark the session as not ready while we're loading a source\n this.localState.ready = false;\n\n // We need to be connected to the room before we can load a source\n await this.client.joinRoom(roomId);\n\n // Load the source\n await this.client.loadQueue({\n title: this.getTitle(),\n roomId,\n videoSource,\n subtitleSource\n });\n\n // Mark the session as ready\n this.localState.ready = true;\n\n // Notify listeners that the source has changed\n this.trigger('sourceloaded', Event.void);\n\n // Seek to where we were before changing sources\n if (currentPosition > 0)\n this.seek(currentPosition);\n\n // We need to explicity set subtitles if we have a subtitle source\n if (subtitleSource)\n this.setSubtitles(subtitleSource);\n } catch (error) {\n console.error(error);\n\n this.trigger('error', new Error('Could not load video on Vivi device'));\n }\n }\n\n public play(): void {\n if (!this.localState.ready)\n return;\n\n if (this.localState.playing !== true) {\n this.localState.playing = true;\n this.client.play(this.getDevice().id);\n this.trigger('playingchange', Event.void);\n }\n }\n\n public pause(): void {\n if (!this.localState.ready)\n return;\n\n if (this.localState.playing !== false) {\n this.localState.playing = false;\n this.client.pause(this.getDevice().id);\n this.trigger('playingchange', Event.void);\n }\n }\n\n public seek(position: number): void {\n if (!this.localState.ready)\n return;\n\n if (this.localState.position !== position) {\n this.localState.position = position;\n this.client.seek(this.getDevice().id, position);\n this.trigger('positionchange', Event.void);\n }\n }\n\n public setVolume(volume: number): void {\n if (!this.localState.ready)\n return;\n\n if (this.localState.volume !== volume) {\n this.localState.volume = volume;\n this.client.setVolume(this.getDevice().id, volume);\n this.trigger('volumechange', Event.void);\n }\n }\n\n public setMuted(muted: boolean): void {\n if (!this.localState.ready)\n return;\n\n if (this.localState.mute !== muted) {\n this.localState.mute = muted;\n this.client.setMuted(this.getDevice().id, muted);\n this.trigger('volumechange', Event.void);\n }\n }\n\n public async setSubtitles(subtitleSource?: string): Promise<void> {\n if (!this.localState.ready)\n return;\n\n if (subtitleSource)\n await this.loadSource(this.localState.videoSource, subtitleSource);\n \n const showSubtitles = !!subtitleSource;\n\n if (this.localState.subtitles !== showSubtitles) {\n this.localState.subtitles = showSubtitles;\n this.client.setSubtitles(this.getDevice().id, showSubtitles);\n this.trigger('subtitleschange', Event.void);\n }\n }\n\n public isPlaying(): boolean {\n return this.localState.playing;\n }\n\n public isPlaybackFinished(): boolean {\n return this.localState.playbackFinished;\n }\n\n public getPosition(): number {\n return this.localState.position;\n }\n\n public getDuration(): number | undefined {\n return this.localState.duration;\n }\n\n public getVolume(): number {\n return this.localState.volume;\n }\n\n public getMuted(): boolean {\n return this.localState.mute;\n }\n\n public getSubtitles(): string | undefined {\n if (this.localState.subtitles)\n return this.localState.subtitleSource;\n }\n\n public getDevice(): Device {\n return this.localState.device;\n }\n\n public getTitle(): string {\n return this.localState.title;\n }\n}\n","import { CastSession, Client, Device, DeviceStatus, DeviceType, SessionConfig } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\nimport { Event, EventBus } from 'projects/player/plugins/devices-plugin/utils/event-bus';\nimport { ResilientWebSocket } from 'projects/player/plugins/devices-plugin/utils/resilient-web-socket';\nimport { Scheduler } from 'projects/player/plugins/devices-plugin/utils/scheduler';\nimport { debounce } from 'projects/player/utils/fn';\nimport { IdHelper } from 'projects/player/utils/id-helper';\n\nimport { ViviCastSession } from './vivi-cast-session';\nimport { ViviClientEventMap, ViviIncomingMessage, ViviLoadQueueRequest, ViviOutgoingMessage, ViviRoom } from './vivi-interfaces';\n\nconst MESSAGE_TIMEOUT_IN_MILLISECONDS = 10000;\nconst MESSAGE_DEBOUNCE_IN_MILLISECONDS = 500;\nconst DEVICE_DISCOVERY_SCHEDULE_IN_MILLISECONDS = 10000;\n\ninterface ViviClientOptions {\n url: string;\n fetchAccessToken: () => Promise<string>;\n}\n\nexport class ViviClient extends EventBus<ViviClientEventMap> implements Client<ViviClientEventMap> {\n private options: ViviClientOptions;\n private webSocket?: ResilientWebSocket;\n private accessToken: string;\n private devices: Device[];\n private devicesFingerprint: string;\n private deviceDiscovery: Scheduler;\n\n private sendMessageDebounced: (msg: ViviOutgoingMessage) => boolean;\n\n constructor(options: ViviClientOptions) {\n super();\n \n this.options = options;\n this.accessToken = '';\n this.devices = [];\n this.devicesFingerprint = '';\n this.deviceDiscovery = new Scheduler();\n\n this.bindFunctions();\n this.initialize();\n }\n\n private bindFunctions(): void {\n this.initialize = this.initialize.bind(this);\n this.sendMessage = this.sendMessage.bind(this);\n this.sendMessageDebounced = debounce(this.sendMessage, MESSAGE_DEBOUNCE_IN_MILLISECONDS, true);\n this.beginDeviceDiscovery = this.beginDeviceDiscovery.bind(this);\n this.dispose = this.dispose.bind(this);\n this.canCastToDevice = this.canCastToDevice.bind(this);\n this.getDevices = this.getDevices.bind(this);\n this.startCastSession = this.startCastSession.bind(this);\n this.authenticateWithVivi = this.authenticateWithVivi.bind(this);\n this.getRoomList = this.getRoomList.bind(this);\n this.joinRoom = this.joinRoom.bind(this);\n this.query = this.query.bind(this);\n this.loadQueue = this.loadQueue.bind(this);\n this.play = this.play.bind(this);\n this.pause = this.pause.bind(this);\n this.stop = this.stop.bind(this);\n this.seek = this.seek.bind(this);\n this.setVolume = this.setVolume.bind(this);\n this.setMuted = this.setMuted.bind(this);\n this.setSubtitles = this.setSubtitles.bind(this);\n }\n\n private initialize(): void {\n this.webSocket = new ResilientWebSocket(this.options.url);\n\n this.webSocket.onMessage = (event: MessageEvent) => this.trigger('message', JSON.parse(event.data));\n\n this.webSocket.onOpen = async () => {\n try {\n this.accessToken = await this.options.fetchAccessToken();\n \n await this.authenticateWithVivi();\n \n this.beginDeviceDiscovery();\n\n this.trigger('connected', Event.void);\n } catch (err) {\n console.error(err);\n \n this.trigger('error', new Error('Could not connect to Vivi'));\n }\n };\n }\n\n private sendMessage(msg: ViviOutgoingMessage): void {\n this.webSocket?.send(JSON.stringify(msg));\n }\n\n private beginDeviceDiscovery(): void {\n this.deviceDiscovery\n .every(DEVICE_DISCOVERY_SCHEDULE_IN_MILLISECONDS)\n .schedule(async () => {\n try {\n const rooms = await this.getRoomList();\n const roomsFingerprint = ViviClient.calculateFingerprint(rooms);\n\n // If the rooms haven't changed, don't bother updating the devices\n if (roomsFingerprint === this.devicesFingerprint)\n return;\n\n const numberOfUniqueOrganisations = new Set(rooms.map(r => r.organisation ?? '')).size;\n const numberOfUniqueLocations = new Set(rooms.map(r => r.location ?? '')).size;\n\n this.devices = rooms.map(r => ({\n id: r.id,\n name: r.name,\n schoolName: numberOfUniqueOrganisations > 1 ? r.organisation : '',\n description: numberOfUniqueLocations > 1 ? r.location : '',\n type: DeviceType.Vivi,\n status: DeviceStatus.Available\n }));\n\n this.devicesFingerprint = roomsFingerprint;\n\n this.trigger('deviceschange', Event.void);\n } catch (error) {\n // This could be a transient error, so we don't want to trigger the 'error' event\n // as that would cause the player to stop playback for an error that it could recover from..\n console.warn(error);\n }\n })\n .trigger()\n .start();\n }\n\n public dispose(): void {\n // Stop the device discovery\n this.deviceDiscovery.stop();\n\n // Dispose websocket\n this.webSocket?.dipose();\n\n // Dispose event bus\n super.dispose();\n }\n\n public canCastToDevice(deviceType: DeviceType): boolean {\n if (deviceType === DeviceType.Vivi)\n return true;\n\n return false;\n }\n\n public getDevices(): Device[] {\n return this.devices;\n }\n\n public startCastSession(config: SessionConfig): CastSession {\n return new ViviCastSession(this, config);\n }\n\n public async authenticateWithVivi(): Promise<void> {\n this.sendMessage({\n destination: 'relay',\n message: {\n token: this.accessToken,\n type: 'identify_video_api'\n }\n });\n\n await this\n .one('message', msg => msg.message.type === 'video_api_identified')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to authenticate with Vivi'); });\n }\n\n public async getRoomList(): Promise<ViviRoom[]> {\n this.sendMessage({\n destination: 'relay',\n message: {\n type: 'video_api_rooms'\n }\n });\n\n const response = await this\n .one('message', msg => msg.message.type === 'video_api_rooms')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to fetch rooms'); });\n\n return response.message.rooms || [];\n }\n\n public async joinRoom(roomId: string): Promise<void> {\n this.sendMessage({\n destination: 'relay',\n message: {\n destination_type: 'box',\n new_destination: roomId,\n token: this.accessToken,\n type: 'connect'\n }\n });\n\n await this\n .one('message', msg => {\n if (msg.source === roomId && msg.message.type === 'connect') return true;\n if (msg.message.type === 'error' && msg.message.error_type === 'already_connected') return true;\n })\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to join room'); });\n }\n\n public async query(roomId: string): Promise<ViviIncomingMessage> {\n const ackId = ViviClient.createAckId();\n\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message_with_ack',\n ack_id: ackId,\n name: 'query'\n }\n });\n\n return await this\n .one('message', msg => msg.message.ack_id === ackId)\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to fetch query'); });\n }\n\n public async loadQueue({ roomId, title, videoSource, subtitleSource }: ViviLoadQueueRequest): Promise<void> {\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message_with_ack',\n ack_id: ViviClient.createAckId(),\n name: 'queue_load',\n payload: {\n urls: [{\n title,\n url: videoSource,\n suburl: subtitleSource\n }]\n }\n }\n });\n\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'ready')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to load media'); });\n }\n\n public async play(roomId: string): Promise<void> {\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message',\n name: 'video_play',\n payload: {}\n }\n });\n\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'playing')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to play video'); });\n }\n\n public async pause(roomId: string): Promise<void> {\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message',\n name: 'video_pause'\n }\n });\n\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'paused')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to pause video'); });\n }\n\n public async stop(roomId: string): Promise<void> {\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message',\n name: 'video_stop'\n }\n });\n\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'stopped')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to stop video'); });\n }\n\n public async seek(roomId: string, position: number): Promise<void> {\n const sent = this.sendMessageDebounced({\n destination: roomId,\n message: {\n type: 'message',\n name: 'video_seek',\n payload: {\n position\n }\n }\n });\n\n if (sent) {\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'playing')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to seek video'); });\n }\n }\n\n public async setVolume(roomId: string, volume: number): Promise<void> {\n const sent = this.sendMessageDebounced({\n destination: roomId,\n message: {\n type: 'message',\n name: 'set_volume',\n payload: {\n volume\n }\n }\n });\n\n if (sent) {\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'volume')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to set volume'); });\n }\n }\n\n public async setMuted(roomId: string, muted: boolean): Promise<void> {\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message',\n name: 'set_mute',\n payload: {\n mute: muted\n }\n }\n });\n\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'mute')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to set mute'); });\n }\n\n public async setSubtitles(roomId: string, showSubtitles: boolean): Promise<void> {\n const ackId = ViviClient.createAckId();\n\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message_with_ack',\n ack_id: ackId,\n name: 'set_subtitles',\n payload: {\n subtitles: showSubtitles\n }\n }\n });\n \n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'subtitles')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to set subtitles'); });\n }\n\n private static createAckId(): string {\n return IdHelper.generateRandomId();\n }\n\n private static calculateFingerprint(devicesOrRooms: { id: string }[]): string {\n return devicesOrRooms.map(dr => dr.id).sort().join(',');\n }\n}\n","import { CastSession, Client, Device, SessionConfig } from './clients/client-interfaces';\nimport { BaseEvents, EventBus } from './utils/event-bus';\n\ninterface DevicesSessionManagerEventMap extends BaseEvents {\n deviceschange: Device[];\n castsessionchange: CastSession | undefined;\n error: Error;\n}\n\nexport class DevicesSessionManager extends EventBus<DevicesSessionManagerEventMap> {\n private instanceId: string;\n private clients: Client[];\n private castSession?: CastSession;\n\n private constructor(instanceId: string) {\n super();\n\n this.instanceId = instanceId;\n this.clients = [];\n \n this.bindFunctions();\n }\n\n private bindFunctions(): void {\n this.addClient = this.addClient.bind(this);\n this.hasInstanceOfClient = this.hasInstanceOfClient.bind(this);\n this.startCastSession = this.startCastSession.bind(this);\n this.gatherAndPublishDevices = this.gatherAndPublishDevices.bind(this);\n this.dispose = this.dispose.bind(this);\n }\n\n public addClient(client: Client): void {\n client.on('deviceschange', this.gatherAndPublishDevices);\n client.on('error', err => this.trigger('error', err));\n \n this.clients.push(client);\n }\n\n public hasInstanceOfClient(clientType: any): boolean {\n return this.clients.some(c => c instanceof clientType);\n }\n \n public startCastSession(config: SessionConfig): void {\n // If a session with the selected device is already in progress, we need to dispose it\n if (this.castSession) {\n if (this.castSession.getDevice().id !== config.device.id)\n this.castSession.dispose();\n else {\n console.info(`A session with device ${config.device.id} already exists - this is a no-op`);\n return;\n }\n }\n\n // Find a client that can cast to the selected device\n const client = this.clients.find(c => c.canCastToDevice(config.device.type));\n\n // Create a new session and notify listeners\n if (client) {\n this.castSession = client.startCastSession(config);\n\n this.castSession.on('error', err => {\n this.castSession.dispose();\n this.trigger('error', err);\n });\n\n this.castSession.on('dispose', () => {\n this.castSession = undefined;\n this.trigger('castsessionchange', undefined);\n });\n \n this.trigger('castsessionchange', this.castSession);\n }\n }\n\n public getCastSession(): CastSession | undefined {\n return this.castSession;\n }\n\n private gatherAndPublishDevices(): void {\n const results = this.clients.map(c => c.getDevices());\n const devices = results.reduce((agg, val) => [ ...agg, ...val ], []);\n\n this.trigger('deviceschange', devices);\n }\n\n public dispose(): void {\n this.castSession?.dispose();\n this.clients.forEach(c => c.dispose());\n \n this.castSession = undefined;\n this.clients = [];\n\n super.dispose();\n }\n\n private static instances: {[key: string]: DevicesSessionManager } = {};\n\n public static getOrCreateInstance(instanceId: string): DevicesSessionManager {\n if (!instanceId)\n throw new Error('instanceId is required');\n\n if (!this.instances[instanceId])\n this.instances[instanceId] = new DevicesSessionManager(instanceId);\n \n return this.instances[instanceId];\n }\n\n public static disposeAndRemoveInstance(sessionManager: DevicesSessionManager): void {\n sessionManager.dispose();\n delete this.instances[sessionManager.instanceId];\n }\n\n public static isActive(): boolean {\n return Object.keys(this.instances).length > 0;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { DeviceType } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\n\nimport './device-menu-item.scss';\n\ninterface DeviceMenuItemOptions extends videojs.MenuItemOptions {\n available: boolean;\n type: DeviceType;\n id: string;\n schoolName?: string;\n description?: string;\n onClick: () => void;\n}\n\nconst MenuItem = videojs.getComponent('MenuItem');\n\nexport class DeviceMenuItem extends MenuItem {\n public options_: DeviceMenuItemOptions;\n\n constructor(player: VideoJsPlayer, options?: DeviceMenuItemOptions) {\n super(player, options);\n\n this.isVisible = this.isVisible.bind(this);\n }\n\n public createEl(): HTMLLIElement {\n const iconClassNames: Record<DeviceType, string> = {\n 'vivi': 'cv-vivi-icon',\n 'apple-tv': 'cv-apple-icon'\n };\n\n const container = super.createEl('li', {\n className: 'vjs-menu-item cv-device-menu-item'\n });\n\n const el = videojs.dom.createEl('div', {\n className: 'cv-device-menu-item-body',\n innerHTML: `\n <span class=\"cv-device-icon ${iconClassNames[this.options_.type]}\"></span>\n <div>\n <span class=\"vjs-menu-item-text\">${this.options_.label}</span>\n <span class=\"vjs-menu-item-text cv-device-truncated-text\">${this.options_.schoolName ?? ''}</span>\n <span class=\"vjs-menu-item-text cv-device-truncated-text cv-device-description\">${this.options_.description ?? ''}</span>\n </div>\n `\n });\n\n container.replaceChildren(el);\n\n return container;\n }\n\n public handleClick(): void {\n this.options_.onClick();\n }\n\n public show(): void {\n super.show();\n }\n\n public hide(): void {\n super.hide();\n }\n\n public isVisible(): boolean {\n return !super.hasClass('vjs-hidden');\n }\n}\n","import SimpleBar from 'simplebar';\nimport videojs from 'video.js';\n\nimport { baseMenuCreateEl } from 'projects/player/components/menu/menu';\n\nimport './devices-menu.scss';\n\nconst Menu = videojs.getComponent('Menu');\n\nexport class DevicesMenu extends Menu {\n private contentWrapper: HTMLDivElement;\n private ctaElement: HTMLDivElement;\n private simpleBar: SimpleBar;\n\n public createEl(): HTMLDivElement {\n const el = baseMenuCreateEl.apply(this);\n const content = (this as any).contentEl_;\n\n this.contentWrapper = videojs.dom.createEl('div', {\n className: 'vjs-menu-content'\n }) as HTMLDivElement;\n \n el.className = 'vjs-menu cv-devices-menu';\n content.className = 'cv-devices-menu-item-list';\n\n el.removeChild(content);\n el.appendChild(this.contentWrapper);\n\n this.contentWrapper.appendChild(content);\n this.simpleBar = new SimpleBar(content as HTMLElement, { autoHide: false });\n\n return el;\n }\n\n public addCta(component: videojs.Component): void {\n if (this.ctaElement) {\n console.warn('CTA has already been added to the menu - this is a no-op');\n return;\n }\n\n this.ctaElement = component.el() as HTMLDivElement;\n this.contentWrapper.prepend(this.ctaElement);\n this.el().classList.add('has-cta');\n }\n\n public removeCta(): void {\n if (this.ctaElement) {\n this.contentWrapper.removeChild(this.ctaElement);\n this.el().classList.remove('has-cta');\n }\n }\n}\n\nvideojs.registerComponent('DevicesMenu', DevicesMenu);\n","import * as React from 'react';\nimport videojs, { VideoJsPlayer } from 'video.js';\n\nimport { CtaContext } from 'libs/shared/interfaces';\n\nimport { DeviceType } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\nimport { getReactComponent } from 'projects/player/react/react-component';\n\nimport './devices-cta.scss';\n\ninterface DevicesCtaProps {\n onDismiss: (context: CtaContext) => void;\n onInstall: (context: CtaContext) => void;\n onLearnMore: (context: CtaContext) => void;\n onContactSupport: (context: CtaContext) => void;\n inactiveIntegrations: DeviceType[];\n canUserManageIntegrations: boolean;\n player: VideoJsPlayer;\n}\n\nfunction DevicesCta({\n inactiveIntegrations,\n canUserManageIntegrations,\n player,\n onDismiss,\n onInstall,\n onLearnMore,\n onContactSupport\n}: DevicesCtaProps): JSX.Element {\n if (inactiveIntegrations.length === 0) return <></>;\n\n const localize = (text: string) => player.localize(text);\n\n const isInactive = (val: DeviceType) =>\n inactiveIntegrations.indexOf(val) !== -1;\n\n let context: CtaContext;\n \n if (isInactive(DeviceType.AppleTv) && isInactive(DeviceType.Vivi))\n context = 'vivi_and_apple_tv';\n else if (isInactive(DeviceType.Vivi))\n context = 'vivi';\n else\n context = 'apple_tv';\n\n return (\n <div className='cv-devices-cta' tabIndex={-1}>\n <Header context={context} localize={localize} onDismiss={() => onDismiss(context)} />\n <Body context={context} />\n <Footer\n context={context}\n canUserManageIntegrations={canUserManageIntegrations}\n localize={localize}\n onContactSupport={() => onContactSupport(context)}\n onInstall={() => onInstall(context)}\n onLearnMore={() => onLearnMore(context)}\n />\n </div>\n );\n}\n\ninterface HeaderProps {\n context: CtaContext;\n localize: (text: string) => string;\n onDismiss: () => void;\n}\n\nfunction Header({ context, localize, onDismiss }: HeaderProps): JSX.Element {\n return (\n <div className='cv-devices-cta-header'>\n <span className='cv-devices-badge'>{localize('New')}</span>\n <span className='cv-devices-title'>\n {context === 'vivi_and_apple_tv' && localize('Cast to Vivi and Apple TV')}\n {context === 'vivi' && localize('Cast to Vivi')}\n {context === 'apple_tv' && localize('Cast to Apple TV')}\n </span>\n <span className='cv-devices-close' onClick={onDismiss}>\n <svg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>\n <path fillRule='evenodd' clipRule='evenodd' fill='white' d='M11.9588 10.6413L16.3612 6.34478C16.7361 5.97191 17.3439 5.97191 17.7188 6.34478C18.0937 6.71764 18.0937 7.32218 17.7188 7.69505L13.3165 11.9916L17.7188 16.3701C18.0937 16.7429 18.0937 17.3475 17.7188 17.7203C17.3439 18.0932 16.7361 18.0932 16.3612 17.7203L11.9588 13.3419L7.63882 17.7203C7.26392 18.0932 6.65608 18.0932 6.28118 17.7203C5.90627 17.3475 5.90627 16.7429 6.28118 16.3701L10.6012 11.9916L6.28118 7.62993C5.90627 7.25706 5.90627 6.65252 6.28118 6.27965C6.65608 5.90678 7.26392 5.90678 7.63882 6.27965L11.9588 10.6413Z' />\n </svg>\n </span>\n </div>\n );\n}\n\ninterface BodyProps {\n context: CtaContext;\n}\n\nfunction Body({ context }: BodyProps): JSX.Element {\n const bgClassName = context === 'vivi_and_apple_tv' ? 'bg-vivi-and-apple' : context === 'vivi' ? 'bg-vivi' : 'bg-apple';\n\n return (\n <div className={`cv-devices-cta-body ${bgClassName}`}>\n {(context === 'vivi_and_apple_tv' || context === 'apple_tv') && <div className='cv-devices-icon-container'><span className='cv-devices-icon apple'></span></div>}\n {(context === 'vivi_and_apple_tv' || context === 'vivi') && <div className='cv-devices-icon-container'><span className='cv-devices-icon vivi'></span></div>}\n </div>\n );\n}\n\ninterface FooterProps {\n context: CtaContext;\n canUserManageIntegrations: boolean;\n localize: (text: string) => string;\n onInstall: () => void;\n onLearnMore: () => void;\n onContactSupport: () => void;\n}\n\nfunction Footer({\n context,\n canUserManageIntegrations,\n localize,\n onInstall,\n onLearnMore,\n onContactSupport\n}: FooterProps): JSX.Element {\n if (canUserManageIntegrations) {\n return (\n <div className='cv-devices-cta-footer'>\n <span>\n {context === 'vivi_and_apple_tv' && localize('Discover our new device integrations to make presenting in the classroom easy!')}\n {context === 'vivi' && localize('Discover our new Vivi integration.')}\n {context === 'apple_tv' && localize('Discover our new Apple TV integration.')}\n </span>\n <br />\n <span className='cv-devices-link' onClick={onInstall}>{localize('Click here to install')}</span>\n </div>\n );\n }\n\n return (\n <div className='cv-devices-cta-footer'>\n <span>\n {context === 'vivi_and_apple_tv' && localize('Cast to Vivi and Apple TV is now available! Please contact ')}\n {context === 'vivi' && localize('Cast to Vivi is now available! Please contact ')}\n {context === 'apple_tv' && localize('Cast to Apple TV is now available! Please contact ')}\n </span>\n <span className='cv-devices-link' onClick={onContactSupport}>ClickView Support</span>\n <span>\n {context === 'vivi_and_apple_tv' && localize(' or your administrator to set up Apple TV and Vivi.')}\n {context === 'vivi' && localize(' or your administrator to set up Vivi.')}\n {context === 'apple_tv' && localize(' or your administrator to set up Apple TV.')}\n </span>\n <br />\n <span className='cv-devices-link' onClick={onLearnMore}>Learn more</span>\n </div>\n );\n}\n\nvideojs.registerComponent(\n 'DevicesCta',\n getReactComponent(\n (player: VideoJsPlayer, options: DevicesCtaProps) => <DevicesCta player={player} {...options} />,\n { properties: { className: 'cv-devices-cta-wrapper' } }\n )\n);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { CtaContext } from 'libs/shared/interfaces';\n\nimport { CollapsibleHeadingMenuItem } from 'projects/player/components/cog-button/collapsible-heading-menu-item';\nimport { NoMatchingResultsMenuItem, SearchInputMenuItem } from 'projects/player/components/search-input-menu-item/search-input-menu-item';\nimport { CollapsibleComponent } from 'projects/player/interfaces/CollapsibleComponent';\nimport { CastSession, Device, DeviceStatus, DeviceType } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\n\nimport { DeviceMenuItem } from '../device-menu-item/device-menu-item';\nimport { DevicesMenu } from '../devices-menu/devices-menu';\n\nimport './devices-button.scss';\n\nimport 'projects/player/plugins/devices-plugin/components/devices-cta/devices-cta';\n\nconst DEVICE_COUNT_THRESHOLD_FOR_SEARCH = 20;\n\nconst DevicesCta = videojs.getComponent('DevicesCta');\nconst MenuButton = videojs.getComponent('MenuButton');\n\nexport interface DevicesButtonOptions extends videojs.MenuButtonOptions {\n onClick: () => void;\n onDeviceMenuItemClick: (item: DeviceMenuItem, device: Device) => void;\n ctaOptions: {\n hasBeenDismissed: boolean,\n canUserManageIntegrations: boolean,\n inactiveIntegrations: DeviceType[],\n onDismiss: (context: CtaContext) => void,\n onInstall: (context: CtaContext) => void,\n onLearnMore: (context: CtaContext) => void,\n onContactSupport: (context: CtaContext) => void\n };\n}\n\nexport class DevicesButton extends MenuButton implements CollapsibleComponent {\n private searchText: string;\n private devices: Device[];\n private castSession?: CastSession;\n private headingItem?: CollapsibleHeadingMenuItem;\n private searchInputItem?: SearchInputMenuItem;\n private emptyPlaceholder?: NoMatchingResultsMenuItem;\n private cta?: videojs.Component;\n \n public options_: DevicesButtonOptions;\n public controlText_: string;\n\n constructor(player: VideoJsPlayer, options?: DevicesButtonOptions) {\n super(player, options);\n\n this.searchText = '';\n this.devices = [];\n this.castSession = undefined;\n\n this.bindFunctions();\n this.bindEventListeners();\n }\n\n private bindFunctions(): void {\n this.bindEventListeners = this.bindEventListeners.bind(this);\n this.setDevices = this.setDevices.bind(this);\n this.setCastSession = this.setCastSession.bind(this);\n this.setSearchText = this.setSearchText.bind(this);\n this.getDeviceMenuItems = this.getDeviceMenuItems.bind(this);\n this.showNotificationBadge = this.showNotificationBadge.bind(this);\n this.hideNotificationBadge = this.hideNotificationBadge.bind(this);\n this.render = this.render.bind(this);\n this.removeMenuItems = this.removeMenuItems.bind(this);\n this.addMenuItemsForDevices = this.addMenuItemsForDevices.bind(this);\n this.shouldShowSearchInput = this.shouldShowSearchInput.bind(this);\n this.toggleSearchInput = this.toggleSearchInput.bind(this);\n this.toggleDeviceMenuItems = this.toggleDeviceMenuItems.bind(this);\n this.toggleEmptyStatePlaceholder = this.toggleEmptyStatePlaceholder.bind(this);\n }\n\n private bindEventListeners(): void {\n const el = this.$('button');\n\n const onBlur = (e: videojs.EventTarget.Event) => {\n (this.menu as any).handleBlur(e);\n };\n\n el.addEventListener('blur', onBlur);\n\n this.one('dispose', () => {\n el.removeEventListener('blur', onBlur);\n this.cta?.dispose();\n });\n }\n\n public createEl(...args: any[]): Element {\n return MenuButton.prototype.createEl.apply(this, ...args);\n }\n\n public buildWrapperCSSClass() {\n return `cv-menu-small cv-devices-button ${super.buildWrapperCSSClass()}`;\n }\n\n public createMenu(): videojs.Menu {\n const menu = new DevicesMenu(this.player_, {\n menuButton: this\n });\n\n if (!this.options_.ctaOptions.hasBeenDismissed && this.options_.ctaOptions.inactiveIntegrations.length > 0) {\n const { onDismiss, ...rest } = this.options_.ctaOptions;\n\n this.cta = new DevicesCta(this.player(), {\n ...rest,\n onDismiss: (context: CtaContext) => {\n this.hideNotificationBadge();\n menu.removeCta();\n onDismiss(context);\n }\n } as any);\n \n this.showNotificationBadge();\n menu.addCta(this.cta);\n }\n\n const children = this.createItems();\n\n children.forEach(x => menu.addItem(x));\n\n return menu;\n }\n\n public createItems(): videojs.MenuItem[] {\n const items: videojs.MenuItem[] = [];\n\n this.headingItem = new CollapsibleHeadingMenuItem(this.player_, {\n label: this.localize('Select a device'),\n selectable: false\n });\n\n this.searchInputItem = new SearchInputMenuItem(this.player_, {\n menuButton: this,\n search: searchText => this.setSearchText(searchText),\n className: 'cv-devices-search-input'\n });\n\n this.emptyPlaceholder = new NoMatchingResultsMenuItem(this.player_, {\n label: 'No devices found',\n selected: false,\n selectable: false,\n multiSelectable: false\n });\n\n this.headingItem.show();\n this.searchInputItem.hide();\n this.emptyPlaceholder.show();\n\n items.push(\n this.headingItem,\n this.searchInputItem,\n this.emptyPlaceholder\n );\n\n return items;\n }\n\n public pressButton(): void {\n super.pressButton();\n\n if (this.shouldShowSearchInput())\n this.searchInputItem?.focus();\n }\n\n public setDevices(devices: Device[]): void {\n this.devices = devices;\n this.render();\n }\n\n public setCastSession(castSession?: CastSession): void {\n this.castSession = castSession;\n this.render();\n }\n\n public setSearchText(searchText: string): void {\n this.searchText = searchText;\n this.render();\n }\n\n public getDeviceMenuItems(): DeviceMenuItem[] {\n return this.menu.children_.filter(x => x instanceof DeviceMenuItem) as DeviceMenuItem[];\n }\n\n public showNotificationBadge(): void {\n this.addClass('notification-badge');\n }\n\n public hideNotificationBadge(): void {\n this.removeClass('notification-badge');\n }\n\n private render(): void {\n // Update the UI\n this.removeMenuItems(this.getDeviceMenuItems());\n this.addMenuItemsForDevices(this.devices);\n this.toggleSearchInput();\n this.toggleDeviceMenuItems();\n this.toggleEmptyStatePlaceholder();\n }\n\n private removeMenuItems(items: videojs.MenuItem[]): void {\n items.forEach(x => {\n this.menu.removeChild(x);\n x.dispose();\n });\n }\n\n private addMenuItemsForDevices(devices: Device[]): void {\n // Sort devices by type, description and name\n const sortedDevices = devices.sort((a, b) => {\n const qualifiedNameDeviceA = `${a.type}${a.schoolName ?? ''}${a.description ?? ''}${a.name}`;\n const qualifiedNameDeviceB = `${b.type}${b.schoolName ?? ''}${b.description ?? ''}${b.name}`;\n return qualifiedNameDeviceA.localeCompare(qualifiedNameDeviceB);\n });\n\n sortedDevices.forEach(x => {\n const newItem = new DeviceMenuItem(this.player(), {\n id: x.id,\n label: x.name,\n schoolName: x.schoolName,\n description: x.description,\n selected: false,\n multiSelectable: false,\n selectable: true,\n available: x.status === DeviceStatus.Available,\n type: x.type,\n onClick: () => {\n this.options_.onDeviceMenuItemClick(newItem, x);\n }\n });\n\n this.menu.addItem(newItem);\n });\n }\n\n private shouldShowSearchInput(): boolean {\n const deviceMenuItems = this.getDeviceMenuItems();\n const showSearchInput = deviceMenuItems.length >= DEVICE_COUNT_THRESHOLD_FOR_SEARCH;\n\n return showSearchInput;\n }\n\n private toggleSearchInput(): void {\n if (this.shouldShowSearchInput()) {\n this.searchInputItem.show();\n this.menu.addClass('vertical-fill');\n } else {\n this.searchInputItem.hide();\n this.menu.removeClass('vertical-fill');\n }\n }\n\n private toggleDeviceMenuItems(): void {\n const deviceMenuItems = this.getDeviceMenuItems();\n const isSearchEnabled = this.shouldShowSearchInput();\n const searchTextLowerCase = this.searchText.toLowerCase();\n \n // Update the UI of each device menu item\n deviceMenuItems.forEach(x => {\n const device = this.devices.find(y => y.id === x.options_.id);\n\n if (!device)\n return;\n\n const isAvailable = device.status === DeviceStatus.Available;\n const isInSession = device.id === this.castSession?.getDevice().id;\n const isMatchingSearch = isSearchEnabled ?\n `${device.name} ${device.schoolName ?? ''} ${device.description ?? ''}`.trim().toLowerCase().indexOf(searchTextLowerCase) !== -1 :\n true;\n \n isAvailable ? x.enable() : x.disable();\n isMatchingSearch ? x.show() : x.hide();\n isInSession ? x.selected(true) : x.selected(false);\n });\n }\n\n private toggleEmptyStatePlaceholder(): void {\n const allDeviceMenuItems = this.getDeviceMenuItems();\n const visibleDeviceMenuItems = allDeviceMenuItems.filter(x => x.isVisible());\n\n visibleDeviceMenuItems.length ?\n this.emptyPlaceholder.hide() :\n this.emptyPlaceholder.show();\n \n allDeviceMenuItems.length ?\n this.emptyPlaceholder.setLabel(this.localize('No matching results')) :\n this.emptyPlaceholder.setLabel(this.localize('No devices found'));\n }\n\n /**\n * CollapsibileComponent interface implementation\n * from here onward\n */\n public alwaysCollapsed: boolean = false;\n public isCollapsed: boolean = false;\n public isCollabsible: boolean = true;\n public className: string = 'cv-devices-menu-button';\n\n public getCollabsibleName(): string {\n return this.controlText_;\n }\n\n public getCollabsibleValue(): string {\n return this.castSession?.getDevice().name ?? ' ';\n }\n\n public showInCollabsibleMenu(): boolean {\n return true;\n }\n\n public showCollapsibleMenu(): void {\n this.handleClick();\n }\n\n public handleClick(): void {\n super.handleClick(null);\n this.options_.onClick();\n }\n}\n\nDevicesButton.prototype.controlText_ = 'Devices';\n\nvideojs.registerComponent('DevicesButton', DevicesButton);\n","import videojs from 'video.js';\n\nimport { Device, DeviceType } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\n\nimport './devices-tech-ui.scss';\n\nconst Component = videojs.getComponent('Component');\n\ninterface DevicesTechUIOptions extends videojs.ComponentOptions {\n onStopCasting: () => void;\n}\n\nexport class DevicesTechUI extends Component {\n private poster: string;\n private device?: Device;\n \n public options_: DevicesTechUIOptions;\n\n constructor(options: DevicesTechUIOptions) {\n super(null, options);\n }\n\n public createEl(): Element {\n return super.createEl('div', {\n className: 'cv-devices-tech'\n });\n }\n\n public setPoster(poster: string): void {\n this.poster = poster;\n this.update();\n }\n\n public setDevice(device: Device): void {\n this.device = device;\n this.update();\n }\n\n /**\n * Unfortunately we can't use the traditional way\n * of building out components and click handlers\n * because this component is ultimately detached\n * from the player so much of it's functionality won't work\n */\n public update(): void {\n const iconClassNames: Record<DeviceType, string> = {\n 'vivi': 'cv-vivi-icon',\n 'apple-tv': 'cv-apple-icon'\n };\n\n (this as any).el_.innerHTML = `\n <div class=\"cv-devices-content\">\n <p>${this.localize('Currently playing on')}</p>\n <h2><span class=\"cv-device-icon ${iconClassNames[this.device?.type ?? DeviceType.Vivi]}\"></span>${this.device?.name ?? ''}</h2>\n </div>\n <div class=\"cv-devices-background\" style=\"background-image: url(${this.poster})\"></div>\n `;\n\n const button = document.createElement('button');\n \n const onPress = (event: Event | TouchEvent) => {\n event.stopPropagation();\n this.options_.onStopCasting();\n };\n\n button.onclick = onPress;\n button.ontouchstart = onPress;\n button.className = 'stop-casting-button';\n button.innerHTML = this.localize('Stop casting');\n\n (this as any).el_.querySelector('.cv-devices-content').appendChild(button);\n }\n\n // This function needs to be here in order to get \n // VideoJS to add this component into its UI tree..\n public play(): void {}\n}\n","import videojs from 'video.js';\n\nimport { CastSession, Device } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\nimport { DevicesSessionManager } from 'projects/player/plugins/devices-plugin/devices-session-manager';\nimport { LocalCacheHelper } from 'projects/player/utils/local-cache-helper';\nimport { TrackHelper } from 'projects/player/utils/track-helper';\n\nimport { DevicesTechUI } from './devices-tech-ui/devices-tech-ui';\n\ninterface TechWithConstructor extends videojs.Tech {\n new (options: videojs.ComponentOptions, ready: videojs.Component.ReadyCallback): videojs.Tech;\n}\n\ninterface DevicesTechOptions extends videojs.ComponentOptions {\n source: videojs.Tech.SourceObject;\n instanceId?: string;\n poster?: string;\n playerId: string;\n}\n\ntype PlayerTextTrack = TextTrack & { src?: string };\n\nconst Tech = videojs.getComponent('Tech') as unknown as TechWithConstructor;\n\nclass DevicesTech extends Tech {\n private ui?: DevicesTechUI;\n private videojsPlayer: videojs.Player;\n\n public readonly featuresVolumeControl: boolean = true;\n public readonly featuresPlaybackRate: boolean = false;\n public readonly movingMediaElementInDOM: boolean = false;\n public readonly featuresFullscreenResize: boolean = true;\n public readonly featuresTimeupdateEvents: boolean = true;\n public readonly featuresProgressEvents: boolean = false;\n public readonly featuresNativeTextTracks: boolean = false;\n public readonly featuresNativeAudioTracks: boolean = false;\n public readonly featuresNativeVideoTracks: boolean = false;\n public readonly featuresMuteControl: boolean = true;\n public readonly featuresSourceset: boolean = false;\n\n public options_: DevicesTechOptions;\n\n constructor(options: videojs.ComponentOptions, ready: videojs.Component.ReadyCallback) {\n super(options, ready as any);\n\n this.videojsPlayer = videojs(this.options_.playerId);\n \n this.bindFunctions();\n this.bindEventListeners();\n\n this.ready((): void => {\n this.setSource(this.options_.source);\n });\n \n this.triggerReady();\n }\n\n private bindFunctions(): void {\n this.bindEventListeners = this.bindEventListeners.bind(this);\n this.onTextTrackChanged = this.onTextTrackChanged.bind(this);\n this.getSelectedTextTrack = this.getSelectedTextTrack.bind(this);\n this.setSelectedTextTrack = this.setSelectedTextTrack.bind(this);\n this.showUI = this.showUI.bind(this);\n this.hideUI = this.hideUI.bind(this);\n this.dispose = this.dispose.bind(this);\n this.setSource = this.setSource.bind(this);\n this.getCastSession = this.getCastSession.bind(this);\n }\n\n private bindEventListeners(): void {\n const session = this.getCastSession();\n\n if (!session) return;\n\n this.textTracks().on('change', this.onTextTrackChanged);\n\n this.videojsPlayer.one('ended', () => {\n session.dispose();\n });\n\n session.on('durationchange', () => {\n this.trigger('durationchange');\n });\n\n session.on('dispose', () => {\n this.trigger('ended');\n this.hideUI();\n });\n\n session.on('playingchange', () => {\n const playing = session.isPlaying();\n\n if (playing) {\n this.trigger('play');\n this.trigger('playing');\n } else {\n this.trigger('pause');\n }\n });\n\n session.on('volumechange', () => {\n this.trigger('volumechange');\n });\n\n session.on('sourceloaded', () => {\n this.trigger('loadeddata');\n });\n\n session.on('subtitleschange', () => {\n this.setSelectedTextTrack(session.getSubtitles());\n });\n }\n\n private onTextTrackChanged(): void {\n const textTrack = this.getSelectedTextTrack();\n\n this.getCastSession()?.setSubtitles(textTrack?.src);\n }\n\n private getSelectedTextTrack(): PlayerTextTrack | null {\n return TrackHelper.findTrackByPredicate(this.videojsPlayer.player_, (track: PlayerTextTrack) => {\n return track.mode === 'showing' && !!track.src;\n }) as PlayerTextTrack;\n }\n\n private setSelectedTextTrack(subtitleSource: string): void {\n TrackHelper.forEachTrack(this.videojsPlayer.player_, (t: PlayerTextTrack) => {\n if (t.kind !== 'subtitles')\n return;\n\n if (t.src === subtitleSource)\n t.mode = 'showing';\n else\n t.mode = 'disabled';\n });\n }\n\n private showUI(device: Device): void {\n if (!this.ui) return;\n\n this.ui.setPoster(this.options_.poster);\n this.ui.setDevice(device);\n this.ui.show();\n }\n\n private hideUI(): void {\n this.ui?.hide();\n }\n\n public dispose(): void {\n this.textTracks().off('change', this.onTextTrackChanged);\n\n const session = this.getCastSession();\n\n if (session)\n session.dispose();\n \n super.cleanupAutoTextTracks();\n super.dispose();\n }\n\n public createEl(): Element {\n this.ui = this.ui || new DevicesTechUI({\n onStopCasting: () => {\n this.getCastSession()?.dispose();\n }\n });\n\n return this.ui.el();\n }\n\n public setSource(source: videojs.Tech.SourceObject): void {\n const session = this.getCastSession();\n\n if (!session) return;\n\n this.showUI(session.getDevice());\n\n this.trigger('loadstart');\n\n const textTrack = this.getSelectedTextTrack();\n\n // The remote casting devices often cannot reach the Local Cache server on a\n // school's network. When setting the source for the casting session, we always\n // use the CDN URL..\n session.loadSource(LocalCacheHelper.getOriginalUrl(source.src), textTrack?.src);\n }\n\n public addRemoteTextTrack(options: videojs.TextTrackOptions): HTMLTrackElement {\n return super.addRemoteTextTrack(options, true);\n }\n\n public getCastSession(): CastSession | undefined {\n return DevicesSessionManager\n .getOrCreateInstance(this.options_.instanceId ?? '')\n .getCastSession();\n }\n\n public play(): void {\n this.getCastSession()?.play();\n }\n\n public pause(): void {\n this.getCastSession()?.pause();\n }\n\n public paused(): boolean {\n return this.getCastSession()?.isPlaying() === false;\n }\n\n public ended(): boolean {\n return this.getCastSession()?.isPlaybackFinished() ?? false;\n }\n\n public setCurrentTime(time?: number): void {\n this.getCastSession()?.seek(time ?? 0);\n }\n\n public currentTime(): number {\n return this.getCastSession()?.getPosition() ?? 0;\n }\n\n public duration(): number {\n return this.getCastSession()?.getDuration() ?? this.videojsPlayer.duration();\n }\n\n public volume(): number {\n return this.getCastSession()?.getVolume() ?? 1;\n }\n\n public setVolume(volume: number): void {\n this.getCastSession()?.setVolume(volume);\n }\n\n public muted(): boolean {\n return this.getCastSession()?.getMuted() ?? false;\n }\n\n public setMuted(muted: boolean): void {\n this.getCastSession()?.setMuted(muted);\n }\n \n public buffered(): void {\n return undefined; // Intentionally returning undefined to opt out of displaying a buffer\n }\n\n public seekable(): videojs.TimeRange {\n return videojs.createTimeRanges(0, this.duration());\n }\n\n public playbackRate(): number {\n return 1;\n }\n\n public readyState(): number {\n // See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState\n return 4;\n }\n\n public controls(): boolean {\n return false;\n }\n\n public playsinline(): boolean {\n return true;\n }\n\n public supportsFullScreen(): boolean {\n return true;\n }\n\n public setAutoplay(): void { }\n\n public preload(): void { }\n\n public load(): void { }\n\n public setPlaybackRate(): void { }\n \n public static canPlayType(): string {\n return '';\n }\n\n public static canPlaySource(sourceObject: videojs.Tech.SourceObject, techOptions?: { instanceId: string }): boolean {\n // TODO: Check if the selected device can actually play the current source type\n return !!DevicesSessionManager\n .getOrCreateInstance(techOptions?.instanceId ?? '')\n .getCastSession();\n }\n\n public static isSupported(): boolean {\n return DevicesSessionManager.isActive();\n }\n}\n\nvideojs.registerTech('devices', DevicesTech);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { EntityType, EventVersion, PlaybackDescriptor, UserAction, WorkflowPhase } from 'libs/analytics/interfaces';\n\nimport { DevicesConfig } from 'projects/player/interfaces/DevicesConfig';\nimport { AnalyticsService } from 'projects/player/services/analytics-service';\n\nimport { AppleTvClient } from './clients/apple-tv/apple-tv-client';\nimport { CastSession, Client, Device, DeviceType } from './clients/client-interfaces';\nimport { ViviClient } from './clients/vivi/vivi-client';\nimport { DeviceMenuItem } from './components/device-menu-item/device-menu-item';\nimport { DevicesButton, DevicesButtonOptions } from './components/devices-button/devices-button';\nimport { DevicesSessionManager } from './devices-session-manager';\n\nimport './devices-plugin.scss';\n\nimport './components/devices-button/devices-button';\nimport './tech/devices-tech';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface DevicesPluginOptions extends DevicesConfig {\n userId?: number;\n title: string;\n analyticsService?: AnalyticsService;\n}\n\nclass DevicesPlugin extends Plugin {\n private options: DevicesPluginOptions;\n private devicesButton?: DevicesButton;\n private instanceId: string;\n\n constructor(player: VideoJsPlayer, options: DevicesPluginOptions) {\n super(player, options);\n\n this.options = options;\n this.instanceId = this.player.options_.devices?.instanceId ?? '';\n\n this.bindFunctions();\n this.initialize();\n }\n\n private bindFunctions(): void {\n this.initialize = this.initialize.bind(this);\n this.onReady = this.onReady.bind(this);\n this.onDevicesChanged = this.onDevicesChanged.bind(this);\n this.onCastSessionChanged = this.onCastSessionChanged.bind(this);\n this.onDevicesError = this.onDevicesError.bind(this);\n this.addViviClient = this.addViviClient.bind(this);\n this.addAppleTvClient = this.addAppleTvClient.bind(this);\n this.reloadTech = this.reloadTech.bind(this);\n this.getSessionManager = this.getSessionManager.bind(this);\n this.dispose = this.dispose.bind(this);\n }\n\n private initialize(): void {\n this.player.ready(this.onReady);\n }\n\n private onReady(): void {\n const collapserator = this.player.getChild('collapserator');\n const sessionManager = this.getSessionManager();\n\n if (!collapserator) return;\n if (!sessionManager) return;\n\n sessionManager.on('deviceschange', this.onDevicesChanged);\n sessionManager.on('castsessionchange', this.onCastSessionChanged);\n sessionManager.on('error', this.onDevicesError);\n\n const onDevicesButtonClick = () => {\n this.addViviClient(sessionManager);\n this.addAppleTvClient(sessionManager);\n };\n\n const onDeviceMenuItemClick = (item: DeviceMenuItem, device: Device) => {\n sessionManager.startCastSession({\n device,\n title: this.options.title\n });\n\n this.options.analyticsService?.logUserAction(device, {\n actionType: UserAction.Select,\n workflowPhase: WorkflowPhase.Complete,\n descriptor: PlaybackDescriptor.ChangeDevice,\n entity: EntityType.Device,\n eventVersion: EventVersion.V3\n });\n };\n\n // Determine which integrations are inactive for the CTA\n const ctaOptions = this.options.ctaOptions;\n const viviConfig = this.options.vivi;\n const appleTvConfig = this.options.appleTv;\n const inactiveIntegrations: DeviceType[] = [];\n\n if (!appleTvConfig.enabled)\n inactiveIntegrations.push(DeviceType.AppleTv);\n\n if (!viviConfig.enabled || !viviConfig.accountConnected)\n inactiveIntegrations.push(DeviceType.Vivi);\n\n const buttonOptions: DevicesButtonOptions = {\n onClick: onDevicesButtonClick,\n onDeviceMenuItemClick,\n ctaOptions: {\n ...ctaOptions,\n inactiveIntegrations\n }\n };\n\n this.devicesButton = collapserator.addChild('DevicesButton', buttonOptions) as DevicesButton;\n }\n\n private onDevicesChanged(devices: Device[]): void {\n this.devicesButton?.setDevices(devices);\n }\n\n private onCastSessionChanged(castSession: CastSession | undefined): void {\n this.devicesButton?.setCastSession(castSession);\n this.reloadTech();\n\n if (castSession) {\n // Hide some UI elements and prevent the controls from fading out when casting\n this.player.addClass('cv-device-casting');\n this.player.addClass(`cv-device-${castSession.getDevice().type}`);\n\n // Exit fullscreen when casting\n if (this.player.isFullscreen())\n this.player.exitFullscreen();\n } else {\n // Restore the UI elements\n this.player.removeClass('cv-device-casting');\n this.player.removeClass(`cv-device-${DeviceType.AppleTv}`);\n this.player.removeClass(`cv-device-${DeviceType.Vivi}`);\n }\n }\n\n private onDevicesError(err: Error): void {\n this.player.error(err.message);\n this.player.pause();\n }\n\n private addViviClient(sessionManager: DevicesSessionManager): void {\n if (!this.options.vivi.enabled) return;\n if (!this.options.vivi.accountConnected) return;\n if (!this.options.vivi.apiUrl) return;\n if (sessionManager.hasInstanceOfClient(ViviClient)) return;\n\n const viviClient = new ViviClient({\n url: this.options.vivi.apiUrl,\n fetchAccessToken: this.options.vivi.fetchAccessToken\n });\n\n sessionManager.addClient(viviClient as Client);\n }\n\n private addAppleTvClient(sessionManager: DevicesSessionManager): void {\n if (!this.options.appleTv.enabled) return;\n if (!this.options.trackingCode) return;\n if (!this.options.userId) return;\n if (sessionManager.hasInstanceOfClient(AppleTvClient)) return;\n\n const appleTvClient = new AppleTvClient({\n fetchAccessToken: this.options.appleTv.fetchAccessToken,\n trackingCode: this.options.trackingCode,\n userId: this.options.userId\n });\n\n sessionManager.addClient(appleTvClient as Client);\n }\n\n private reloadTech(): void {\n const player = this.player;\n const sources = player.currentSources();\n const volume = player.volume();\n const muted = player.muted();\n const time = player.currentTime();\n const paused = player.paused();\n \n // This will cause the techs to get re-evaluated in the provided `techOrder`\n player.src(sources);\n\n // Restore the state of the player when playback starts\n player.one('playing', () => {\n player.volume(volume);\n player.muted(muted);\n player.currentTime(time);\n \n if (paused)\n player.pause();\n else\n player.play();\n });\n }\n\n private getSessionManager(): DevicesSessionManager | undefined {\n if (this.instanceId)\n return DevicesSessionManager.getOrCreateInstance(this.instanceId);\n }\n\n public dispose(): void {\n const sessionManager = this.getSessionManager();\n\n if (!sessionManager) return;\n\n sessionManager.off('deviceschange', this.onDevicesChanged);\n sessionManager.off('castsessionchange', this.onCastSessionChanged);\n sessionManager.off('error', this.onDevicesError);\n\n DevicesSessionManager.disposeAndRemoveInstance(sessionManager);\n\n super.dispose();\n }\n}\n\nvideojs.registerPlugin('devicesPlugin', DevicesPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n devicesPlugin(options: DevicesPluginOptions): void;\n }\n}\n","import React from 'react';\nimport videojs, { VideoJsPlayer } from 'video.js';\n\nimport { ResourceTile } from 'libs/shared/components/widgets/items/resource-widget-item/ResourceWidgetItem';\nimport { Resource } from 'libs/shared/interfaces';\n\nimport { Resource as PlayerResource } from 'projects/player/interfaces/models/PlaybackObject';\nimport { getReactComponent } from 'projects/player/react/react-component';\n\nimport './resource-menu-item.scss';\n\ninterface ResourceMenuItemProps {\n resource: PlayerResource;\n imageCdnUrl: string;\n label?: string;\n}\n\nfunction ReactResourceMenuItem(props: ResourceMenuItemProps): JSX.Element {\n return (\n <div className='cv-resource-item'>\n <ResourceTile\n data={props.resource as Resource}\n imageCdnUrl={props.imageCdnUrl}\n titlePosition='above'\n hideTypeBadge\n />\n </div>\n );\n}\n\nconst _ResourceMenuItem = getReactComponent<ResourceMenuItemProps>(\n (player: VideoJsPlayer, options: ResourceMenuItemProps) => <ReactResourceMenuItem {...options} />\n);\n\nconst MenuItem = videojs.getComponent('MenuItem');\n\ninterface ResourceMenuItemOptions extends videojs.ComponentOptions, ResourceMenuItemProps {\n downloadResource: (resource: PlayerResource) => void;\n}\n\nexport class ResourceMenuItem extends MenuItem {\n public options_: ResourceMenuItemOptions;\n\n constructor(player: VideoJsPlayer, options: ResourceMenuItemOptions) {\n super(player, options);\n\n const menuItem = new _ResourceMenuItem(player, { resource: options.resource, imageCdnUrl: options.imageCdnUrl });\n this.addChild(menuItem);\n }\n\n public createEl(tagName?: string, properties: any = {}, attributes?: any): HTMLLIElement {\n return super.createEl(tagName, {\n ...properties,\n className: `${properties.className} cv-resource-menu-item`\n }, attributes);\n }\n\n public handleClick(event: videojs.EventTarget.Event): void {\n // Prevent menu from closing on click\n event.stopImmediatePropagation();\n\n this.options_.downloadResource(this.options_.resource);\n }\n}\n","import videojs from 'video.js';\n\nimport { LocationUtils } from 'libs/common/backbone/core';\n\nimport { CollapsibleHeadingMenuItem } from 'projects/player/components/cog-button/collapsible-heading-menu-item';\nimport { CollapsibleComponent } from 'projects/player/interfaces/CollapsibleComponent';\nimport { Resource as PlayerResource } from 'projects/player/interfaces/models/PlaybackObject';\nimport {\n ResourceMenuItem\n} from 'projects/player/plugins/resources-plugin/components/resource-menu-item/resource-menu-item';\n\nimport './resources-button.scss';\n\nconst MenuButton = videojs.getComponent('MenuButton');\n\ninterface ResourceButtonOptions extends videojs.MenuButtonOptions {\n resources: PlayerResource[];\n imageCdnUrl: string;\n onClickResource: (resource: PlayerResource) => void;\n}\n\nclass ResourcesButton extends MenuButton implements CollapsibleComponent {\n public options_: ResourceButtonOptions;\n public controlText_: string;\n\n private downloadIframe: HTMLIFrameElement;\n\n public buildWrapperCSSClass() {\n return `cv-menu-small cv-resources-button-wrapper ${super.buildWrapperCSSClass()}`;\n }\n\n public buildCSSClass(): string {\n return `cv-resources-button ${super.buildCSSClass()}`;\n }\n\n public update(): void {\n super.update();\n }\n\n public createItems(): videojs.MenuItem[] {\n const items: videojs.MenuItem[] = [];\n\n items.push(new CollapsibleHeadingMenuItem(this.player_, {\n label: 'Resources'\n }) as any);\n\n this.options_.resources.forEach(resource => {\n const menuItem = new ResourceMenuItem(this.player(), {\n resource,\n imageCdnUrl: this.options_.imageCdnUrl,\n downloadResource: (resource: PlayerResource) => this.downloadResource(resource),\n label: resource.name\n });\n\n items.push(menuItem as unknown as videojs.MenuItem);\n });\n\n return items;\n }\n\n private downloadResource(resource: PlayerResource): void {\n if (resource.type === 'link') {\n LocationUtils.PageLoad(resource.url, true);\n return;\n }\n\n this.getDownloadIframe().src = resource.url;\n }\n\n private getDownloadIframe(): HTMLIFrameElement {\n if (this.downloadIframe)\n return this.downloadIframe;\n\n this.downloadIframe = videojs.dom.createEl('iframe') as HTMLIFrameElement;\n this.downloadIframe.style.display = 'none';\n\n videojs.dom.appendContent(videojs.dom.$('body'), this.downloadIframe);\n\n return this.downloadIframe;\n }\n\n /**\n * CollapsibleComponent implementation below\n */\n public alwaysCollapsed: boolean = false;\n \n public isCollapsed: boolean = false;\n \n public isCollabsible: boolean = true;\n \n public getCollabsibleName(): string {\n return this.controlText_;\n }\n \n public getCollabsibleValue(): string {\n return '';\n }\n \n public showInCollabsibleMenu(): boolean {\n return true;\n }\n \n public showCollapsibleMenu(): void {\n super.handleClick(null);\n }\n}\n\nResourcesButton.prototype.controlText_ = 'Resources';\n\nvideojs.registerComponent('ResourcesButton', ResourcesButton);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Resource } from 'projects/player/interfaces/models/PlaybackObject';\n\nimport 'projects/player/plugins/resources-plugin/components/resources-button/resources-button';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface ResourcesPluginOptions {\n resources: Resource[];\n imageCdnUrl: string;\n}\n\nclass ResourcesPlugin extends Plugin {\n private options: ResourcesPluginOptions;\n\n constructor(player: VideoJsPlayer, options: ResourcesPluginOptions) {\n super(player, options);\n\n this.options = options;\n\n player.ready(() => this.onReady());\n }\n\n private onReady(): void {\n if (!this.options.resources.length)\n return;\n\n const collapserator = this.player.getChild('collapserator');\n\n collapserator.addChild('ResourcesButton', {\n resources: this.options.resources,\n imageCdnUrl: this.options.imageCdnUrl\n });\n }\n}\n\nvideojs.registerPlugin('resourcesPlugin', ResourcesPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n resourcesPlugin(options: ResourcesPluginOptions): void;\n }\n}\n","import React from 'react';\n\nimport { Player, PlayerOptions } from 'projects/player/players/player';\nimport { getProxy } from 'projects/player/utils/getProxy';\n\n/**\n * React plugins are exported on the react player in order to allow\n * our dist files to not require react - Sha\n */\nimport 'projects/player/plugins/devices-plugin/devices-plugin';\nimport 'projects/player/plugins/next-video-plugin/next-video-plugin';\nimport 'projects/player/plugins/resources-plugin/resources-plugin';\nimport 'projects/player/plugins/transcript-plugin/transcript-plugin';\nimport 'projects/player/plugins/old-version-refresh-plugin/old-version-refresh-plugin';\n\nexport interface ClickViewPlayerProps extends Omit<PlayerOptions, 'playerApi'> {\n // TODO Remove optional from playerApi\n playerApi?: URL;\n className?: string;\n onReady?: (player: Player) => void;\n onError?: (error: any) => void;\n onDispose?: () => void;\n}\n\nexport function ClickViewPlayer(props: ClickViewPlayerProps): React.ReactElement {\n const { className = '', playerApi, onReady, onDispose, ...playerOptions } = props;\n \n const containerRef = React.useRef(null);\n\n React.useEffect(() => {\n if (!containerRef)\n return;\n\n const player = new Player(containerRef.current, {\n ...playerOptions,\n playerApi: playerApi\n });\n\n if (onReady) {\n player.ready(() => {\n onReady(getProxy(player));\n });\n }\n\n if (onDispose) {\n player.one('dispose', onDispose);\n }\n \n return () => {\n player?.dispose();\n };\n }, [props.viewKey]);\n\n return (\n <div ref={containerRef} className={className}></div>\n );\n}\n\nexport default ClickViewPlayer;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BOQck-Qs.chunk.js","names":[],"sources":["../../../player/src/plugins/create-clip-button-plugin/components/create-clip-button.scss","../../../player/src/plugins/create-clip-button-plugin/components/create-clip-button.ts","../../../player/src/plugins/create-clip-button-plugin/create-clip-button-plugin.ts","../../../player/src/plugins/picture-in-picture-plugin/components/picture-in-picture-toggle.ts","../../../player/src/plugins/picture-in-picture-plugin/picture-in-picture-plugin.ts","../../../player/src/plugins/points-of-interest-plugin/components/point-of-interest-indicator/point-of-interest-indicator.ts","../../../player/src/plugins/points-of-interest-plugin/components/points-of-interest-menu-item/points-of-interest-menu-item.ts","../../../player/src/plugins/points-of-interest-plugin/points-of-interest-plugin.ts","../../../player/src/plugins/range-indicator-plugin/components/range-indicator/range-indicator.ts","../../../player/src/plugins/range-indicator-plugin/components/replay-view-button/replay-view-button.ts","../../../player/src/plugins/range-indicator-plugin/components/replay-view/replay-view.ts","../../../player/src/plugins/range-indicator-plugin/range-indicator-plugin.ts","../../../player/src/utils/id-helper.ts","../../../player/src/players/player.ts","../../../player/src/plugins/devices-plugin/utils/resilient-web-socket.ts","../../../player/src/plugins/devices-plugin/clients/vivi/vivi-cast-session-state.ts","../../../player/src/plugins/devices-plugin/clients/vivi/vivi-interfaces.ts","../../../player/src/plugins/devices-plugin/clients/vivi/vivi-cast-session.ts","../../../player/src/plugins/devices-plugin/clients/vivi/vivi-client.ts","../../../player/src/plugins/devices-plugin/devices-session-manager.ts","../../../player/src/plugins/devices-plugin/components/device-menu-item/device-menu-item.ts","../../../player/src/plugins/devices-plugin/components/devices-menu/devices-menu.ts","../../../player/src/plugins/devices-plugin/components/devices-cta/devices-cta.tsx","../../../player/src/plugins/devices-plugin/components/devices-button/devices-button.ts","../../../player/src/plugins/devices-plugin/tech/devices-tech-ui/devices-tech-ui.ts","../../../player/src/plugins/devices-plugin/tech/devices-tech.ts","../../../player/src/plugins/devices-plugin/devices-plugin.ts","../../../player/src/plugins/resources-plugin/components/resource-menu-item/resource-menu-item.tsx","../../../player/src/plugins/resources-plugin/components/resources-button/resources-button.ts","../../../player/src/plugins/resources-plugin/resources-plugin.ts","../../../player/src/react/Player.tsx"],"sourcesContent":[".video-js {\n .cv-create-clip-button {\n width: 4em;\n padding: 0;\n\n .vjs-icon-placeholder::before {\n font-family: CVPlayer;\n /* Defined in font/icon-map.js */\n content: unquote(\"\\\"\\\\f10e\\\"\");\n }\n }\n}\n","import videojs from 'video.js';\n\nimport { CollapsibleComponent } from 'projects/player/interfaces/CollapsibleComponent';\n\nconst Button = videojs.getComponent('Button');\n\nimport './create-clip-button.scss';\n\nclass CreateClipButton extends Button implements CollapsibleComponent {\n public controlText_: string;\n\n public buildCSSClass(): string {\n return 'cv-create-clip-button';\n }\n\n /**\n * CollapsibleComponent interface implementation below\n */\n public alwaysCollapsed: boolean = false;\n\n public isCollapsed: boolean = false;\n\n public isCollabsible: boolean = true;\n\n public getCollabsibleName(): string {\n return this.controlText_;\n }\n \n public getCollabsibleValue(): string {\n return '';\n }\n \n public showInCollabsibleMenu(): boolean {\n return true;\n }\n \n public showCollapsibleMenu(): void {\n super.handleClick(null);\n }\n}\n\nCreateClipButton.prototype.controlText_ = 'Create clip';\n\nvideojs.registerComponent('CreateClipButton', CreateClipButton);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport 'projects/player/plugins/create-clip-button-plugin/components/create-clip-button';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface CreateClipButtonPluginOptions {\n onClick: () => void;\n}\n\nclass CreateClipButtonPlugin extends Plugin {\n private options: CreateClipButtonPluginOptions;\n\n constructor(player: VideoJsPlayer, options: CreateClipButtonPluginOptions) {\n super(player, options);\n\n this.options = options;\n\n player.ready(() => this.onReady());\n }\n\n private onReady(): void {\n const collapserator = this.player.getChild('collapserator');\n\n if (!collapserator)\n return;\n\n collapserator.addChild('CreateClipButton', {\n clickHandler: this.options.onClick\n });\n }\n}\n\nvideojs.registerPlugin('createClipButtonPlugin', CreateClipButtonPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n createClipButtonPlugin(options: CreateClipButtonPluginOptions): void;\n }\n}\n","import videojs from 'video.js';\n\nconst BasePictureInPictureToggle = videojs.getComponent('PictureInPictureToggle');\n\nclass PictureInPictureToggle extends BasePictureInPictureToggle {\n handlePictureInPictureEnabledChange() {\n (this as any).enable();\n }\n}\n\nvideojs.registerComponent('PictureInPictureToggle', PictureInPictureToggle);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport './picture-in-picture.scss';\n\nimport './components/picture-in-picture-toggle';\n\nconst PlayToggle = videojs.getComponent('PlayToggle');\n\nconst Plugin = videojs.getPlugin('plugin');\n\nconst MIN_WIDTH = 800;\n\ninterface PictureInPicturePluginOptions {\n onRequestPictureInPicture: (isPiP: boolean) => void;\n}\n\nclass PictureInPicturePlugin extends Plugin {\n private options: PictureInPicturePluginOptions;\n private playerRequestPictureInPictureFn: () => Promise<videojs.PictureInPictureWindow>;\n private playerExitPictureInPictureFn: () => Promise<void>;\n private playToggle: videojs.Component;\n private toggle: videojs.Button;\n\n constructor(player: VideoJsPlayer, options: PictureInPicturePluginOptions) {\n super(player, options);\n\n this.options = options;\n\n this.bindFunctions();\n player.ready(() => this.initialize());\n }\n\n private bindFunctions(): void {\n this.requestPictureInPicture = this.requestPictureInPicture.bind(this);\n this.exitPictureInPicture = this.exitPictureInPicture.bind(this);\n this.onPlayerResize = this.onPlayerResize.bind(this);\n \n this.playerRequestPictureInPictureFn = this.player.requestPictureInPicture;\n this.playerExitPictureInPictureFn = this.player.exitPictureInPicture;\n \n this.player.requestPictureInPicture = this.requestPictureInPicture;\n this.player.exitPictureInPicture = this.exitPictureInPicture;\n }\n\n public initialize(): void {\n const toggleParent = this.player.getChild('collapserator');\n\n this.toggle = toggleParent.addChild('pictureInPictureToggle', {}) as videojs.Button;\n\n /**\n * By default the toggle is initialised in a disabled state.\n */\n this.toggle.enable();\n\n this.player.on('playerresize', this.onPlayerResize);\n\n this.player.on('dispose', () => {\n this.player?.off('playerresize', this.onPlayerResize);\n });\n }\n\n public togglePictureInPicture(isInPictureInPicture: boolean): void {\n if (isInPictureInPicture === this.player.isInPictureInPicture())\n return;\n\n const event = isInPictureInPicture ?\n 'enterpictureinpicture' :\n 'leavepictureinpicture';\n\n this.player.isInPictureInPicture(isInPictureInPicture);\n this.player.trigger(event);\n\n isInPictureInPicture ? this.addPipStyles() : this.removePipStyles();\n }\n\n private onPlayerResize(): void {\n /**\n * Don't enable/disable PiP while in PiP.\n */\n if (this.player.isInPictureInPicture())\n return;\n\n const playerRect = this.player.el().getBoundingClientRect();\n\n /**\n * In case our update function runs before our\n * player has properly rendered within the DOM\n */\n if (playerRect.width === 0)\n return;\n\n if (playerRect.width < MIN_WIDTH)\n this.toggle?.hide();\n else\n this.toggle?.show();\n }\n\n private addPipStyles(): void {\n this.player.addClass('cv-picture-in-picture');\n this.playToggle = new PlayToggle(this.player);\n this.playToggle.addClass('cv-pip-play-toggle');\n this.player.addChild(this.playToggle);\n\n if (this.player.paused())\n (this.playToggle as any).handlePause();\n else\n (this.playToggle as any).handlePlay();\n }\n\n private removePipStyles(): void {\n this.player.removeClass('cv-picture-in-picture');\n this.player.removeChild(this.playToggle);\n delete this.playToggle;\n }\n \n private requestPictureInPicture(): Promise<videojs.PictureInPictureWindow> {\n this.togglePictureInPicture(true);\n\n if (typeof this.options?.onRequestPictureInPicture === 'function')\n this.options.onRequestPictureInPicture(true);\n\n return;\n }\n\n private async exitPictureInPicture(): Promise<void> {\n this.togglePictureInPicture(false);\n this.options.onRequestPictureInPicture(false);\n this.removePipStyles();\n }\n\n public dispose(): void {\n this.player.requestPictureInPicture = this.playerRequestPictureInPictureFn;\n this.player.exitPictureInPicture = this.playerExitPictureInPictureFn;\n super.dispose();\n }\n}\n\nvideojs.registerPlugin('pictureInPicture', PictureInPicturePlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n pictureInPicture(options?: PictureInPicturePluginOptions): PictureInPicturePlugin;\n isInPictureInPicture(isPiP?: boolean): boolean | void;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { EventsService, StaticEventsService } from 'libs/common/react/services/EventsService';\n\nimport { PointOfInterest } from 'libs/shared/interfaces';\n\nimport { MouseTimeDisplay } from 'projects/player/components/mouse-time-display/mouse-time-display';\nimport { TimeTooltip } from 'projects/player/components/time-tooltip/time-tooltip';\n\nimport './point-of-interest-indicator.scss';\n\nconst Component = videojs.getComponent('Component');\n\ninterface PointOfInterestIndicatorOptions extends videojs.ComponentOptions {\n pointOfInterest: PointOfInterest;\n}\n\nexport class PointOfInterestIndicator extends Component {\n private el_: HTMLElement;\n public options_: PointOfInterestIndicatorOptions;\n\n private eventsService: StaticEventsService;\n\n private pointOfInterest: PointOfInterest;\n private hasBuffered: boolean = false;\n private hasPlayed: boolean = false;\n\n constructor(player: VideoJsPlayer, options: PointOfInterestIndicatorOptions) {\n super(player, options);\n\n this.eventsService = EventsService;\n\n this.pointOfInterest = options.pointOfInterest;\n\n this.onMouseOver = this.onMouseOver.bind(this);\n this.onMouseLeave = this.onMouseLeave.bind(this);\n this.onGlancePointOfInterestMouseEnter = this.onGlancePointOfInterestMouseEnter.bind(this);\n this.onGlancePointOfInterestMouseLeave = this.onGlancePointOfInterestMouseLeave.bind(this);\n\n this.initialize();\n }\n\n public initialize(): void {\n this.setPosition();\n this.bindListeners();\n }\n\n public buildCSSClass(): string {\n return `cv-point-of-interest-indicator ${super.buildCSSClass()}`;\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n return super.createEl(tagName, {\n ...properties,\n className: this.buildCSSClass()\n }, attributes);\n }\n\n private bindListeners(): void {\n this.on('mouseover', this.onMouseOver);\n this.on('mouseleave', this.onMouseLeave);\n\n this.eventsService.subscribe('glance:poi:mouseover', this.onGlancePointOfInterestMouseEnter);\n this.eventsService.subscribe('glance:poi:mouseleave', this.onGlancePointOfInterestMouseLeave);\n }\n\n public dispose(): void {\n this.eventsService.unsubscribe('glance:poi:mouseover', this.onGlancePointOfInterestMouseEnter);\n this.eventsService.unsubscribe('glance:poi:mouseleave', this.onGlancePointOfInterestMouseLeave);\n }\n\n private getPointOfInterestTime(): number {\n return this.pointOfInterest.startTime;\n }\n\n private setPosition(): void {\n const duration = this.player().duration();\n this.el_.style.left = (this.getPointOfInterestTime() / duration * 100) + '%';\n }\n\n public updateBuffered(bufferEnd: number): void {\n const hasBuffered = this.getPointOfInterestTime() <= bufferEnd;\n\n if (hasBuffered === this.hasBuffered)\n return;\n\n this.hasBuffered = hasBuffered;\n\n const bufferedClassName = 'cv-point-of-interest-indicator-buffered';\n\n if (this.hasBuffered)\n this.addClass(bufferedClassName);\n else\n this.removeClass(bufferedClassName);\n }\n\n public updatePlaybackProgress(currentTime: number): void {\n const hasPlayed = this.getPointOfInterestTime() <= currentTime;\n\n if (hasPlayed === this.hasPlayed)\n return;\n\n this.hasPlayed = hasPlayed;\n\n const className = 'cv-point-of-interest-indicator-played';\n\n if (hasPlayed)\n this.addClass(className);\n else\n this.removeClass(className);\n }\n\n public toggleVisibility(visible: boolean): void {\n const visibilityClassName = 'cv-point-of-interest-indicator-hidden';\n\n if (visible)\n this.removeClass(visibilityClassName);\n else\n this.addClass(visibilityClassName);\n }\n\n /**\n * We want the POI description to be displayed in the TimeTooltip when the user\n * hovers over a POI.\n * Because we don't know the exact time range on the seekbar covered by a POI indicator,\n * TimeTooltip can't use the current time to determine the active POI cue the same way\n * that it does for chapters. So instead we use the mouse events on this component and\n * set it manually.\n */\n private onMouseOver(): void {\n this.setTimeTooltipText();\n this.eventsService.trigger('player:poi:mouseover', this.pointOfInterest);\n }\n\n private onMouseLeave(): void {\n this.clearTimeTooltipText();\n this.eventsService.trigger('player:poi:mouseleave');\n }\n\n private onGlancePointOfInterestMouseEnter(pointOfInterest: PointOfInterest): void {\n if (pointOfInterest.id !== this.pointOfInterest.id)\n return;\n\n this.addClass('cv-point-of-interest-indicator-highlight');\n this.setTimeTooltipTime();\n this.setTimeTooltipText();\n this.positionMouseTimeDisplay();\n this.showMouseTimeDisplay();\n }\n\n private onGlancePointOfInterestMouseLeave(): void {\n this.removeClass('cv-point-of-interest-indicator-highlight');\n this.hideMouseTimeDisplay();\n }\n\n private setTimeTooltipText(): void {\n this.getTimeTooltip()?.setCustomChapterText(this.pointOfInterest.description);\n }\n\n private clearTimeTooltipText(): void {\n this.getTimeTooltip()?.setCustomChapterText();\n }\n\n /**\n * We only need to call this when we're manually forcing the MouseTimeDisplay\n * to show. If it's being triggered natively using pointer events then the time\n * will be set automatically.\n */\n private setTimeTooltipTime(): void {\n const timeTooltip = this.getTimeTooltip();\n timeTooltip?.updateTime(this.getPointOfInterestTime());\n }\n\n private positionMouseTimeDisplay(): void {\n const seekBarEl = this.getSeekBar()?.el();\n\n if (!seekBarEl)\n return;\n\n const seekBarRect = videojs.dom.findPosition(seekBarEl) as ClientRect;\n const point = this.getPointOfInterestTime() / this.player().duration();\n\n this.getMouseTimeDisplay()?.update(seekBarRect, point);\n }\n\n private showMouseTimeDisplay(): void {\n this.getMouseTimeDisplay()?.forceShow();\n }\n\n private hideMouseTimeDisplay(): void {\n this.getMouseTimeDisplay()?.removeForceShow();\n }\n\n private getSeekBar(): videojs.SeekBar {\n return this.player().controlBar\n .getChild('ProgressControl')\n ?.getChild('SeekBar') as videojs.SeekBar;\n }\n\n private getMouseTimeDisplay(): MouseTimeDisplay {\n return this.getSeekBar()\n ?.getChild('MouseTimeDisplay') as MouseTimeDisplay;\n }\n\n private getTimeTooltip(): TimeTooltip {\n return this.getMouseTimeDisplay()\n ?.getChild('TimeTooltip') as TimeTooltip;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport './points-of-interest-menu-item.scss';\n\nconst MenuItem = videojs.getComponent('MenuItem');\n\ninterface PointsOfInterestMenuItemOptions extends videojs.MenuItemOptions {\n pointsOfInterestVisible: boolean;\n}\n\nexport class PointsOfInterestMenuItem extends MenuItem {\n private toggleEl: Element;\n private pointsOfInterestVisible: boolean;\n\n /**\n * Because we want to bind our listener in createEl\n * and createEl runs in super. We store if we've bounud\n * our handler, so we only call bind once and \n * the call to removeEventListener will still work\n */\n private handlerBound: boolean;\n\n constructor(player: VideoJsPlayer, options: PointsOfInterestMenuItemOptions) {\n super(player, options);\n\n this.pointsOfInterestVisible = options.pointsOfInterestVisible;\n this.toggle(this.pointsOfInterestVisible);\n }\n\n public handleToggle(): void {\n this.toggle(!this.pointsOfInterestVisible);\n }\n\n private toggle(state: boolean): void {\n state ? this.toggleOn() : this.toggleOff();\n }\n\n private toggleOn(): void {\n videojs.dom.addClass(this.toggleEl, 'on');\n videojs.dom.setAttribute(this.toggleEl, 'aria-checked', 'true');\n this.pointsOfInterestVisible = true;\n this.player().pointsOfInterestPlugin().togglePointsOfInterest(this.pointsOfInterestVisible);\n }\n\n private toggleOff(): void {\n videojs.dom.removeClass(this.toggleEl, 'on');\n videojs.dom.setAttribute(this.toggleEl, 'aria-checked', 'false');\n this.pointsOfInterestVisible = false;\n this.player().pointsOfInterestPlugin().togglePointsOfInterest(this.pointsOfInterestVisible);\n }\n\n /**\n * Because we extend MenuItem which will close the menu by default\n * we need to halt the event propogation here\n */\n public handleClick(event: videojs.EventTarget.Event): void {\n event.stopImmediatePropagation();\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): HTMLLIElement {\n /**\n * Bind our event listener only once\n * see the comment where handlerBound is defined\n */\n if (!this.handlerBound) {\n this.handleToggle = this.handleToggle.bind(this);\n this.handlerBound = true;\n }\n\n if (this.toggleEl)\n this.toggleEl.removeEventListener('click', this.handleToggle);\n\n this.toggleEl = videojs.dom.createEl('div', {\n className: `custom-toggle custom-toggle-info toggle-option float-end`,\n innerHTML: '<span class=\"handle\"></span></div>'\n });\n videojs.dom.setAttribute(this.toggleEl, 'id', 'poi-toggle');\n videojs.dom.setAttribute(this.toggleEl, 'role', 'switch');\n this.toggleEl.addEventListener('click', this.handleToggle);\n\n const innerHTML = `\n <span for=\"poi-toggle\" class=\"vjs-menu-item-text\">Points of Interest</span>\n <span class=\"cv-toggle-container\"></span>`;\n\n const el = super.createEl(tagName, {\n className: 'vjs-menu-item cv-cog-menu-item cv-poi-toggle',\n innerHTML\n }, attributes);\n\n /**\n * Indexing into the child this way is only safe to do because\n * we know that the el only has two children\n */\n el.children[1].appendChild(this.toggleEl);\n\n return el;\n }\n}\n\nvideojs.registerComponent('PointsOfInterestMenuItem', PointsOfInterestMenuItem);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { PointOfInterest } from 'libs/shared/interfaces';\n\nimport { CogButton } from 'projects/player/components/cog-button/cog-button';\nimport { getBufferedEnd } from 'projects/player/utils/getBufferedEnd';\nimport { LocalStorageHelper } from 'projects/player/utils/local-storage-helper';\n\nimport { PointOfInterestIndicator } from './components/point-of-interest-indicator/point-of-interest-indicator';\nimport { PointsOfInterestMenuItem } from './components/points-of-interest-menu-item/points-of-interest-menu-item';\n\nconst Plugin = videojs.getPlugin('plugin');\n\nconst POINTS_OF_INTEREST = 'cvplayer-points-of-interest';\n\ninterface PointsOfInterestPluginOptions {\n pointsOfInterest: PointOfInterest[];\n}\n\nexport class PointsOfInterestPlugin extends Plugin {\n private pointOfInterestIndicators: PointOfInterestIndicator[] = [];\n private pointsOfInterest?: PointOfInterest[];\n private enabled: boolean = true;\n\n constructor(player: VideoJsPlayer, options?: PointsOfInterestPluginOptions) {\n super(player);\n\n this.pointsOfInterest = options?.pointsOfInterest;\n \n this.initialize = this.initialize.bind(this);\n this.updateBuffered = this.updateBuffered.bind(this);\n this.updatePlaybackProgress = this.updatePlaybackProgress.bind(this);\n\n this.player.one('loadedmetadata', () => this.player.ready(this.initialize));\n }\n\n private initialize(): void {\n if (!this.pointsOfInterest)\n return;\n\n if (LocalStorageHelper.hasLocalStorage() && LocalStorageHelper.get(POINTS_OF_INTEREST) === 'false')\n this.enabled = false;\n\n this.setupTrack();\n this.createPointOfInterestIndicators();\n this.addMenuItem();\n this.bindListeners();\n }\n\n private bindListeners(): void {\n this.player.on('progress', this.updateBuffered);\n this.player.on('timeupdate', this.updatePlaybackProgress);\n\n this.player.on('dispose', () => {\n this.player?.off('progress', this.updateBuffered);\n this.player?.off('timeupdate', this.updatePlaybackProgress);\n });\n }\n\n public togglePointsOfInterest(visible: boolean): void {\n LocalStorageHelper.set(POINTS_OF_INTEREST, visible.toString());\n this.pointOfInterestIndicators.forEach(p => p.toggleVisibility(visible));\n }\n\n private setupTrack(): void {\n const track = this.player.addTextTrack('metadata', 'pointsofinterest') as any;\n\n this.pointsOfInterest.forEach(p => {\n track.addCue({\n startTime: p.startTime,\n endTime: p.endTime,\n text: p.description\n });\n });\n\n track.trigger({\n type: 'loadeddata',\n target: track\n });\n }\n\n private createPointOfInterestIndicators(): void {\n const seekBar = this.player.controlBar.getChild('ProgressControl')?.getChild('SeekBar');\n \n this.pointsOfInterest.forEach(pointOfInterest => {\n const component = new PointOfInterestIndicator(this.player, { pointOfInterest });\n this.pointOfInterestIndicators.push(component);\n seekBar.addChild(component);\n });\n }\n\n private addMenuItem(): void {\n /**\n * Check additionalItemOrder in cog-button.ts if you need to change the order. - Sha\n */\n const cogButton = this.player.getChild('collapserator')?.getChild('cogButton') as CogButton;\n cogButton.addItem({\n ctor: PointsOfInterestMenuItem,\n name: 'PointsOfInterestMenuItem',\n options: { pointsOfInterestVisible: this.enabled }\n });\n }\n\n private updateBuffered(): void {\n this.pointOfInterestIndicators.forEach(p => p.updateBuffered(getBufferedEnd(this.player)));\n }\n\n private updatePlaybackProgress(): void {\n this.pointOfInterestIndicators.forEach(p => p.updatePlaybackProgress(this.player.currentTime()));\n }\n}\n\nvideojs.registerPlugin('pointsOfInterestPlugin', PointsOfInterestPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n pointsOfInterestPlugin(options?: PointsOfInterestPluginOptions): PointsOfInterestPlugin;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport './range-indicator.scss';\n\nconst Component = videojs.getComponent('Component');\n\ninterface RangeIndicatorOptions extends videojs.ComponentOptions {\n time: number;\n}\n\nexport class RangeIndicator extends Component {\n private el_: HTMLElement;\n public options_: RangeIndicatorOptions;\n\n constructor(player: VideoJsPlayer, options: RangeIndicatorOptions) {\n super(player, options);\n\n this.initialize();\n }\n\n public initialize(): void {\n this.setPosition();\n }\n\n public buildCSSClass(): string {\n return `cv-range-indicator ${super.buildCSSClass()}`;\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n return super.createEl(tagName, {\n ...properties,\n className: this.buildCSSClass()\n }, attributes);\n }\n\n private setPosition(): void {\n const duration = this.player().duration();\n this.el_.style.left = (this.options_.time / duration * 100) + '%';\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport './replay-view-button.scss';\n\nconst ClickableComponent = videojs.getComponent('ClickableComponent');\n\ninterface ReplayViewButtonOptions extends videojs.ComponentOptions {\n onPress: () => void;\n label: string;\n iconClassName: 'cv-replay-icon' | 'cv-continue-icon';\n}\n\nexport class ReplayViewButton extends ClickableComponent {\n public options_: ReplayViewButtonOptions;\n\n constructor(player: VideoJsPlayer, options: ReplayViewButtonOptions) {\n super(player, options);\n }\n\n public buildCSSClass(): string {\n return `cv-replay-view-button ${super.buildCSSClass()}`;\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n const el = super.createEl(tagName, {\n ...properties,\n innerHTML: `<span class=\"${this.options_.iconClassName}\"></span><span>${this.options_.label}</span>`,\n className: this.buildCSSClass()\n }, attributes);\n\n return el;\n }\n\n public handleClick() {\n this.options_.onPress();\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { ReplayViewButton } from 'projects/player/plugins/range-indicator-plugin/components/replay-view-button/replay-view-button';\n\nimport './replay-view.scss';\n\nconst Component = videojs.getComponent('Component');\n\ninterface ReplayViewOptions extends videojs.ComponentOptions {\n onContinuePress: () => void;\n onReplayPress: () => void;\n}\n\nexport class ReplayView extends Component {\n public options_: ReplayViewOptions;\n\n constructor(player: VideoJsPlayer, options: ReplayViewOptions) {\n super(player, options);\n }\n\n public buildCSSClass(): string {\n return `cv-replay-view ${super.buildCSSClass()}`;\n }\n\n public createEl(tagName?: string, properties?: any, attributes?: any): Element {\n const el = super.createEl(tagName, {\n ...properties,\n className: this.buildCSSClass()\n }, attributes);\n\n const heading = videojs.dom.createEl('h5', {\n innerHTML: this.localize('This clip has finished'),\n className: 'cv-replay-heading'\n });\n\n const buttonContainer = videojs.dom.createEl('div', {\n className: 'cv-button-container'\n });\n\n const replayButton = new ReplayViewButton(this.player_, {\n label: this.localize('Replay clip'),\n iconClassName: 'cv-replay-icon',\n onPress: this.options_.onReplayPress\n });\n\n const continueButton = new ReplayViewButton(this.player_, {\n label: this.localize('Continue watching'),\n iconClassName: 'cv-continue-icon',\n onPress: this.options_.onContinuePress\n });\n\n el.appendChild(heading);\n el.appendChild(buttonContainer);\n \n buttonContainer.appendChild(replayButton.el());\n buttonContainer.appendChild(continueButton.el());\n \n return el;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { RangeIndicator } from './components/range-indicator/range-indicator';\nimport { ReplayView } from './components/replay-view/replay-view';\n\nimport './range-indicator-plugin.scss';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface RangeIndicatorPluginOptions {\n startTime: number;\n endTime: number;\n}\n\nclass RangeIndicatorPlugin extends Plugin {\n private startTime: number;\n private endTime: number;\n private dismissed: boolean;\n private startTimeIndicator?: RangeIndicator;\n private endTimeIndicator?: RangeIndicator;\n private replayView?: ReplayView;\n\n constructor(player: VideoJsPlayer, options: RangeIndicatorPluginOptions) {\n super(player, options);\n\n this.startTime = parseFloat(options.startTime.toPrecision(4));\n this.endTime = parseFloat(options.endTime.toPrecision(4));\n this.dismissed = false;\n \n if (this.startTime > this.endTime)\n throw Error('Range start cannot be greater than range end');\n\n this.bindFunctions();\n this.initialize();\n }\n\n private bindFunctions(): void {\n this.onReady = this.onReady.bind(this);\n this.onTimeUpdateOrSeeked = this.onTimeUpdateOrSeeked.bind(this);\n this.onReplayPress = this.onReplayPress.bind(this);\n this.onContinuePress = this.onContinuePress.bind(this);\n }\n\n private initialize(): void {\n this.player.one('loadedmetadata', () => this.player.ready(this.onReady));\n this.player.on('timeupdate', this.onTimeUpdateOrSeeked);\n this.player.on('seeked', this.onTimeUpdateOrSeeked);\n }\n\n private onReady(): void {\n this.addCssClasses();\n this.showRangeIndicators();\n this.addMaskToProgressBar();\n }\n\n private onTimeUpdateOrSeeked(): void {\n if (this.dismissed) return;\n\n const currentTime = this.player.currentTime();\n\n if (currentTime < this.startTime) {\n this.player.currentTime(this.startTime);\n\n return;\n }\n\n if (currentTime > this.endTime) {\n this.showReplayView();\n this.disablePlayToggle();\n this.player.pause();\n this.player.currentTime(this.endTime);\n\n return;\n }\n }\n\n private onReplayPress(): void {\n this.player.currentTime(this.startTime);\n this.player.play();\n this.hideReplayView();\n this.enablePlayToggle();\n }\n\n private onContinuePress(): void {\n this.dismissed = true;\n this.player.play();\n this.hideRangeIndicators();\n this.removeMaskFromProgressBar();\n this.hideReplayView();\n this.enablePlayToggle();\n this.removeCssClasses();\n }\n\n private showRangeIndicators(): void {\n const seekBar = this.player.controlBar.getChild('ProgressControl')?.getChild('SeekBar');\n\n if (!this.startTimeIndicator) {\n this.startTimeIndicator = new RangeIndicator(this.player, { time: this.startTime });\n seekBar?.addChild(this.startTimeIndicator);\n }\n\n if (!this.endTimeIndicator) {\n this.endTimeIndicator = new RangeIndicator(this.player, { time: this.endTime });\n seekBar?.addChild(this.endTimeIndicator);\n }\n }\n\n private hideRangeIndicators(): void {\n this.startTimeIndicator?.hide();\n this.endTimeIndicator?.hide();\n }\n\n private addMaskToProgressBar(): void {\n const seekBar = this.player.controlBar.getChild('ProgressControl')?.getChild('SeekBar');\n const elements = seekBar?.el().getElementsByClassName('cv-chapter-bar-items');\n\n if (elements && elements.length) {\n const progressBar = elements[0] as HTMLElement;\n const duration = this.player.duration();\n const leftInset = this.startTime / duration * 100;\n const rightInset = 100 - (this.endTime / duration * 100);\n const verticalInset = -5; // Increase the mask vertically to account for the thumbtack during scrubbing\n\n progressBar.style.clipPath = `inset(${verticalInset}em ${rightInset}% ${verticalInset}em ${leftInset}%)`;\n }\n }\n\n private removeMaskFromProgressBar(): void {\n const seekBar = this.player.controlBar.getChild('ProgressControl')?.getChild('SeekBar');\n const elements = seekBar?.el().getElementsByClassName('cv-chapter-bar-items');\n\n if (elements && elements.length) {\n const progressBar = elements[0] as HTMLElement;\n\n progressBar.style.clipPath = '';\n }\n }\n\n private showReplayView(): void {\n if (!this.replayView) {\n this.replayView = new ReplayView(this.player, {\n onContinuePress: this.onContinuePress,\n onReplayPress: this.onReplayPress\n });\n \n this.player.addChild(this.replayView);\n }\n\n this.replayView.show();\n }\n\n private hideReplayView(): void {\n this.replayView?.hide();\n }\n\n private getPlayToggle(): videojs.Button | undefined {\n const collapserator = this.player.getChild('collapserator');\n return collapserator?.getChild('PlayToggle') as videojs.Button;\n }\n\n private enablePlayToggle(): void {\n const playToggle = this.getPlayToggle();\n \n if (playToggle)\n playToggle.enable();\n }\n\n private disablePlayToggle(): void {\n const playToggle = this.getPlayToggle();\n \n if (playToggle)\n playToggle.disable();\n }\n\n private addCssClasses(): void {\n this.player.addClass('cv-range-indicator-plugin');\n }\n\n private removeCssClasses(): void {\n this.player.removeClass('cv-range-indicator-plugin');\n }\n\n public dispose(): void {\n this.removeCssClasses();\n\n this.player.off('timeupdate', this.onTimeUpdateOrSeeked);\n this.player.off('seeked', this.onTimeUpdateOrSeeked);\n \n this.startTimeIndicator?.dispose();\n this.endTimeIndicator?.dispose();\n this.replayView?.dispose();\n\n super.dispose();\n }\n}\n\nvideojs.registerPlugin('rangeIndicatorPlugin', RangeIndicatorPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n rangeIndicatorPlugin(options: RangeIndicatorPluginOptions): void;\n }\n}\n","export const IdHelper = {\n generateRandomId: () => {\n return (window.crypto as any)?.randomUUID?.() ?? Math.random().toString();\n }\n};\n","/* eslint simple-import-sort/imports: 0 */\n\nimport { VideoJsPlayerOptions } from 'video.js';\nimport { BasePlayer, BasePlayerOptions } from './base-player';\n\nimport { PointOfInterest } from 'libs/shared/interfaces';\nimport { ShareActivityStatus } from 'libs/shared/enums/ShareActivityStatus';\nimport 'projects/player/plugins/clip-plugin/clip-plugin';\n\nimport 'projects/player/plugins/create-clip-button-plugin/create-clip-button-plugin';\n\nimport 'projects/player/plugins/picture-in-picture-plugin/picture-in-picture-plugin';\nimport 'projects/player/plugins/points-of-interest-plugin/points-of-interest-plugin';\nimport 'projects/player/plugins/activity-status-plugin/activity-status-plugin';\nimport 'projects/player/plugins/range-indicator-plugin/range-indicator-plugin';\nimport 'projects/player/plugins/theatre-mode-plugin/theatre-mode-plugin';\nimport 'projects/player/plugins/loop-video-plugin/loop-video-plugin';\n\nimport { PlaybackObject } from 'projects/player/interfaces/models/PlaybackObject';\nimport { ClipData } from 'projects/player/interfaces/models/ClipData';\nimport { NextVideo } from 'projects/player/interfaces/NextVideo';\n\nimport { IdHelper } from '../utils/id-helper';\nimport { TrackHelper } from 'projects/player/utils/track-helper';\n\nexport interface PlayerOptions extends BasePlayerOptions {\n showResources?: boolean;\n pointsOfInterest?: PointOfInterest[];\n}\n\nexport class Player extends BasePlayer {\n declare protected options: PlayerOptions;\n\n constructor(id: string | Element, options: PlayerOptions) {\n super(id, options);\n }\n\n protected getPlayerOptions(): VideoJsPlayerOptions {\n const options = super.getPlayerOptions();\n\n if (this.options.allowTranscript) {\n options.allowTranscript = true;\n }\n\n if (options.devicesConfig?.canUserCastToDevices) {\n return {\n ...options,\n techOrder: [ 'devices', ...options.techOrder ],\n devices: {\n instanceId: IdHelper.generateRandomId()\n }\n };\n }\n\n return options;\n }\n\n protected configurePlugins(): void {\n try {\n if (this.options.onClickCreateClip) {\n this.player.createClipButtonPlugin({\n onClick: this.options.onClickCreateClip\n });\n }\n\n if (this.options.onRequestPictureInPicture) {\n this.player.pictureInPicture({\n onRequestPictureInPicture: this.options.onRequestPictureInPicture\n });\n }\n\n if (this.options.pointsOfInterest?.length) {\n this.player.pointsOfInterestPlugin({\n pointsOfInterest: this.options.pointsOfInterest\n });\n }\n\n this.player.loopVideoPlugin({ allowLoop: this.options.allowLoop });\n } catch (ex) {\n console.log('failed to register plugins', ex);\n }\n }\n\n public setNextVideo(nextVideo: NextVideo, playNext: boolean, onPlayNext: () => void): void {\n /**\n * Next video plugin needs to be imported separately to be used \n * This is because it uses react components.\n * We want to keep react out of our main player bundle. - Sha\n */\n if (!this.player.nextVideoPlugin)\n return;\n\n const plugin = this.player.nextVideoPlugin();\n plugin.setNextVideo(nextVideo, playNext, onPlayNext);\n }\n\n public togglePictureInPicture(isInPictureInPicture: boolean): void {\n const plugin = this.player.pictureInPicture();\n\n if (plugin)\n plugin.togglePictureInPicture(isInPictureInPicture);\n }\n\n public toggleTheatreMode(status?: boolean): void {\n const plugin = this.player.theatreModePlugin();\n\n if (plugin)\n plugin.toggleTheatreMode(status, { shouldLog: true });\n }\n\n public toggleTranscript(status?: boolean): void {\n if (!this.player.viewTranscriptPlugin)\n return;\n\n const plugin = this.player.viewTranscriptPlugin();\n\n if (plugin)\n plugin.toggleTranscript(status);\n }\n\n public hasStarted(): boolean {\n return this.player.hasStarted();\n }\n\n protected async additionalSetup(playbackObject: PlaybackObject): Promise<void> {\n // instantiate before calling super\n // ensure the theatreMode is set up first before theatre mode registerAnalytics is called\n if (this.options.onRequestTheatreMode && this.options.allowTheatreMode && this.player.theatreModePlugin) {\n this.player.theatreModePlugin({\n onRequestTheatreMode: this.options.onRequestTheatreMode,\n theatreMode: this.options.theatreMode,\n playbackObject\n });\n }\n\n super.additionalSetup(playbackObject);\n\n /**\n * Resources plugin needs to be imported seperately to be used \n * This is because it uses react components.\n * We want to keep react out of our main player bundle. - Sha\n */\n if (this.options.showResources && playbackObject.resources && this.player.resourcesPlugin) {\n this.player.resourcesPlugin({\n resources: playbackObject.resources.list,\n imageCdnUrl: this.options.imageCdnUrl\n });\n }\n\n if (playbackObject.mediaType === 'MasterClip') {\n const clipData = playbackObject.additionalData as ClipData;\n\n if (clipData === null)\n throw Error('Invalid clip data');\n\n this.player.clipPlugin({\n startTime: clipData.startTime,\n endTime: clipData.endTime\n });\n }\n\n /**\n * The range indicator plugin is only applicable when watching videos\n */\n if (playbackObject.mediaType === 'MasterVideo' && this.options.startTime && this.options.endTime) {\n this.player.rangeIndicatorPlugin({\n startTime: this.options.startTime,\n endTime: this.options.endTime\n });\n }\n }\n\n protected setupAnalyticsDependentPlugins(playbackObject: PlaybackObject): void {\n super.setupAnalyticsDependentPlugins(playbackObject);\n\n if (this.options.allowTranscript) {\n this.player.viewTranscriptPlugin().registerAnalytics(\n this.analyticsService,\n playbackObject\n );\n }\n\n if (this.options.onRequestTheatreMode && this.options.allowTheatreMode && this.player.theatreModePlugin) {\n this.player.theatreModePlugin().registerAnalytics(\n this.analyticsService\n );\n }\n\n /**\n * The devices plugin needs to be imported separately to be used \n * This is because it uses react components.\n * We want to keep react out of our main player bundle. - Sha\n */\n if (this.options.devicesConfig?.canUserCastToDevices && this.player.devicesPlugin) {\n this.player.devicesPlugin({\n ...this.options.devicesConfig,\n userId: parseInt(playbackObject.viewerId),\n title: playbackObject.title,\n analyticsService: this.analyticsService\n });\n }\n }\n\n public setActivityStatus(status: ShareActivityStatus, onToggle: () => void): void {\n const plugin = this.player.activityStatusPlugin();\n plugin.setActivityStatus(status, onToggle);\n }\n\n public useCurrentTranscript(callback: (track: TextTrack) => void, language?: string): void {\n // eslint-disable-next-line react-hooks/rules-of-hooks \n TrackHelper.useMetadataTracks(this.player, 'transcript', callback, language);\n }\n\n public useChapters(callback: (track: TextTrack) => void): void {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n TrackHelper.useChapters(this.player, callback);\n }\n}\n","/**\n * Inspired by https://github.com/marchaos/resilient-websocket\n */\n\nimport { Scheduler } from './scheduler';\n\ntype MessageData = string | ArrayBufferLike | Blob | ArrayBufferView;\n\ninterface ResilientWebSocketOptions {\n reconnectIntervalInMilliseconds?: number;\n heartbeatEnabled?: boolean;\n heartbeatIntervalInMillseconds?: number;\n heartbeatMessage?: MessageData;\n}\n\nconst defaultOptions: ResilientWebSocketOptions = {\n reconnectIntervalInMilliseconds: 3000,\n heartbeatEnabled: false,\n heartbeatIntervalInMillseconds: 10000,\n heartbeatMessage: ''\n};\n\nexport class ResilientWebSocket {\n private readonly url: string;\n private readonly options: ResilientWebSocketOptions;\n \n private webSocket: WebSocket;\n private heartbeat: Scheduler;\n\n public onOpen?: (event: Event) => void;\n public onClose?: (event?: CloseEvent) => void;\n public onMessage?: (event: MessageEvent) => void;\n public onError?: (event: Event) => void;\n \n constructor(url: string, options: ResilientWebSocketOptions = defaultOptions) {\n this.bindFunctions();\n\n this.url = url;\n this.options = { ...defaultOptions, ...options };\n this.webSocket = this.connect();\n this.heartbeat = new Scheduler()\n .schedule(() => this.send(this.options.heartbeatMessage))\n .every(this.options.heartbeatIntervalInMillseconds);\n }\n\n private bindFunctions(): void {\n this.cleanup = this.cleanup.bind(this);\n this.handleOpen = this.handleOpen.bind(this);\n this.handleMessage = this.handleMessage.bind(this);\n this.handleClose = this.handleClose.bind(this);\n this.handleError = this.handleError.bind(this);\n this.connect = this.connect.bind(this);\n this.send = this.send.bind(this);\n this.dipose = this.dipose.bind(this);\n }\n\n private cleanup(): void {\n this.heartbeat.stop();\n\n this.webSocket.removeEventListener('error', this.handleError);\n this.webSocket.removeEventListener('message', this.handleMessage);\n this.webSocket.removeEventListener('open', this.handleOpen);\n this.webSocket.removeEventListener('close', this.handleClose);\n }\n\n private handleOpen(event?: Event): void {\n this.onOpen?.(event);\n\n if (this.options.heartbeatEnabled)\n this.heartbeat.start();\n }\n\n private handleMessage(event: MessageEvent): void {\n this.onMessage?.(event);\n }\n\n private handleClose(event?: CloseEvent): void {\n this.onClose?.(event);\n\n this.cleanup();\n\n setTimeout(() => {\n this.webSocket = this.connect();\n }, this.options.reconnectIntervalInMilliseconds);\n }\n\n private handleError(event: Event): void {\n this.onError?.(event);\n this.handleClose();\n }\n\n public connect(): WebSocket {\n const socket = new WebSocket(this.url);\n \n socket.addEventListener('open', this.handleOpen);\n socket.addEventListener('message', this.handleMessage);\n socket.addEventListener('close', this.handleClose);\n socket.addEventListener('error', this.handleError);\n\n return socket;\n }\n\n public send(data: MessageData): void {\n this.webSocket.send(data);\n }\n\n public dipose(): void {\n this.cleanup();\n this.webSocket.close();\n }\n}\n","import { Device } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\nimport { ProxyHelper } from 'projects/player/plugins/devices-plugin/utils/proxy-helper';\n\nconst PROPERTY_SETTER_DEBOUNCE_DURATION_IN_MILLISECONDS = 2000;\n\nexport class ViviCastSessionState {\n public duration: number | undefined;\n public mute: boolean;\n public videoSource: string;\n public subtitleSource: string;\n public subtitles: boolean;\n public volume: number;\n public title: string;\n public device: Device;\n public ready: boolean;\n public playbackFinished: boolean;\n public debounced: ViviCastSessionState;\n\n private _position: number;\n private _playing: boolean;\n private _timerStartedAt: number = 0;\n\n constructor(title: string, device: Device) {\n this.position = 0;\n this.duration = undefined;\n this.playing = false;\n this.mute = false;\n this.videoSource = '';\n this.subtitleSource = '';\n this.subtitles = false;\n this.volume = 0;\n this.title = title;\n this.device = device;\n this.ready = false;\n this.playbackFinished = false;\n this.debounced = ProxyHelper.withDebouncedSetters(this, PROPERTY_SETTER_DEBOUNCE_DURATION_IN_MILLISECONDS);\n \n return ProxyHelper.withTimestampedSetters(this);\n }\n\n public get position() {\n return this._position + this.getTimerDurationInSeconds();\n }\n \n public set position(val: number) {\n this._position = val;\n this.restartTimer();\n }\n\n public get playing() {\n return this._playing;\n }\n \n public set playing(val: boolean) {\n this._playing = val;\n\n if (val) {\n this.restartTimer();\n } else {\n this._position += this.getTimerDurationInSeconds();\n this.stopTimer();\n }\n }\n\n private restartTimer() {\n this._timerStartedAt = Date.now();\n }\n\n private stopTimer() {\n this._timerStartedAt = 0;\n }\n\n private getTimerDurationInSeconds() {\n if (this._timerStartedAt) {\n const duration = Date.now() - this._timerStartedAt;\n return duration / 1000;\n }\n\n return 0;\n }\n}\n","import { HashObject } from 'libs/common/react/interfaces';\n\nimport { ClientEvents } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\n\nexport interface ViviUrl {\n id?: string;\n url: string;\n title: string;\n suburl: string;\n}\n\nexport interface ViviRoom {\n id: string;\n name: string;\n organisation: string;\n location?: string;\n}\n\nexport interface ViviPlayState {\n duration: number;\n position: number;\n playing: boolean;\n volume: number;\n mute: boolean;\n chapter: number;\n subtitles: boolean;\n}\n\nexport interface ViviOutgoingIdentifyMessage {\n destination: 'relay';\n message: {\n type: 'identify_video_api',\n token: string\n };\n}\n\nexport interface ViviOutgoingRoomsMessage {\n destination: 'relay';\n message: {\n type: 'video_api_rooms'\n };\n}\n\nexport interface ViviOutgoingJoinRoomMessage {\n destination: 'relay';\n message: {\n type: 'connect',\n destination_type: 'box',\n new_destination: string,\n token: string\n };\n}\n\nexport interface ViviOutgoingQueryMessage {\n destination: string;\n message: {\n type: 'message_with_ack',\n name: 'query',\n ack_id: string\n };\n}\n\nexport interface ViviOutgoingQueueLoadMessage {\n destination: string;\n message: {\n type: 'message_with_ack',\n name: 'queue_load',\n ack_id: string,\n payload: {\n urls: ViviUrl[]\n }\n };\n}\n\nexport interface ViviOutgoingPlayMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'video_play',\n payload: HashObject // Yep, we need to send an empty object here\n };\n}\n\nexport interface ViviOutgoingPauseMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'video_pause'\n };\n}\n\nexport interface ViviOutgoingStopMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'video_stop'\n };\n}\n\nexport interface ViviOutgoingSeekMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'video_seek',\n payload: {\n position: number\n }\n };\n}\n\nexport interface ViviOutgoingVolumeMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'set_volume',\n payload: {\n volume: number\n }\n };\n}\n\nexport interface ViviOutgoingMuteMessage {\n destination: string;\n message: {\n type: 'message',\n name: 'set_mute',\n payload: {\n mute: boolean\n }\n };\n}\n\nexport interface ViviOutgoingSubtitleMessage {\n destination: string;\n message: {\n type: 'message_with_ack',\n name: 'set_subtitles',\n ack_id: string,\n payload: {\n subtitles: boolean\n }\n };\n}\n\nexport enum ViviEventName {\n Update = 'update',\n Volume = 'volume',\n Playing = 'playing',\n Paused = 'paused',\n NewChapter = 'new_chapter',\n Stopped = 'stopped',\n Ready = 'ready',\n Mute = 'mute',\n Finished = 'finished',\n Subtitles = 'subtitles'\n}\n\nexport type ViviOutgoingMessage =\n ViviOutgoingIdentifyMessage |\n ViviOutgoingRoomsMessage |\n ViviOutgoingJoinRoomMessage |\n ViviOutgoingQueryMessage |\n ViviOutgoingQueueLoadMessage |\n ViviOutgoingPlayMessage |\n ViviOutgoingPauseMessage |\n ViviOutgoingStopMessage |\n ViviOutgoingSeekMessage |\n ViviOutgoingVolumeMessage |\n ViviOutgoingMuteMessage |\n ViviOutgoingSubtitleMessage;\n\nexport interface ViviIncomingMessageParams {\n level?: number;\n chapter?: number;\n duration?: number;\n position?: number;\n playing?: boolean;\n mute?: boolean;\n subtitles?: boolean;\n queue?: ViviUrl[];\n}\n\nexport interface ViviIncomingMessagePayload {\n play_state?: ViviPlayState;\n urls?: ViviUrl[];\n event?: ViviEventName;\n params?: ViviIncomingMessageParams;\n}\n\nexport interface ViviIncomingMessage {\n source: string;\n message: {\n type: string,\n payload?: ViviIncomingMessagePayload,\n error_type?: string,\n ack_id?: string,\n rooms?: ViviRoom[]\n };\n}\n\nexport interface ViviLoadQueueRequest {\n roomId: string;\n title: string;\n videoSource: string;\n subtitleSource?: string;\n}\n\nexport interface ViviClientEventMap extends ClientEvents {\n message: ViviIncomingMessage;\n connected: void;\n}\n","import { CastSession, Device, SessionConfig, SessionEvents } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\nimport { Event, EventBus } from 'projects/player/plugins/devices-plugin/utils/event-bus';\n\nimport { ViviCastSessionState } from './vivi-cast-session-state';\nimport { ViviClient } from './vivi-client';\nimport { ViviEventName, ViviIncomingMessage, ViviIncomingMessageParams } from './vivi-interfaces';\n\nexport class ViviCastSession extends EventBus<SessionEvents> implements CastSession {\n private client: ViviClient;\n private localState: ViviCastSessionState;\n\n constructor(client: ViviClient, config: SessionConfig) {\n super();\n\n this.client = client;\n this.localState = new ViviCastSessionState(config.title, config.device);\n\n this.bindFunctions();\n this.initialize();\n }\n\n private bindFunctions(): void {\n this.initialize = this.initialize.bind(this);\n this.dispose = this.dispose.bind(this);\n \n this.handleClientConnected = this.handleClientConnected.bind(this);\n this.handleDisconnectMessage = this.handleDisconnectMessage.bind(this);\n this.handleAllVideoMessages = this.handleAllVideoMessages.bind(this);\n this.handleUpdateMessage = this.handleUpdateMessage.bind(this);\n this.handleVolumeMessage = this.handleVolumeMessage.bind(this);\n this.handlePlayingMessage = this.handlePlayingMessage.bind(this);\n this.handlePausedMessage = this.handlePausedMessage.bind(this);\n this.handleFinishedMessage = this.handleFinishedMessage.bind(this);\n this.handleNewChapterMessage = this.handleNewChapterMessage.bind(this);\n this.handleStoppedMessage = this.handleStoppedMessage.bind(this);\n\n this.loadSource = this.loadSource.bind(this);\n this.play = this.play.bind(this);\n this.pause = this.pause.bind(this);\n this.seek = this.seek.bind(this);\n this.setVolume = this.setVolume.bind(this);\n this.isPlaying = this.isPlaying.bind(this);\n this.getPosition = this.getPosition.bind(this);\n this.getDuration = this.getDuration.bind(this);\n this.getVolume = this.getVolume.bind(this);\n }\n\n private initialize(): void {\n // Subscribe to client diposed messages\n this.client.on('dispose', this.dispose);\n\n // Subscribe to client connected messages\n this.client.on('connected', this.handleClientConnected);\n\n // Subscribe to device disconnect messages\n this.client\n .on('message', this.handleDisconnectMessage)\n .filter(msg =>\n msg.source === this.getDevice().id &&\n msg.message.type === 'disconnect');\n\n // Subscribe to device video messages\n this.client\n .on('message', this.handleAllVideoMessages)\n .filter(msg =>\n msg.source === this.getDevice().id &&\n msg.message.type === 'video_event');\n }\n\n public dispose(): void {\n // Cleanup the subscriptions from the initialize function\n this.client.off('dispose', this.dispose);\n this.client.off('connected', this.handleClientConnected);\n this.client.off('message', this.handleDisconnectMessage);\n this.client.off('message', this.handleAllVideoMessages);\n\n // Do our best to signal to the device that we're done with it\n this.client.stop(this.getDevice().id).catch(err => console.error(err));\n\n // Trigger the dispose event\n super.dispose();\n }\n\n private async handleClientConnected(): Promise<void> {\n try {\n await this.client.joinRoom(this.getDevice().id);\n } catch (error) {\n this.trigger('error', error);\n }\n }\n\n private handleDisconnectMessage(): void {\n this.dispose();\n }\n\n private handleAllVideoMessages(msg: ViviIncomingMessage): void {\n const localState = this.localState.debounced;\n const remoteState = msg.message.payload.params || {};\n\n switch (msg.message.payload.event) {\n case ViviEventName.Update:\n this.handleUpdateMessage(localState, remoteState);\n break;\n\n case ViviEventName.NewChapter:\n this.handleNewChapterMessage(localState, remoteState);\n break;\n \n case ViviEventName.Volume:\n this.handleVolumeMessage(localState, remoteState);\n break;\n\n case ViviEventName.Playing:\n this.handlePlayingMessage(localState);\n break;\n\n case ViviEventName.Paused:\n this.handlePausedMessage(localState);\n break;\n\n case ViviEventName.Finished:\n this.handleFinishedMessage(localState);\n break;\n \n case ViviEventName.Stopped:\n this.handleStoppedMessage();\n break;\n }\n }\n\n private handleUpdateMessage(localState: ViviCastSessionState, remoteState: ViviIncomingMessageParams): void {\n if (localState.duration !== remoteState.duration) {\n localState.duration = remoteState.duration;\n this.trigger('durationchange', Event.void);\n }\n\n if (localState.position !== remoteState.position) {\n localState.position = remoteState.position;\n this.trigger('positionchange', Event.void);\n }\n\n if (localState.subtitles !== remoteState.subtitles) {\n localState.subtitles = remoteState.subtitles;\n this.trigger('subtitleschange', Event.void);\n }\n }\n\n private handleVolumeMessage(localState: ViviCastSessionState, remoteState: ViviIncomingMessageParams): void {\n if (localState.volume !== remoteState.level) {\n localState.volume = remoteState.level;\n localState.mute = remoteState.level === 0;\n this.trigger('volumechange', Event.void);\n }\n }\n\n private handlePlayingMessage(localState: ViviCastSessionState): void {\n if (localState.playing !== true) {\n localState.playing = true;\n localState.playbackFinished = false;\n this.trigger('playingchange', Event.void);\n }\n }\n\n private handlePausedMessage(localState: ViviCastSessionState): void {\n if (localState.playing !== false) {\n localState.playing = false;\n this.trigger('playingchange', Event.void);\n }\n }\n\n private handleFinishedMessage(localState: ViviCastSessionState): void {\n if (localState.playbackFinished !== true) {\n localState.playing = false;\n localState.playbackFinished = true;\n this.trigger('playingchange', Event.void);\n }\n }\n\n private handleNewChapterMessage(localState: ViviCastSessionState, remoteState: ViviIncomingMessageParams): void {\n const remoteUrls = remoteState.queue ?? [];\n const remoteChapter = remoteUrls.find(x => x.url === localState.videoSource);\n\n if (!remoteChapter) {\n console.info(`The device is no longer playing the source we loaded - disposing the session`);\n this.dispose();\n return;\n }\n\n if (localState.subtitleSource !== remoteChapter.suburl) {\n localState.subtitleSource = remoteChapter.suburl;\n this.trigger('subtitleschange', Event.void);\n }\n }\n\n private handleStoppedMessage(): void {\n this.dispose();\n }\n\n public async loadSource(videoSource: string, subtitleSource?: string): Promise<void> {\n if (this.localState.videoSource === videoSource && this.localState.subtitleSource === subtitleSource)\n return;\n\n try {\n // Prepare some handy variables\n const roomId = this.getDevice().id;\n const currentPosition = this.getPosition();\n \n // Set the sources\n this.localState.videoSource = videoSource;\n this.localState.subtitleSource = subtitleSource;\n\n // Mark the session as not ready while we're loading a source\n this.localState.ready = false;\n\n // We need to be connected to the room before we can load a source\n await this.client.joinRoom(roomId);\n\n // Load the source\n await this.client.loadQueue({\n title: this.getTitle(),\n roomId,\n videoSource,\n subtitleSource\n });\n\n // Mark the session as ready\n this.localState.ready = true;\n\n // Notify listeners that the source has changed\n this.trigger('sourceloaded', Event.void);\n\n // Seek to where we were before changing sources\n if (currentPosition > 0)\n this.seek(currentPosition);\n\n // We need to explicity set subtitles if we have a subtitle source\n if (subtitleSource)\n this.setSubtitles(subtitleSource);\n } catch (error) {\n console.error(error);\n\n this.trigger('error', new Error('Could not load video on Vivi device'));\n }\n }\n\n public play(): void {\n if (!this.localState.ready)\n return;\n\n if (this.localState.playing !== true) {\n this.localState.playing = true;\n this.client.play(this.getDevice().id);\n this.trigger('playingchange', Event.void);\n }\n }\n\n public pause(): void {\n if (!this.localState.ready)\n return;\n\n if (this.localState.playing !== false) {\n this.localState.playing = false;\n this.client.pause(this.getDevice().id);\n this.trigger('playingchange', Event.void);\n }\n }\n\n public seek(position: number): void {\n if (!this.localState.ready)\n return;\n\n if (this.localState.position !== position) {\n this.localState.position = position;\n this.client.seek(this.getDevice().id, position);\n this.trigger('positionchange', Event.void);\n }\n }\n\n public setVolume(volume: number): void {\n if (!this.localState.ready)\n return;\n\n if (this.localState.volume !== volume) {\n this.localState.volume = volume;\n this.client.setVolume(this.getDevice().id, volume);\n this.trigger('volumechange', Event.void);\n }\n }\n\n public setMuted(muted: boolean): void {\n if (!this.localState.ready)\n return;\n\n if (this.localState.mute !== muted) {\n this.localState.mute = muted;\n this.client.setMuted(this.getDevice().id, muted);\n this.trigger('volumechange', Event.void);\n }\n }\n\n public async setSubtitles(subtitleSource?: string): Promise<void> {\n if (!this.localState.ready)\n return;\n\n if (subtitleSource)\n await this.loadSource(this.localState.videoSource, subtitleSource);\n \n const showSubtitles = !!subtitleSource;\n\n if (this.localState.subtitles !== showSubtitles) {\n this.localState.subtitles = showSubtitles;\n this.client.setSubtitles(this.getDevice().id, showSubtitles);\n this.trigger('subtitleschange', Event.void);\n }\n }\n\n public isPlaying(): boolean {\n return this.localState.playing;\n }\n\n public isPlaybackFinished(): boolean {\n return this.localState.playbackFinished;\n }\n\n public getPosition(): number {\n return this.localState.position;\n }\n\n public getDuration(): number | undefined {\n return this.localState.duration;\n }\n\n public getVolume(): number {\n return this.localState.volume;\n }\n\n public getMuted(): boolean {\n return this.localState.mute;\n }\n\n public getSubtitles(): string | undefined {\n if (this.localState.subtitles)\n return this.localState.subtitleSource;\n }\n\n public getDevice(): Device {\n return this.localState.device;\n }\n\n public getTitle(): string {\n return this.localState.title;\n }\n}\n","import { CastSession, Client, Device, DeviceStatus, DeviceType, SessionConfig } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\nimport { Event, EventBus } from 'projects/player/plugins/devices-plugin/utils/event-bus';\nimport { ResilientWebSocket } from 'projects/player/plugins/devices-plugin/utils/resilient-web-socket';\nimport { Scheduler } from 'projects/player/plugins/devices-plugin/utils/scheduler';\nimport { debounce } from 'projects/player/utils/fn';\nimport { IdHelper } from 'projects/player/utils/id-helper';\n\nimport { ViviCastSession } from './vivi-cast-session';\nimport { ViviClientEventMap, ViviIncomingMessage, ViviLoadQueueRequest, ViviOutgoingMessage, ViviRoom } from './vivi-interfaces';\n\nconst MESSAGE_TIMEOUT_IN_MILLISECONDS = 10000;\nconst MESSAGE_DEBOUNCE_IN_MILLISECONDS = 500;\nconst DEVICE_DISCOVERY_SCHEDULE_IN_MILLISECONDS = 10000;\n\ninterface ViviClientOptions {\n url: string;\n fetchAccessToken: () => Promise<string>;\n}\n\nexport class ViviClient extends EventBus<ViviClientEventMap> implements Client<ViviClientEventMap> {\n private options: ViviClientOptions;\n private webSocket?: ResilientWebSocket;\n private accessToken: string;\n private devices: Device[];\n private devicesFingerprint: string;\n private deviceDiscovery: Scheduler;\n\n private sendMessageDebounced: (msg: ViviOutgoingMessage) => boolean;\n\n constructor(options: ViviClientOptions) {\n super();\n \n this.options = options;\n this.accessToken = '';\n this.devices = [];\n this.devicesFingerprint = '';\n this.deviceDiscovery = new Scheduler();\n\n this.bindFunctions();\n this.initialize();\n }\n\n private bindFunctions(): void {\n this.initialize = this.initialize.bind(this);\n this.sendMessage = this.sendMessage.bind(this);\n this.sendMessageDebounced = debounce(this.sendMessage, MESSAGE_DEBOUNCE_IN_MILLISECONDS, true);\n this.beginDeviceDiscovery = this.beginDeviceDiscovery.bind(this);\n this.dispose = this.dispose.bind(this);\n this.canCastToDevice = this.canCastToDevice.bind(this);\n this.getDevices = this.getDevices.bind(this);\n this.startCastSession = this.startCastSession.bind(this);\n this.authenticateWithVivi = this.authenticateWithVivi.bind(this);\n this.getRoomList = this.getRoomList.bind(this);\n this.joinRoom = this.joinRoom.bind(this);\n this.query = this.query.bind(this);\n this.loadQueue = this.loadQueue.bind(this);\n this.play = this.play.bind(this);\n this.pause = this.pause.bind(this);\n this.stop = this.stop.bind(this);\n this.seek = this.seek.bind(this);\n this.setVolume = this.setVolume.bind(this);\n this.setMuted = this.setMuted.bind(this);\n this.setSubtitles = this.setSubtitles.bind(this);\n }\n\n private initialize(): void {\n this.webSocket = new ResilientWebSocket(this.options.url);\n\n this.webSocket.onMessage = (event: MessageEvent) => this.trigger('message', JSON.parse(event.data));\n\n this.webSocket.onOpen = async () => {\n try {\n this.accessToken = await this.options.fetchAccessToken();\n \n await this.authenticateWithVivi();\n \n this.beginDeviceDiscovery();\n\n this.trigger('connected', Event.void);\n } catch (err) {\n console.error(err);\n \n this.trigger('error', new Error('Could not connect to Vivi'));\n }\n };\n }\n\n private sendMessage(msg: ViviOutgoingMessage): void {\n this.webSocket?.send(JSON.stringify(msg));\n }\n\n private beginDeviceDiscovery(): void {\n this.deviceDiscovery\n .every(DEVICE_DISCOVERY_SCHEDULE_IN_MILLISECONDS)\n .schedule(async () => {\n try {\n const rooms = await this.getRoomList();\n const roomsFingerprint = ViviClient.calculateFingerprint(rooms);\n\n // If the rooms haven't changed, don't bother updating the devices\n if (roomsFingerprint === this.devicesFingerprint)\n return;\n\n const numberOfUniqueOrganisations = new Set(rooms.map(r => r.organisation ?? '')).size;\n const numberOfUniqueLocations = new Set(rooms.map(r => r.location ?? '')).size;\n\n this.devices = rooms.map(r => ({\n id: r.id,\n name: r.name,\n schoolName: numberOfUniqueOrganisations > 1 ? r.organisation : '',\n description: numberOfUniqueLocations > 1 ? r.location : '',\n type: DeviceType.Vivi,\n status: DeviceStatus.Available\n }));\n\n this.devicesFingerprint = roomsFingerprint;\n\n this.trigger('deviceschange', Event.void);\n } catch (error) {\n // This could be a transient error, so we don't want to trigger the 'error' event\n // as that would cause the player to stop playback for an error that it could recover from..\n console.warn(error);\n }\n })\n .trigger()\n .start();\n }\n\n public dispose(): void {\n // Stop the device discovery\n this.deviceDiscovery.stop();\n\n // Dispose websocket\n this.webSocket?.dipose();\n\n // Dispose event bus\n super.dispose();\n }\n\n public canCastToDevice(deviceType: DeviceType): boolean {\n if (deviceType === DeviceType.Vivi)\n return true;\n\n return false;\n }\n\n public getDevices(): Device[] {\n return this.devices;\n }\n\n public startCastSession(config: SessionConfig): CastSession {\n return new ViviCastSession(this, config);\n }\n\n public async authenticateWithVivi(): Promise<void> {\n this.sendMessage({\n destination: 'relay',\n message: {\n token: this.accessToken,\n type: 'identify_video_api'\n }\n });\n\n await this\n .one('message', msg => msg.message.type === 'video_api_identified')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to authenticate with Vivi'); });\n }\n\n public async getRoomList(): Promise<ViviRoom[]> {\n this.sendMessage({\n destination: 'relay',\n message: {\n type: 'video_api_rooms'\n }\n });\n\n const response = await this\n .one('message', msg => msg.message.type === 'video_api_rooms')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to fetch rooms'); });\n\n return response.message.rooms || [];\n }\n\n public async joinRoom(roomId: string): Promise<void> {\n this.sendMessage({\n destination: 'relay',\n message: {\n destination_type: 'box',\n new_destination: roomId,\n token: this.accessToken,\n type: 'connect'\n }\n });\n\n await this\n .one('message', msg => {\n if (msg.source === roomId && msg.message.type === 'connect') return true;\n if (msg.message.type === 'error' && msg.message.error_type === 'already_connected') return true;\n })\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to join room'); });\n }\n\n public async query(roomId: string): Promise<ViviIncomingMessage> {\n const ackId = ViviClient.createAckId();\n\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message_with_ack',\n ack_id: ackId,\n name: 'query'\n }\n });\n\n return await this\n .one('message', msg => msg.message.ack_id === ackId)\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to fetch query'); });\n }\n\n public async loadQueue({ roomId, title, videoSource, subtitleSource }: ViviLoadQueueRequest): Promise<void> {\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message_with_ack',\n ack_id: ViviClient.createAckId(),\n name: 'queue_load',\n payload: {\n urls: [{\n title,\n url: videoSource,\n suburl: subtitleSource\n }]\n }\n }\n });\n\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'ready')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to load media'); });\n }\n\n public async play(roomId: string): Promise<void> {\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message',\n name: 'video_play',\n payload: {}\n }\n });\n\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'playing')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to play video'); });\n }\n\n public async pause(roomId: string): Promise<void> {\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message',\n name: 'video_pause'\n }\n });\n\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'paused')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to pause video'); });\n }\n\n public async stop(roomId: string): Promise<void> {\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message',\n name: 'video_stop'\n }\n });\n\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'stopped')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to stop video'); });\n }\n\n public async seek(roomId: string, position: number): Promise<void> {\n const sent = this.sendMessageDebounced({\n destination: roomId,\n message: {\n type: 'message',\n name: 'video_seek',\n payload: {\n position\n }\n }\n });\n\n if (sent) {\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'playing')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to seek video'); });\n }\n }\n\n public async setVolume(roomId: string, volume: number): Promise<void> {\n const sent = this.sendMessageDebounced({\n destination: roomId,\n message: {\n type: 'message',\n name: 'set_volume',\n payload: {\n volume\n }\n }\n });\n\n if (sent) {\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'volume')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to set volume'); });\n }\n }\n\n public async setMuted(roomId: string, muted: boolean): Promise<void> {\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message',\n name: 'set_mute',\n payload: {\n mute: muted\n }\n }\n });\n\n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'mute')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to set mute'); });\n }\n\n public async setSubtitles(roomId: string, showSubtitles: boolean): Promise<void> {\n const ackId = ViviClient.createAckId();\n\n this.sendMessage({\n destination: roomId,\n message: {\n type: 'message_with_ack',\n ack_id: ackId,\n name: 'set_subtitles',\n payload: {\n subtitles: showSubtitles\n }\n }\n });\n \n await this\n .one('message', msg => msg.source === roomId && msg.message.payload?.event === 'subtitles')\n .timeout(MESSAGE_TIMEOUT_IN_MILLISECONDS)\n .catch(() => { throw new Error('Failed to set subtitles'); });\n }\n\n private static createAckId(): string {\n return IdHelper.generateRandomId();\n }\n\n private static calculateFingerprint(devicesOrRooms: { id: string }[]): string {\n return devicesOrRooms.map(dr => dr.id).sort().join(',');\n }\n}\n","import { CastSession, Client, Device, SessionConfig } from './clients/client-interfaces';\nimport { BaseEvents, EventBus } from './utils/event-bus';\n\ninterface DevicesSessionManagerEventMap extends BaseEvents {\n deviceschange: Device[];\n castsessionchange: CastSession | undefined;\n error: Error;\n}\n\nexport class DevicesSessionManager extends EventBus<DevicesSessionManagerEventMap> {\n private instanceId: string;\n private clients: Client[];\n private castSession?: CastSession;\n\n private constructor(instanceId: string) {\n super();\n\n this.instanceId = instanceId;\n this.clients = [];\n \n this.bindFunctions();\n }\n\n private bindFunctions(): void {\n this.addClient = this.addClient.bind(this);\n this.hasInstanceOfClient = this.hasInstanceOfClient.bind(this);\n this.startCastSession = this.startCastSession.bind(this);\n this.gatherAndPublishDevices = this.gatherAndPublishDevices.bind(this);\n this.dispose = this.dispose.bind(this);\n }\n\n public addClient(client: Client): void {\n client.on('deviceschange', this.gatherAndPublishDevices);\n client.on('error', err => this.trigger('error', err));\n \n this.clients.push(client);\n }\n\n public hasInstanceOfClient(clientType: any): boolean {\n return this.clients.some(c => c instanceof clientType);\n }\n \n public startCastSession(config: SessionConfig): void {\n // If a session with the selected device is already in progress, we need to dispose it\n if (this.castSession) {\n if (this.castSession.getDevice().id !== config.device.id)\n this.castSession.dispose();\n else {\n console.info(`A session with device ${config.device.id} already exists - this is a no-op`);\n return;\n }\n }\n\n // Find a client that can cast to the selected device\n const client = this.clients.find(c => c.canCastToDevice(config.device.type));\n\n // Create a new session and notify listeners\n if (client) {\n this.castSession = client.startCastSession(config);\n\n this.castSession.on('error', err => {\n this.castSession.dispose();\n this.trigger('error', err);\n });\n\n this.castSession.on('dispose', () => {\n this.castSession = undefined;\n this.trigger('castsessionchange', undefined);\n });\n \n this.trigger('castsessionchange', this.castSession);\n }\n }\n\n public getCastSession(): CastSession | undefined {\n return this.castSession;\n }\n\n private gatherAndPublishDevices(): void {\n const results = this.clients.map(c => c.getDevices());\n const devices = results.reduce((agg, val) => [ ...agg, ...val ], []);\n\n this.trigger('deviceschange', devices);\n }\n\n public dispose(): void {\n this.castSession?.dispose();\n this.clients.forEach(c => c.dispose());\n \n this.castSession = undefined;\n this.clients = [];\n\n super.dispose();\n }\n\n private static instances: {[key: string]: DevicesSessionManager } = {};\n\n public static getOrCreateInstance(instanceId: string): DevicesSessionManager {\n if (!instanceId)\n throw new Error('instanceId is required');\n\n if (!this.instances[instanceId])\n this.instances[instanceId] = new DevicesSessionManager(instanceId);\n \n return this.instances[instanceId];\n }\n\n public static disposeAndRemoveInstance(sessionManager: DevicesSessionManager): void {\n sessionManager.dispose();\n delete this.instances[sessionManager.instanceId];\n }\n\n public static isActive(): boolean {\n return Object.keys(this.instances).length > 0;\n }\n}\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { DeviceType } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\n\nimport './device-menu-item.scss';\n\ninterface DeviceMenuItemOptions extends videojs.MenuItemOptions {\n available: boolean;\n type: DeviceType;\n id: string;\n schoolName?: string;\n description?: string;\n onClick: () => void;\n}\n\nconst MenuItem = videojs.getComponent('MenuItem');\n\nexport class DeviceMenuItem extends MenuItem {\n public options_: DeviceMenuItemOptions;\n\n constructor(player: VideoJsPlayer, options?: DeviceMenuItemOptions) {\n super(player, options);\n\n this.isVisible = this.isVisible.bind(this);\n }\n\n public createEl(): HTMLLIElement {\n const iconClassNames: Record<DeviceType, string> = {\n 'vivi': 'cv-vivi-icon',\n 'apple-tv': 'cv-apple-icon'\n };\n\n const container = super.createEl('li', {\n className: 'vjs-menu-item cv-device-menu-item'\n });\n\n const el = videojs.dom.createEl('div', {\n className: 'cv-device-menu-item-body',\n innerHTML: `\n <span class=\"cv-device-icon ${iconClassNames[this.options_.type]}\"></span>\n <div>\n <span class=\"vjs-menu-item-text\">${this.options_.label}</span>\n <span class=\"vjs-menu-item-text cv-device-truncated-text\">${this.options_.schoolName ?? ''}</span>\n <span class=\"vjs-menu-item-text cv-device-truncated-text cv-device-description\">${this.options_.description ?? ''}</span>\n </div>\n `\n });\n\n container.replaceChildren(el);\n\n return container;\n }\n\n public handleClick(): void {\n this.options_.onClick();\n }\n\n public show(): void {\n super.show();\n }\n\n public hide(): void {\n super.hide();\n }\n\n public isVisible(): boolean {\n return !super.hasClass('vjs-hidden');\n }\n}\n","import SimpleBar from 'simplebar';\nimport videojs from 'video.js';\n\nimport { baseMenuCreateEl } from 'projects/player/components/menu/menu';\n\nimport './devices-menu.scss';\n\nconst Menu = videojs.getComponent('Menu');\n\nexport class DevicesMenu extends Menu {\n private contentWrapper: HTMLDivElement;\n private ctaElement: HTMLDivElement;\n private simpleBar: SimpleBar;\n\n public createEl(): HTMLDivElement {\n const el = baseMenuCreateEl.apply(this);\n const content = (this as any).contentEl_;\n\n this.contentWrapper = videojs.dom.createEl('div', {\n className: 'vjs-menu-content'\n }) as HTMLDivElement;\n \n el.className = 'vjs-menu cv-devices-menu';\n content.className = 'cv-devices-menu-item-list';\n\n el.removeChild(content);\n el.appendChild(this.contentWrapper);\n\n this.contentWrapper.appendChild(content);\n this.simpleBar = new SimpleBar(content as HTMLElement, { autoHide: false });\n\n return el;\n }\n\n public addCta(component: videojs.Component): void {\n if (this.ctaElement) {\n console.warn('CTA has already been added to the menu - this is a no-op');\n return;\n }\n\n this.ctaElement = component.el() as HTMLDivElement;\n this.contentWrapper.prepend(this.ctaElement);\n this.el().classList.add('has-cta');\n }\n\n public removeCta(): void {\n if (this.ctaElement) {\n this.contentWrapper.removeChild(this.ctaElement);\n this.el().classList.remove('has-cta');\n }\n }\n}\n\nvideojs.registerComponent('DevicesMenu', DevicesMenu);\n","import * as React from 'react';\nimport videojs, { VideoJsPlayer } from 'video.js';\n\nimport { CtaContext } from 'libs/shared/interfaces';\n\nimport { DeviceType } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\nimport { getReactComponent } from 'projects/player/react/react-component';\n\nimport './devices-cta.scss';\n\ninterface DevicesCtaProps {\n onDismiss: (context: CtaContext) => void;\n onInstall: (context: CtaContext) => void;\n onLearnMore: (context: CtaContext) => void;\n onContactSupport: (context: CtaContext) => void;\n inactiveIntegrations: DeviceType[];\n canUserManageIntegrations: boolean;\n player: VideoJsPlayer;\n}\n\nfunction DevicesCta({\n inactiveIntegrations,\n canUserManageIntegrations,\n player,\n onDismiss,\n onInstall,\n onLearnMore,\n onContactSupport\n}: DevicesCtaProps): JSX.Element {\n if (inactiveIntegrations.length === 0) return <></>;\n\n const localize = (text: string) => player.localize(text);\n\n const isInactive = (val: DeviceType) =>\n inactiveIntegrations.indexOf(val) !== -1;\n\n let context: CtaContext;\n \n if (isInactive(DeviceType.AppleTv) && isInactive(DeviceType.Vivi))\n context = 'vivi_and_apple_tv';\n else if (isInactive(DeviceType.Vivi))\n context = 'vivi';\n else\n context = 'apple_tv';\n\n return (\n <div className='cv-devices-cta' tabIndex={-1}>\n <Header context={context} localize={localize} onDismiss={() => onDismiss(context)} />\n <Body context={context} />\n <Footer\n context={context}\n canUserManageIntegrations={canUserManageIntegrations}\n localize={localize}\n onContactSupport={() => onContactSupport(context)}\n onInstall={() => onInstall(context)}\n onLearnMore={() => onLearnMore(context)}\n />\n </div>\n );\n}\n\ninterface HeaderProps {\n context: CtaContext;\n localize: (text: string) => string;\n onDismiss: () => void;\n}\n\nfunction Header({ context, localize, onDismiss }: HeaderProps): JSX.Element {\n return (\n <div className='cv-devices-cta-header'>\n <span className='cv-devices-badge'>{localize('New')}</span>\n <span className='cv-devices-title'>\n {context === 'vivi_and_apple_tv' && localize('Cast to Vivi and Apple TV')}\n {context === 'vivi' && localize('Cast to Vivi')}\n {context === 'apple_tv' && localize('Cast to Apple TV')}\n </span>\n <span className='cv-devices-close' onClick={onDismiss}>\n <svg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>\n <path fillRule='evenodd' clipRule='evenodd' fill='white' d='M11.9588 10.6413L16.3612 6.34478C16.7361 5.97191 17.3439 5.97191 17.7188 6.34478C18.0937 6.71764 18.0937 7.32218 17.7188 7.69505L13.3165 11.9916L17.7188 16.3701C18.0937 16.7429 18.0937 17.3475 17.7188 17.7203C17.3439 18.0932 16.7361 18.0932 16.3612 17.7203L11.9588 13.3419L7.63882 17.7203C7.26392 18.0932 6.65608 18.0932 6.28118 17.7203C5.90627 17.3475 5.90627 16.7429 6.28118 16.3701L10.6012 11.9916L6.28118 7.62993C5.90627 7.25706 5.90627 6.65252 6.28118 6.27965C6.65608 5.90678 7.26392 5.90678 7.63882 6.27965L11.9588 10.6413Z' />\n </svg>\n </span>\n </div>\n );\n}\n\ninterface BodyProps {\n context: CtaContext;\n}\n\nfunction Body({ context }: BodyProps): JSX.Element {\n const bgClassName = context === 'vivi_and_apple_tv' ? 'bg-vivi-and-apple' : context === 'vivi' ? 'bg-vivi' : 'bg-apple';\n\n return (\n <div className={`cv-devices-cta-body ${bgClassName}`}>\n {(context === 'vivi_and_apple_tv' || context === 'apple_tv') && <div className='cv-devices-icon-container'><span className='cv-devices-icon apple'></span></div>}\n {(context === 'vivi_and_apple_tv' || context === 'vivi') && <div className='cv-devices-icon-container'><span className='cv-devices-icon vivi'></span></div>}\n </div>\n );\n}\n\ninterface FooterProps {\n context: CtaContext;\n canUserManageIntegrations: boolean;\n localize: (text: string) => string;\n onInstall: () => void;\n onLearnMore: () => void;\n onContactSupport: () => void;\n}\n\nfunction Footer({\n context,\n canUserManageIntegrations,\n localize,\n onInstall,\n onLearnMore,\n onContactSupport\n}: FooterProps): JSX.Element {\n if (canUserManageIntegrations) {\n return (\n <div className='cv-devices-cta-footer'>\n <span>\n {context === 'vivi_and_apple_tv' && localize('Discover our new device integrations to make presenting in the classroom easy!')}\n {context === 'vivi' && localize('Discover our new Vivi integration.')}\n {context === 'apple_tv' && localize('Discover our new Apple TV integration.')}\n </span>\n <br />\n <span className='cv-devices-link' onClick={onInstall}>{localize('Click here to install')}</span>\n </div>\n );\n }\n\n return (\n <div className='cv-devices-cta-footer'>\n <span>\n {context === 'vivi_and_apple_tv' && localize('Cast to Vivi and Apple TV is now available! Please contact ')}\n {context === 'vivi' && localize('Cast to Vivi is now available! Please contact ')}\n {context === 'apple_tv' && localize('Cast to Apple TV is now available! Please contact ')}\n </span>\n <span className='cv-devices-link' onClick={onContactSupport}>ClickView Support</span>\n <span>\n {context === 'vivi_and_apple_tv' && localize(' or your administrator to set up Apple TV and Vivi.')}\n {context === 'vivi' && localize(' or your administrator to set up Vivi.')}\n {context === 'apple_tv' && localize(' or your administrator to set up Apple TV.')}\n </span>\n <br />\n <span className='cv-devices-link' onClick={onLearnMore}>Learn more</span>\n </div>\n );\n}\n\nvideojs.registerComponent(\n 'DevicesCta',\n getReactComponent(\n (player: VideoJsPlayer, options: DevicesCtaProps) => <DevicesCta player={player} {...options} />,\n { properties: { className: 'cv-devices-cta-wrapper' } }\n )\n);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { CtaContext } from 'libs/shared/interfaces';\n\nimport { CollapsibleHeadingMenuItem } from 'projects/player/components/cog-button/collapsible-heading-menu-item';\nimport { NoMatchingResultsMenuItem, SearchInputMenuItem } from 'projects/player/components/search-input-menu-item/search-input-menu-item';\nimport { CollapsibleComponent } from 'projects/player/interfaces/CollapsibleComponent';\nimport { CastSession, Device, DeviceStatus, DeviceType } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\n\nimport { DeviceMenuItem } from '../device-menu-item/device-menu-item';\nimport { DevicesMenu } from '../devices-menu/devices-menu';\n\nimport './devices-button.scss';\n\nimport 'projects/player/plugins/devices-plugin/components/devices-cta/devices-cta';\n\nconst DEVICE_COUNT_THRESHOLD_FOR_SEARCH = 20;\n\nconst DevicesCta = videojs.getComponent('DevicesCta');\nconst MenuButton = videojs.getComponent('MenuButton');\n\nexport interface DevicesButtonOptions extends videojs.MenuButtonOptions {\n onClick: () => void;\n onDeviceMenuItemClick: (item: DeviceMenuItem, device: Device) => void;\n ctaOptions: {\n hasBeenDismissed: boolean,\n canUserManageIntegrations: boolean,\n inactiveIntegrations: DeviceType[],\n onDismiss: (context: CtaContext) => void,\n onInstall: (context: CtaContext) => void,\n onLearnMore: (context: CtaContext) => void,\n onContactSupport: (context: CtaContext) => void\n };\n}\n\nexport class DevicesButton extends MenuButton implements CollapsibleComponent {\n private searchText: string;\n private devices: Device[];\n private castSession?: CastSession;\n private headingItem?: CollapsibleHeadingMenuItem;\n private searchInputItem?: SearchInputMenuItem;\n private emptyPlaceholder?: NoMatchingResultsMenuItem;\n private cta?: videojs.Component;\n \n public options_: DevicesButtonOptions;\n public controlText_: string;\n\n constructor(player: VideoJsPlayer, options?: DevicesButtonOptions) {\n super(player, options);\n\n this.searchText = '';\n this.devices = [];\n this.castSession = undefined;\n\n this.bindFunctions();\n this.bindEventListeners();\n }\n\n private bindFunctions(): void {\n this.bindEventListeners = this.bindEventListeners.bind(this);\n this.setDevices = this.setDevices.bind(this);\n this.setCastSession = this.setCastSession.bind(this);\n this.setSearchText = this.setSearchText.bind(this);\n this.getDeviceMenuItems = this.getDeviceMenuItems.bind(this);\n this.showNotificationBadge = this.showNotificationBadge.bind(this);\n this.hideNotificationBadge = this.hideNotificationBadge.bind(this);\n this.render = this.render.bind(this);\n this.removeMenuItems = this.removeMenuItems.bind(this);\n this.addMenuItemsForDevices = this.addMenuItemsForDevices.bind(this);\n this.shouldShowSearchInput = this.shouldShowSearchInput.bind(this);\n this.toggleSearchInput = this.toggleSearchInput.bind(this);\n this.toggleDeviceMenuItems = this.toggleDeviceMenuItems.bind(this);\n this.toggleEmptyStatePlaceholder = this.toggleEmptyStatePlaceholder.bind(this);\n }\n\n private bindEventListeners(): void {\n const el = this.$('button');\n\n const onBlur = (e: videojs.EventTarget.Event) => {\n (this.menu as any).handleBlur(e);\n };\n\n el.addEventListener('blur', onBlur);\n\n this.one('dispose', () => {\n el.removeEventListener('blur', onBlur);\n this.cta?.dispose();\n });\n }\n\n public createEl(...args: any[]): Element {\n return MenuButton.prototype.createEl.apply(this, ...args);\n }\n\n public buildWrapperCSSClass() {\n return `cv-menu-small cv-devices-button ${super.buildWrapperCSSClass()}`;\n }\n\n public createMenu(): videojs.Menu {\n const menu = new DevicesMenu(this.player_, {\n menuButton: this\n });\n\n if (!this.options_.ctaOptions.hasBeenDismissed && this.options_.ctaOptions.inactiveIntegrations.length > 0) {\n const { onDismiss, ...rest } = this.options_.ctaOptions;\n\n this.cta = new DevicesCta(this.player(), {\n ...rest,\n onDismiss: (context: CtaContext) => {\n this.hideNotificationBadge();\n menu.removeCta();\n onDismiss(context);\n }\n } as any);\n \n this.showNotificationBadge();\n menu.addCta(this.cta);\n }\n\n const children = this.createItems();\n\n children.forEach(x => menu.addItem(x));\n\n return menu;\n }\n\n public createItems(): videojs.MenuItem[] {\n const items: videojs.MenuItem[] = [];\n\n this.headingItem = new CollapsibleHeadingMenuItem(this.player_, {\n label: this.localize('Select a device'),\n selectable: false\n });\n\n this.searchInputItem = new SearchInputMenuItem(this.player_, {\n menuButton: this,\n search: searchText => this.setSearchText(searchText),\n className: 'cv-devices-search-input'\n });\n\n this.emptyPlaceholder = new NoMatchingResultsMenuItem(this.player_, {\n label: 'No devices found',\n selected: false,\n selectable: false,\n multiSelectable: false\n });\n\n this.headingItem.show();\n this.searchInputItem.hide();\n this.emptyPlaceholder.show();\n\n items.push(\n this.headingItem,\n this.searchInputItem,\n this.emptyPlaceholder\n );\n\n return items;\n }\n\n public pressButton(): void {\n super.pressButton();\n\n if (this.shouldShowSearchInput())\n this.searchInputItem?.focus();\n }\n\n public setDevices(devices: Device[]): void {\n this.devices = devices;\n this.render();\n }\n\n public setCastSession(castSession?: CastSession): void {\n this.castSession = castSession;\n this.render();\n }\n\n public setSearchText(searchText: string): void {\n this.searchText = searchText;\n this.render();\n }\n\n public getDeviceMenuItems(): DeviceMenuItem[] {\n return this.menu.children_.filter(x => x instanceof DeviceMenuItem) as DeviceMenuItem[];\n }\n\n public showNotificationBadge(): void {\n this.addClass('notification-badge');\n }\n\n public hideNotificationBadge(): void {\n this.removeClass('notification-badge');\n }\n\n private render(): void {\n // Update the UI\n this.removeMenuItems(this.getDeviceMenuItems());\n this.addMenuItemsForDevices(this.devices);\n this.toggleSearchInput();\n this.toggleDeviceMenuItems();\n this.toggleEmptyStatePlaceholder();\n }\n\n private removeMenuItems(items: videojs.MenuItem[]): void {\n items.forEach(x => {\n this.menu.removeChild(x);\n x.dispose();\n });\n }\n\n private addMenuItemsForDevices(devices: Device[]): void {\n // Sort devices by type, description and name\n const sortedDevices = devices.sort((a, b) => {\n const qualifiedNameDeviceA = `${a.type}${a.schoolName ?? ''}${a.description ?? ''}${a.name}`;\n const qualifiedNameDeviceB = `${b.type}${b.schoolName ?? ''}${b.description ?? ''}${b.name}`;\n return qualifiedNameDeviceA.localeCompare(qualifiedNameDeviceB);\n });\n\n sortedDevices.forEach(x => {\n const newItem = new DeviceMenuItem(this.player(), {\n id: x.id,\n label: x.name,\n schoolName: x.schoolName,\n description: x.description,\n selected: false,\n multiSelectable: false,\n selectable: true,\n available: x.status === DeviceStatus.Available,\n type: x.type,\n onClick: () => {\n this.options_.onDeviceMenuItemClick(newItem, x);\n }\n });\n\n this.menu.addItem(newItem);\n });\n }\n\n private shouldShowSearchInput(): boolean {\n const deviceMenuItems = this.getDeviceMenuItems();\n const showSearchInput = deviceMenuItems.length >= DEVICE_COUNT_THRESHOLD_FOR_SEARCH;\n\n return showSearchInput;\n }\n\n private toggleSearchInput(): void {\n if (this.shouldShowSearchInput()) {\n this.searchInputItem.show();\n this.menu.addClass('vertical-fill');\n } else {\n this.searchInputItem.hide();\n this.menu.removeClass('vertical-fill');\n }\n }\n\n private toggleDeviceMenuItems(): void {\n const deviceMenuItems = this.getDeviceMenuItems();\n const isSearchEnabled = this.shouldShowSearchInput();\n const searchTextLowerCase = this.searchText.toLowerCase();\n \n // Update the UI of each device menu item\n deviceMenuItems.forEach(x => {\n const device = this.devices.find(y => y.id === x.options_.id);\n\n if (!device)\n return;\n\n const isAvailable = device.status === DeviceStatus.Available;\n const isInSession = device.id === this.castSession?.getDevice().id;\n const isMatchingSearch = isSearchEnabled ?\n `${device.name} ${device.schoolName ?? ''} ${device.description ?? ''}`.trim().toLowerCase().indexOf(searchTextLowerCase) !== -1 :\n true;\n \n isAvailable ? x.enable() : x.disable();\n isMatchingSearch ? x.show() : x.hide();\n isInSession ? x.selected(true) : x.selected(false);\n });\n }\n\n private toggleEmptyStatePlaceholder(): void {\n const allDeviceMenuItems = this.getDeviceMenuItems();\n const visibleDeviceMenuItems = allDeviceMenuItems.filter(x => x.isVisible());\n\n visibleDeviceMenuItems.length ?\n this.emptyPlaceholder.hide() :\n this.emptyPlaceholder.show();\n \n allDeviceMenuItems.length ?\n this.emptyPlaceholder.setLabel(this.localize('No matching results')) :\n this.emptyPlaceholder.setLabel(this.localize('No devices found'));\n }\n\n /**\n * CollapsibileComponent interface implementation\n * from here onward\n */\n public alwaysCollapsed: boolean = false;\n public isCollapsed: boolean = false;\n public isCollabsible: boolean = true;\n public className: string = 'cv-devices-menu-button';\n\n public getCollabsibleName(): string {\n return this.controlText_;\n }\n\n public getCollabsibleValue(): string {\n return this.castSession?.getDevice().name ?? ' ';\n }\n\n public showInCollabsibleMenu(): boolean {\n return true;\n }\n\n public showCollapsibleMenu(): void {\n this.handleClick();\n }\n\n public handleClick(): void {\n super.handleClick(null);\n this.options_.onClick();\n }\n}\n\nDevicesButton.prototype.controlText_ = 'Devices';\n\nvideojs.registerComponent('DevicesButton', DevicesButton);\n","import videojs from 'video.js';\n\nimport { Device, DeviceType } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\n\nimport './devices-tech-ui.scss';\n\nconst Component = videojs.getComponent('Component');\n\ninterface DevicesTechUIOptions extends videojs.ComponentOptions {\n onStopCasting: () => void;\n}\n\nexport class DevicesTechUI extends Component {\n private poster: string;\n private device?: Device;\n \n public options_: DevicesTechUIOptions;\n\n constructor(options: DevicesTechUIOptions) {\n super(null, options);\n }\n\n public createEl(): Element {\n return super.createEl('div', {\n className: 'cv-devices-tech'\n });\n }\n\n public setPoster(poster: string): void {\n this.poster = poster;\n this.update();\n }\n\n public setDevice(device: Device): void {\n this.device = device;\n this.update();\n }\n\n /**\n * Unfortunately we can't use the traditional way\n * of building out components and click handlers\n * because this component is ultimately detached\n * from the player so much of it's functionality won't work\n */\n public update(): void {\n const iconClassNames: Record<DeviceType, string> = {\n 'vivi': 'cv-vivi-icon',\n 'apple-tv': 'cv-apple-icon'\n };\n\n (this as any).el_.innerHTML = `\n <div class=\"cv-devices-content\">\n <p>${this.localize('Currently playing on')}</p>\n <h2><span class=\"cv-device-icon ${iconClassNames[this.device?.type ?? DeviceType.Vivi]}\"></span>${this.device?.name ?? ''}</h2>\n </div>\n <div class=\"cv-devices-background\" style=\"background-image: url(${this.poster})\"></div>\n `;\n\n const button = document.createElement('button');\n \n const onPress = (event: Event | TouchEvent) => {\n event.stopPropagation();\n this.options_.onStopCasting();\n };\n\n button.onclick = onPress;\n button.ontouchstart = onPress;\n button.className = 'stop-casting-button';\n button.innerHTML = this.localize('Stop casting');\n\n (this as any).el_.querySelector('.cv-devices-content').appendChild(button);\n }\n\n // This function needs to be here in order to get \n // VideoJS to add this component into its UI tree..\n public play(): void {}\n}\n","import videojs from 'video.js';\n\nimport { CastSession, Device } from 'projects/player/plugins/devices-plugin/clients/client-interfaces';\nimport { DevicesSessionManager } from 'projects/player/plugins/devices-plugin/devices-session-manager';\nimport { LocalCacheHelper } from 'projects/player/utils/local-cache-helper';\nimport { TrackHelper } from 'projects/player/utils/track-helper';\n\nimport { DevicesTechUI } from './devices-tech-ui/devices-tech-ui';\n\ninterface TechWithConstructor extends videojs.Tech {\n new (options: videojs.ComponentOptions, ready: videojs.Component.ReadyCallback): videojs.Tech;\n}\n\ninterface DevicesTechOptions extends videojs.ComponentOptions {\n source: videojs.Tech.SourceObject;\n instanceId?: string;\n poster?: string;\n playerId: string;\n}\n\ntype PlayerTextTrack = TextTrack & { src?: string };\n\nconst Tech = videojs.getComponent('Tech') as unknown as TechWithConstructor;\n\nclass DevicesTech extends Tech {\n private ui?: DevicesTechUI;\n private videojsPlayer: videojs.Player;\n\n public readonly featuresVolumeControl: boolean = true;\n public readonly featuresPlaybackRate: boolean = false;\n public readonly movingMediaElementInDOM: boolean = false;\n public readonly featuresFullscreenResize: boolean = true;\n public readonly featuresTimeupdateEvents: boolean = true;\n public readonly featuresProgressEvents: boolean = false;\n public readonly featuresNativeTextTracks: boolean = false;\n public readonly featuresNativeAudioTracks: boolean = false;\n public readonly featuresNativeVideoTracks: boolean = false;\n public readonly featuresMuteControl: boolean = true;\n public readonly featuresSourceset: boolean = false;\n\n public options_: DevicesTechOptions;\n\n constructor(options: videojs.ComponentOptions, ready: videojs.Component.ReadyCallback) {\n super(options, ready as any);\n\n this.videojsPlayer = videojs(this.options_.playerId);\n \n this.bindFunctions();\n this.bindEventListeners();\n\n this.ready((): void => {\n this.setSource(this.options_.source);\n });\n \n this.triggerReady();\n }\n\n private bindFunctions(): void {\n this.bindEventListeners = this.bindEventListeners.bind(this);\n this.onTextTrackChanged = this.onTextTrackChanged.bind(this);\n this.getSelectedTextTrack = this.getSelectedTextTrack.bind(this);\n this.setSelectedTextTrack = this.setSelectedTextTrack.bind(this);\n this.showUI = this.showUI.bind(this);\n this.hideUI = this.hideUI.bind(this);\n this.dispose = this.dispose.bind(this);\n this.setSource = this.setSource.bind(this);\n this.getCastSession = this.getCastSession.bind(this);\n }\n\n private bindEventListeners(): void {\n const session = this.getCastSession();\n\n if (!session) return;\n\n this.textTracks().on('change', this.onTextTrackChanged);\n\n this.videojsPlayer.one('ended', () => {\n session.dispose();\n });\n\n session.on('durationchange', () => {\n this.trigger('durationchange');\n });\n\n session.on('dispose', () => {\n this.trigger('ended');\n this.hideUI();\n });\n\n session.on('playingchange', () => {\n const playing = session.isPlaying();\n\n if (playing) {\n this.trigger('play');\n this.trigger('playing');\n } else {\n this.trigger('pause');\n }\n });\n\n session.on('volumechange', () => {\n this.trigger('volumechange');\n });\n\n session.on('sourceloaded', () => {\n this.trigger('loadeddata');\n });\n\n session.on('subtitleschange', () => {\n this.setSelectedTextTrack(session.getSubtitles());\n });\n }\n\n private onTextTrackChanged(): void {\n const textTrack = this.getSelectedTextTrack();\n\n this.getCastSession()?.setSubtitles(textTrack?.src);\n }\n\n private getSelectedTextTrack(): PlayerTextTrack | null {\n return TrackHelper.findTrackByPredicate(this.videojsPlayer.player_, (track: PlayerTextTrack) => {\n return track.mode === 'showing' && !!track.src;\n }) as PlayerTextTrack;\n }\n\n private setSelectedTextTrack(subtitleSource: string): void {\n TrackHelper.forEachTrack(this.videojsPlayer.player_, (t: PlayerTextTrack) => {\n if (t.kind !== 'subtitles')\n return;\n\n if (t.src === subtitleSource)\n t.mode = 'showing';\n else\n t.mode = 'disabled';\n });\n }\n\n private showUI(device: Device): void {\n if (!this.ui) return;\n\n this.ui.setPoster(this.options_.poster);\n this.ui.setDevice(device);\n this.ui.show();\n }\n\n private hideUI(): void {\n this.ui?.hide();\n }\n\n public dispose(): void {\n this.textTracks().off('change', this.onTextTrackChanged);\n\n const session = this.getCastSession();\n\n if (session)\n session.dispose();\n \n super.cleanupAutoTextTracks();\n super.dispose();\n }\n\n public createEl(): Element {\n this.ui = this.ui || new DevicesTechUI({\n onStopCasting: () => {\n this.getCastSession()?.dispose();\n }\n });\n\n return this.ui.el();\n }\n\n public setSource(source: videojs.Tech.SourceObject): void {\n const session = this.getCastSession();\n\n if (!session) return;\n\n this.showUI(session.getDevice());\n\n this.trigger('loadstart');\n\n const textTrack = this.getSelectedTextTrack();\n\n // The remote casting devices often cannot reach the Local Cache server on a\n // school's network. When setting the source for the casting session, we always\n // use the CDN URL..\n session.loadSource(LocalCacheHelper.getOriginalUrl(source.src), textTrack?.src);\n }\n\n public addRemoteTextTrack(options: videojs.TextTrackOptions): HTMLTrackElement {\n return super.addRemoteTextTrack(options, true);\n }\n\n public getCastSession(): CastSession | undefined {\n return DevicesSessionManager\n .getOrCreateInstance(this.options_.instanceId ?? '')\n .getCastSession();\n }\n\n public play(): void {\n this.getCastSession()?.play();\n }\n\n public pause(): void {\n this.getCastSession()?.pause();\n }\n\n public paused(): boolean {\n return this.getCastSession()?.isPlaying() === false;\n }\n\n public ended(): boolean {\n return this.getCastSession()?.isPlaybackFinished() ?? false;\n }\n\n public setCurrentTime(time?: number): void {\n this.getCastSession()?.seek(time ?? 0);\n }\n\n public currentTime(): number {\n return this.getCastSession()?.getPosition() ?? 0;\n }\n\n public duration(): number {\n return this.getCastSession()?.getDuration() ?? this.videojsPlayer.duration();\n }\n\n public volume(): number {\n return this.getCastSession()?.getVolume() ?? 1;\n }\n\n public setVolume(volume: number): void {\n this.getCastSession()?.setVolume(volume);\n }\n\n public muted(): boolean {\n return this.getCastSession()?.getMuted() ?? false;\n }\n\n public setMuted(muted: boolean): void {\n this.getCastSession()?.setMuted(muted);\n }\n \n public buffered(): void {\n return undefined; // Intentionally returning undefined to opt out of displaying a buffer\n }\n\n public seekable(): videojs.TimeRange {\n return videojs.createTimeRanges(0, this.duration());\n }\n\n public playbackRate(): number {\n return 1;\n }\n\n public readyState(): number {\n // See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState\n return 4;\n }\n\n public controls(): boolean {\n return false;\n }\n\n public playsinline(): boolean {\n return true;\n }\n\n public supportsFullScreen(): boolean {\n return true;\n }\n\n public setAutoplay(): void { }\n\n public preload(): void { }\n\n public load(): void { }\n\n public setPlaybackRate(): void { }\n \n public static canPlayType(): string {\n return '';\n }\n\n public static canPlaySource(sourceObject: videojs.Tech.SourceObject, techOptions?: { instanceId: string }): boolean {\n // TODO: Check if the selected device can actually play the current source type\n return !!DevicesSessionManager\n .getOrCreateInstance(techOptions?.instanceId ?? '')\n .getCastSession();\n }\n\n public static isSupported(): boolean {\n return DevicesSessionManager.isActive();\n }\n}\n\nvideojs.registerTech('devices', DevicesTech);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { EntityType, EventVersion, PlaybackDescriptor, UserAction, WorkflowPhase } from 'libs/analytics/interfaces';\n\nimport { DevicesConfig } from 'projects/player/interfaces/DevicesConfig';\nimport { AnalyticsService } from 'projects/player/services/analytics-service';\n\nimport { AppleTvClient } from './clients/apple-tv/apple-tv-client';\nimport { CastSession, Client, Device, DeviceType } from './clients/client-interfaces';\nimport { ViviClient } from './clients/vivi/vivi-client';\nimport { DeviceMenuItem } from './components/device-menu-item/device-menu-item';\nimport { DevicesButton, DevicesButtonOptions } from './components/devices-button/devices-button';\nimport { DevicesSessionManager } from './devices-session-manager';\n\nimport './devices-plugin.scss';\n\nimport './components/devices-button/devices-button';\nimport './tech/devices-tech';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface DevicesPluginOptions extends DevicesConfig {\n userId?: number;\n title: string;\n analyticsService?: AnalyticsService;\n}\n\nclass DevicesPlugin extends Plugin {\n private options: DevicesPluginOptions;\n private devicesButton?: DevicesButton;\n private instanceId: string;\n\n constructor(player: VideoJsPlayer, options: DevicesPluginOptions) {\n super(player, options);\n\n this.options = options;\n this.instanceId = this.player.options_.devices?.instanceId ?? '';\n\n this.bindFunctions();\n this.initialize();\n }\n\n private bindFunctions(): void {\n this.initialize = this.initialize.bind(this);\n this.onReady = this.onReady.bind(this);\n this.onDevicesChanged = this.onDevicesChanged.bind(this);\n this.onCastSessionChanged = this.onCastSessionChanged.bind(this);\n this.onDevicesError = this.onDevicesError.bind(this);\n this.addViviClient = this.addViviClient.bind(this);\n this.addAppleTvClient = this.addAppleTvClient.bind(this);\n this.reloadTech = this.reloadTech.bind(this);\n this.getSessionManager = this.getSessionManager.bind(this);\n this.dispose = this.dispose.bind(this);\n }\n\n private initialize(): void {\n this.player.ready(this.onReady);\n }\n\n private onReady(): void {\n const collapserator = this.player.getChild('collapserator');\n const sessionManager = this.getSessionManager();\n\n if (!collapserator) return;\n if (!sessionManager) return;\n\n sessionManager.on('deviceschange', this.onDevicesChanged);\n sessionManager.on('castsessionchange', this.onCastSessionChanged);\n sessionManager.on('error', this.onDevicesError);\n\n const onDevicesButtonClick = () => {\n this.addViviClient(sessionManager);\n this.addAppleTvClient(sessionManager);\n };\n\n const onDeviceMenuItemClick = (item: DeviceMenuItem, device: Device) => {\n sessionManager.startCastSession({\n device,\n title: this.options.title\n });\n\n this.options.analyticsService?.logUserAction(device, {\n actionType: UserAction.Select,\n workflowPhase: WorkflowPhase.Complete,\n descriptor: PlaybackDescriptor.ChangeDevice,\n entity: EntityType.Device,\n eventVersion: EventVersion.V3\n });\n };\n\n // Determine which integrations are inactive for the CTA\n const ctaOptions = this.options.ctaOptions;\n const viviConfig = this.options.vivi;\n const appleTvConfig = this.options.appleTv;\n const inactiveIntegrations: DeviceType[] = [];\n\n if (!appleTvConfig.enabled)\n inactiveIntegrations.push(DeviceType.AppleTv);\n\n if (!viviConfig.enabled || !viviConfig.accountConnected)\n inactiveIntegrations.push(DeviceType.Vivi);\n\n const buttonOptions: DevicesButtonOptions = {\n onClick: onDevicesButtonClick,\n onDeviceMenuItemClick,\n ctaOptions: {\n ...ctaOptions,\n inactiveIntegrations\n }\n };\n\n this.devicesButton = collapserator.addChild('DevicesButton', buttonOptions) as DevicesButton;\n }\n\n private onDevicesChanged(devices: Device[]): void {\n this.devicesButton?.setDevices(devices);\n }\n\n private onCastSessionChanged(castSession: CastSession | undefined): void {\n this.devicesButton?.setCastSession(castSession);\n this.reloadTech();\n\n if (castSession) {\n // Hide some UI elements and prevent the controls from fading out when casting\n this.player.addClass('cv-device-casting');\n this.player.addClass(`cv-device-${castSession.getDevice().type}`);\n\n // Exit fullscreen when casting\n if (this.player.isFullscreen())\n this.player.exitFullscreen();\n } else {\n // Restore the UI elements\n this.player.removeClass('cv-device-casting');\n this.player.removeClass(`cv-device-${DeviceType.AppleTv}`);\n this.player.removeClass(`cv-device-${DeviceType.Vivi}`);\n }\n }\n\n private onDevicesError(err: Error): void {\n this.player.error(err.message);\n this.player.pause();\n }\n\n private addViviClient(sessionManager: DevicesSessionManager): void {\n if (!this.options.vivi.enabled) return;\n if (!this.options.vivi.accountConnected) return;\n if (!this.options.vivi.apiUrl) return;\n if (sessionManager.hasInstanceOfClient(ViviClient)) return;\n\n const viviClient = new ViviClient({\n url: this.options.vivi.apiUrl,\n fetchAccessToken: this.options.vivi.fetchAccessToken\n });\n\n sessionManager.addClient(viviClient as Client);\n }\n\n private addAppleTvClient(sessionManager: DevicesSessionManager): void {\n if (!this.options.appleTv.enabled) return;\n if (!this.options.trackingCode) return;\n if (!this.options.userId) return;\n if (sessionManager.hasInstanceOfClient(AppleTvClient)) return;\n\n const appleTvClient = new AppleTvClient({\n fetchAccessToken: this.options.appleTv.fetchAccessToken,\n trackingCode: this.options.trackingCode,\n userId: this.options.userId\n });\n\n sessionManager.addClient(appleTvClient as Client);\n }\n\n private reloadTech(): void {\n const player = this.player;\n const sources = player.currentSources();\n const volume = player.volume();\n const muted = player.muted();\n const time = player.currentTime();\n const paused = player.paused();\n \n // This will cause the techs to get re-evaluated in the provided `techOrder`\n player.src(sources);\n\n // Restore the state of the player when playback starts\n player.one('playing', () => {\n player.volume(volume);\n player.muted(muted);\n player.currentTime(time);\n \n if (paused)\n player.pause();\n else\n player.play();\n });\n }\n\n private getSessionManager(): DevicesSessionManager | undefined {\n if (this.instanceId)\n return DevicesSessionManager.getOrCreateInstance(this.instanceId);\n }\n\n public dispose(): void {\n const sessionManager = this.getSessionManager();\n\n if (!sessionManager) return;\n\n sessionManager.off('deviceschange', this.onDevicesChanged);\n sessionManager.off('castsessionchange', this.onCastSessionChanged);\n sessionManager.off('error', this.onDevicesError);\n\n DevicesSessionManager.disposeAndRemoveInstance(sessionManager);\n\n super.dispose();\n }\n}\n\nvideojs.registerPlugin('devicesPlugin', DevicesPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n devicesPlugin(options: DevicesPluginOptions): void;\n }\n}\n","import React from 'react';\nimport videojs, { VideoJsPlayer } from 'video.js';\n\nimport { ResourceTile } from 'libs/shared/components/widgets/items/resource-widget-item/ResourceWidgetItem';\nimport { Resource } from 'libs/shared/interfaces';\n\nimport { Resource as PlayerResource } from 'projects/player/interfaces/models/PlaybackObject';\nimport { getReactComponent } from 'projects/player/react/react-component';\n\nimport './resource-menu-item.scss';\n\ninterface ResourceMenuItemProps {\n resource: PlayerResource;\n imageCdnUrl: string;\n label?: string;\n}\n\nfunction ReactResourceMenuItem(props: ResourceMenuItemProps): JSX.Element {\n return (\n <div className='cv-resource-item'>\n <ResourceTile\n data={props.resource as Resource}\n imageCdnUrl={props.imageCdnUrl}\n titlePosition='above'\n hideTypeBadge\n />\n </div>\n );\n}\n\nconst _ResourceMenuItem = getReactComponent<ResourceMenuItemProps>(\n (player: VideoJsPlayer, options: ResourceMenuItemProps) => <ReactResourceMenuItem {...options} />\n);\n\nconst MenuItem = videojs.getComponent('MenuItem');\n\ninterface ResourceMenuItemOptions extends videojs.ComponentOptions, ResourceMenuItemProps {\n downloadResource: (resource: PlayerResource) => void;\n}\n\nexport class ResourceMenuItem extends MenuItem {\n public options_: ResourceMenuItemOptions;\n\n constructor(player: VideoJsPlayer, options: ResourceMenuItemOptions) {\n super(player, options);\n\n const menuItem = new _ResourceMenuItem(player, { resource: options.resource, imageCdnUrl: options.imageCdnUrl });\n this.addChild(menuItem);\n }\n\n public createEl(tagName?: string, properties: any = {}, attributes?: any): HTMLLIElement {\n return super.createEl(tagName, {\n ...properties,\n className: `${properties.className} cv-resource-menu-item`\n }, attributes);\n }\n\n public handleClick(event: videojs.EventTarget.Event): void {\n // Prevent menu from closing on click\n event.stopImmediatePropagation();\n\n this.options_.downloadResource(this.options_.resource);\n }\n}\n","import videojs from 'video.js';\n\nimport { LocationUtils } from 'libs/common/backbone/core';\n\nimport { CollapsibleHeadingMenuItem } from 'projects/player/components/cog-button/collapsible-heading-menu-item';\nimport { CollapsibleComponent } from 'projects/player/interfaces/CollapsibleComponent';\nimport { Resource as PlayerResource } from 'projects/player/interfaces/models/PlaybackObject';\nimport {\n ResourceMenuItem\n} from 'projects/player/plugins/resources-plugin/components/resource-menu-item/resource-menu-item';\n\nimport './resources-button.scss';\n\nconst MenuButton = videojs.getComponent('MenuButton');\n\ninterface ResourceButtonOptions extends videojs.MenuButtonOptions {\n resources: PlayerResource[];\n imageCdnUrl: string;\n onClickResource: (resource: PlayerResource) => void;\n}\n\nclass ResourcesButton extends MenuButton implements CollapsibleComponent {\n public options_: ResourceButtonOptions;\n public controlText_: string;\n\n private downloadIframe: HTMLIFrameElement;\n\n public buildWrapperCSSClass() {\n return `cv-menu-small cv-resources-button-wrapper ${super.buildWrapperCSSClass()}`;\n }\n\n public buildCSSClass(): string {\n return `cv-resources-button ${super.buildCSSClass()}`;\n }\n\n public update(): void {\n super.update();\n }\n\n public createItems(): videojs.MenuItem[] {\n const items: videojs.MenuItem[] = [];\n\n items.push(new CollapsibleHeadingMenuItem(this.player_, {\n label: 'Resources'\n }) as any);\n\n this.options_.resources.forEach(resource => {\n const menuItem = new ResourceMenuItem(this.player(), {\n resource,\n imageCdnUrl: this.options_.imageCdnUrl,\n downloadResource: (resource: PlayerResource) => this.downloadResource(resource),\n label: resource.name\n });\n\n items.push(menuItem as unknown as videojs.MenuItem);\n });\n\n return items;\n }\n\n private downloadResource(resource: PlayerResource): void {\n if (resource.type === 'link') {\n LocationUtils.PageLoad(resource.url, true);\n return;\n }\n\n this.getDownloadIframe().src = resource.url;\n }\n\n private getDownloadIframe(): HTMLIFrameElement {\n if (this.downloadIframe)\n return this.downloadIframe;\n\n this.downloadIframe = videojs.dom.createEl('iframe') as HTMLIFrameElement;\n this.downloadIframe.style.display = 'none';\n\n videojs.dom.appendContent(videojs.dom.$('body'), this.downloadIframe);\n\n return this.downloadIframe;\n }\n\n /**\n * CollapsibleComponent implementation below\n */\n public alwaysCollapsed: boolean = false;\n \n public isCollapsed: boolean = false;\n \n public isCollabsible: boolean = true;\n \n public getCollabsibleName(): string {\n return this.controlText_;\n }\n \n public getCollabsibleValue(): string {\n return '';\n }\n \n public showInCollabsibleMenu(): boolean {\n return true;\n }\n \n public showCollapsibleMenu(): void {\n super.handleClick(null);\n }\n}\n\nResourcesButton.prototype.controlText_ = 'Resources';\n\nvideojs.registerComponent('ResourcesButton', ResourcesButton);\n","import videojs, { VideoJsPlayer } from 'video.js';\n\nimport { Resource } from 'projects/player/interfaces/models/PlaybackObject';\n\nimport 'projects/player/plugins/resources-plugin/components/resources-button/resources-button';\n\nconst Plugin = videojs.getPlugin('plugin');\n\ninterface ResourcesPluginOptions {\n resources: Resource[];\n imageCdnUrl: string;\n}\n\nclass ResourcesPlugin extends Plugin {\n private options: ResourcesPluginOptions;\n\n constructor(player: VideoJsPlayer, options: ResourcesPluginOptions) {\n super(player, options);\n\n this.options = options;\n\n player.ready(() => this.onReady());\n }\n\n private onReady(): void {\n if (!this.options.resources.length)\n return;\n\n const collapserator = this.player.getChild('collapserator');\n\n collapserator.addChild('ResourcesButton', {\n resources: this.options.resources,\n imageCdnUrl: this.options.imageCdnUrl\n });\n }\n}\n\nvideojs.registerPlugin('resourcesPlugin', ResourcesPlugin);\n\ndeclare module 'video.js' {\n export interface VideoJsPlayer {\n resourcesPlugin(options: ResourcesPluginOptions): void;\n }\n}\n","import React from 'react';\n\nimport { Player, PlayerOptions } from 'projects/player/players/player';\nimport { getProxy } from 'projects/player/utils/getProxy';\n\n/**\n * React plugins are exported on the react player in order to allow\n * our dist files to not require react - Sha\n */\nimport 'projects/player/plugins/devices-plugin/devices-plugin';\nimport 'projects/player/plugins/next-video-plugin/next-video-plugin';\nimport 'projects/player/plugins/resources-plugin/resources-plugin';\nimport 'projects/player/plugins/transcript-plugin/transcript-plugin';\nimport 'projects/player/plugins/old-version-refresh-plugin/old-version-refresh-plugin';\n\nexport interface ClickViewPlayerProps extends Omit<PlayerOptions, 'playerApi'> {\n // TODO Remove optional from playerApi\n playerApi?: URL;\n className?: string;\n onReady?: (player: Player) => void;\n onError?: (error: any) => void;\n onDispose?: () => void;\n}\n\nexport function ClickViewPlayer(props: ClickViewPlayerProps): React.ReactElement {\n const { className = '', playerApi, onReady, onDispose, ...playerOptions } = props;\n \n const containerRef = React.useRef(null);\n\n React.useEffect(() => {\n if (!containerRef)\n return;\n\n const player = new Player(containerRef.current, {\n ...playerOptions,\n playerApi: playerApi\n });\n\n if (onReady) {\n player.ready(() => {\n onReady(getProxy(player));\n });\n }\n\n if (onDispose) {\n player.one('dispose', onDispose);\n }\n \n return () => {\n player?.dispose();\n };\n }, [props.viewKey]);\n\n return (\n <div ref={containerRef} className={className}></div>\n );\n}\n\nexport default ClickViewPlayer;\n"],"mappings":"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"}
|