import { resolveDefaultLanguage } from '@vouchfor/media-player-legacy'; import { css, html, LitElement } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { createRef, ref } from 'lit/directives/ref.js'; import type { Scene, Scenes, TemplateInstance } from '@vouchfor/canvas-video-legacy'; import type { MediaPlayer, MediaPlayerProps } from '@vouchfor/media-player-legacy'; import type { PropertyValueMap } from 'lit'; import type { Environment } from '~/utils/env'; import { EventForwardController } from './controllers/event-forwarder'; import { FetcherController } from './controllers/fetcher'; import { TrackingController } from './controllers/tracking'; import { getEnvUrls } from '~/utils/env'; import '@vouchfor/media-player-legacy'; type PlayerEmbedProps = Pick< MediaPlayerProps, 'data' | 'aspectRatio' | 'preload' | 'autoplay' | 'controls' | 'defaultLanguage' | 'languages' > & { env: Environment; apiKey: string; disableTracking?: boolean; trackingSource?: string; vouchId?: string; templateId?: string; // Index of the questions to include starting from 1 questions?: number[]; senderId?: string; }; @customElement('vouch-embed-legacy-player') class PlayerEmbed extends LitElement { static styles = [ css` :host { display: flex; } ` ]; @property({ type: Object }) data: PlayerEmbedProps['data']; @property({ type: String }) vouchId: PlayerEmbedProps['vouchId']; @property({ type: String }) templateId: PlayerEmbedProps['templateId']; @property({ type: Array }) questions: PlayerEmbedProps['questions']; @property({ type: String }) env: PlayerEmbedProps['env'] = 'prod'; @property({ type: String }) apiKey: PlayerEmbedProps['apiKey'] = ''; @property({ type: Boolean }) disableTracking: PlayerEmbedProps['disableTracking'] = false; @property({ type: String }) trackingSource: PlayerEmbedProps['trackingSource'] = 'embedded_player'; @property({ type: Array }) controls: PlayerEmbedProps['controls']; @property({ type: String }) preload: PlayerEmbedProps['preload'] = 'auto'; @property({ type: Boolean }) autoplay: PlayerEmbedProps['autoplay'] = false; @property({ type: Number }) aspectRatio: PlayerEmbedProps['aspectRatio'] = 0; @property({ type: String }) senderId?: PlayerEmbedProps['senderId']; @property({ type: String }) defaultLanguage?: PlayerEmbedProps['defaultLanguage']; @property({ attribute: false }) languages?: PlayerEmbedProps['languages']; private eventController = new EventForwardController(this, [ 'durationchange', 'ended', 'error', 'loadeddata', 'pause', 'stalled', 'play', 'playing', 'ratechange', 'scenechange', 'scenesupdate', 'seeking', 'seeked', 'timeupdate', 'volumechange', 'processing', 'waiting', 'video:loadeddata', 'video:seeking', 'video:seeked', 'video:play', 'video:playing', 'video:pause', 'video:stalled', 'video:timeupdate', 'video:ended', 'video:error' ]); private _fetcherController = new FetcherController(this); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore private _trackingController = new TrackingController(this); @state() vouch: PlayerEmbedProps['data']; @state() template: TemplateInstance | undefined; get fetching() { return this._fetcherController.fetching; } private _mediaPlayerRef = createRef(); get waiting() { return this._mediaPlayerRef.value?.waiting; } get initialised() { return this._mediaPlayerRef.value?.initialised; } get seeking() { return this._mediaPlayerRef.value?.seeking; } get paused() { return this._mediaPlayerRef.value?.paused; } get captions() { return this._mediaPlayerRef.value?.captions; } get fullscreen() { return this._mediaPlayerRef.value?.fullscreen; } get duration() { return this._mediaPlayerRef.value?.duration; } set currentTime(value: number) { if (this._mediaPlayerRef.value) { this._mediaPlayerRef.value.currentTime = value; } } get currentTime() { return this._mediaPlayerRef.value?.currentTime ?? 0; } set playbackRate(value: number) { if (this._mediaPlayerRef.value) { this._mediaPlayerRef.value.playbackRate = value; } } get playbackRate() { return this._mediaPlayerRef.value?.playbackRate ?? 1; } set volume(value: number) { if (this._mediaPlayerRef.value) { this._mediaPlayerRef.value.volume = value; } } get volume() { return this._mediaPlayerRef.value?.volume ?? 1; } set muted(value: boolean) { if (this._mediaPlayerRef.value) { this._mediaPlayerRef.value.muted = value; } } get muted() { return this._mediaPlayerRef.value?.muted ?? false; } get scene(): Scene | null { return this._mediaPlayerRef.value?.scene ?? null; } get scenes(): Scene[] { return this._mediaPlayerRef.value?.scenes ?? []; } get sceneConfig(): Scenes | null { return this._mediaPlayerRef.value?.sceneConfig ?? null; } get videoState() { return this._mediaPlayerRef.value?.videoState; } get mediaPlayer() { return this._mediaPlayerRef.value; } play() { this._mediaPlayerRef.value?.play(); } pause() { this._mediaPlayerRef.value?.pause(); } reset(time = 0, play = false) { this._mediaPlayerRef.value?.reset(time, play); } setScene(index: number) { this._mediaPlayerRef.value?.setScene(index); } private _renderStyles() { if (!this.aspectRatio) { return html` `; } if (typeof this.aspectRatio === 'number') { return html` `; } return null; } protected willUpdate(changedProperties: PropertyValueMap) { // If the vouch this embed is pointing to changes then reset the player if (changedProperties.has('vouchId') && this.vouchId !== changedProperties.get('vouchId')) { this.reset(0, false); } } render() { return html` ${this._renderStyles()} `; } } declare global { interface HTMLElementTagNameMap { 'vouch-embed-legacy-player': PlayerEmbed; } namespace JSX { interface IntrinsicElements { 'vouch-embed-legacy-player': PlayerEmbed; } } } export { PlayerEmbed }; export type { PlayerEmbedProps };