diff --git a/client/src/standalone/videos/embed-api.ts b/client/src/standalone/videos/embed-api.ts index 0e8489b6d..879d251a6 100644 --- a/client/src/standalone/videos/embed-api.ts +++ b/client/src/standalone/videos/embed-api.ts @@ -1,8 +1,8 @@ -import './embed.scss' import * as Channel from 'jschannel' import { logger } from '../../root-helpers' import { PeerTubeResolution, PeerTubeTextTrack } from '../embed-player-api/definitions' import { PeerTubeEmbed } from './embed' +import './embed.scss' /** * Embed API exposes control of the embed player to the outside world via @@ -13,7 +13,6 @@ export class PeerTubeEmbedApi { private isReady = false private resolutions: PeerTubeResolution[] = [] - private oldVideoElement: HTMLVideoElement private videoElPlayListener: () => void private videoElPauseListener: () => void private videoElEndedListener: () => void @@ -36,8 +35,8 @@ export class PeerTubeEmbedApi { } } - private get element () { - return this.embed.getPlayerElement() + private get player () { + return this.embed.player } private constructChannel () { @@ -45,12 +44,12 @@ export class PeerTubeEmbedApi { channel.bind('setVideoPassword', (txn, value) => this.embed.setVideoPasswordByAPI(value)) - channel.bind('play', (txn, params) => this.embed.player.play()) - channel.bind('pause', (txn, params) => this.embed.player.pause()) - channel.bind('seek', (txn, time) => this.embed.player.currentTime(time)) + channel.bind('play', (txn, params) => this.player.play()) + channel.bind('pause', (txn, params) => this.player.pause()) + channel.bind('seek', (txn, time) => this.player.currentTime(time)) - channel.bind('setVolume', (txn, value) => this.embed.player.volume(value)) - channel.bind('getVolume', (txn, value) => this.embed.player.volume()) + channel.bind('setVolume', (txn, value) => this.player.volume(value)) + channel.bind('getVolume', (txn, value) => this.player.volume()) channel.bind('isReady', (txn, params) => this.isReady) @@ -60,9 +59,9 @@ export class PeerTubeEmbedApi { channel.bind('getCaptions', (txn, params) => this.getCaptions()) channel.bind('setCaption', (txn, id) => this.setCaption(id)) - channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate)) - channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate()) - channel.bind('getPlaybackRates', (txn, params) => this.embed.player.options_.playbackRates) + channel.bind('setPlaybackRate', (txn, playbackRate) => this.player.playbackRate(playbackRate)) + channel.bind('getPlaybackRate', (txn, params) => this.player.playbackRate()) + channel.bind('getPlaybackRates', (txn, params) => this.player.options_.playbackRates) channel.bind('playNextVideo', (txn, params) => this.embed.playNextPlaylistVideo()) channel.bind('playPreviousVideo', (txn, params) => this.embed.playPreviousPlaylistVideo()) @@ -79,11 +78,11 @@ export class PeerTubeEmbedApi { return } - this.embed.player.peertubeResolutions().select({ id: resolutionId, fireCallback: true }) + this.player.peertubeResolutions().select({ id: resolutionId, fireCallback: true }) } private getCaptions (): PeerTubeTextTrack[] { - return this.embed.player.textTracks().tracks_.map(t => ({ + return this.player.textTracks().tracks_.map(t => ({ id: t.id, src: t.src, label: t.label, @@ -92,7 +91,7 @@ export class PeerTubeEmbedApi { } private setCaption (id: string) { - const tracks = this.embed.player.textTracks().tracks_ + const tracks = this.player.textTracks().tracks_ for (const track of tracks) { if (track.id === id) track.mode = 'showing' @@ -112,15 +111,15 @@ export class PeerTubeEmbedApi { let currentState: 'playing' | 'paused' | 'unstarted' | 'ended' = 'unstarted' this.videoElInterval = setInterval(() => { - const position = this.element.currentTime - const volume = this.element.volume + const position = this.player?.currentTime() ?? 0 + const volume = this.player?.volume() this.channel.notify({ method: 'playbackStatusUpdate', params: { position, volume, - duration: this.embed.player.duration(), + duration: this.player?.duration(), playbackState: currentState } }) @@ -132,52 +131,48 @@ export class PeerTubeEmbedApi { currentState = 'playing' this.channel.notify({ method: 'playbackStatusChange', params: 'playing' }) } - this.element.addEventListener('play', this.videoElPlayListener) + this.player.on('play', this.videoElPlayListener) this.videoElPauseListener = () => { currentState = 'paused' this.channel.notify({ method: 'playbackStatusChange', params: 'paused' }) } - this.element.addEventListener('pause', this.videoElPauseListener) + this.player.on('pause', this.videoElPauseListener) this.videoElEndedListener = () => { currentState = 'ended' this.channel.notify({ method: 'playbackStatusChange', params: 'ended' }) } - this.element.addEventListener('ended', this.videoElEndedListener) - - this.oldVideoElement = this.element + this.player.on('ended', this.videoElEndedListener) // --------------------------------------------------------------------------- // PeerTube specific capabilities - this.embed.player.peertubeResolutions().on('resolutions-added', () => this.loadResolutions()) - this.embed.player.peertubeResolutions().on('resolutions-changed', () => this.loadResolutions()) + this.player.peertubeResolutions().on('resolutions-added', () => this.loadResolutions()) + this.player.peertubeResolutions().on('resolutions-changed', () => this.loadResolutions()) this.loadResolutions() - this.embed.player.on('volumechange', () => { + this.player.on('volumechange', () => { this.channel.notify({ method: 'volumeChange', - params: this.embed.player.volume() + params: this.player.volume() }) }) } private disposeStateTracking () { - if (!this.oldVideoElement) return + if (!this.player) return - this.oldVideoElement.removeEventListener('play', this.videoElPlayListener) - this.oldVideoElement.removeEventListener('pause', this.videoElPauseListener) - this.oldVideoElement.removeEventListener('ended', this.videoElEndedListener) + this.player.off('play', this.videoElPlayListener) + this.player.off('pause', this.videoElPauseListener) + this.player.off('ended', this.videoElEndedListener) clearInterval(this.videoElInterval) - - this.oldVideoElement = undefined } private loadResolutions () { - this.resolutions = this.embed.player.peertubeResolutions().getResolutions() + this.resolutions = this.player.peertubeResolutions().getResolutions() .map(r => ({ id: r.id, label: r.label, @@ -193,6 +188,6 @@ export class PeerTubeEmbedApi { } private isWebVideo () { - return !!this.embed.player.webVideo + return !!this.player.webVideo } } diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index b61a665e3..5114ec72b 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts @@ -83,10 +83,6 @@ export class PeerTubeEmbed { await embed.init() } - getPlayerElement () { - return this.playerHTML.getPlayerElement() - } - getScope () { return this.playerOptionsBuilder.getScope() } @@ -420,8 +416,8 @@ export class PeerTubeEmbed { playerElement.className = 'video-js vjs-peertube-skin' playerElement.setAttribute('playsinline', 'true') - this.playerHTML.setPlayerElement(playerElement) - this.playerHTML.addPlayerElementToDOM() + this.playerHTML.setInitVideoEl(playerElement) + this.playerHTML.addInitVideoElToDOM() const [ { PeerTubePlayer } ] = await Promise.all([ this.PeerTubePlayerManagerModulePromise, diff --git a/client/src/standalone/videos/shared/player-html.ts b/client/src/standalone/videos/shared/player-html.ts index ffe0261d3..76e5c12fb 100644 --- a/client/src/standalone/videos/shared/player-html.ts +++ b/client/src/standalone/videos/shared/player-html.ts @@ -5,36 +5,32 @@ import { Translations } from './translations' export class PlayerHTML { private readonly wrapperElement: HTMLElement - private playerElement: HTMLVideoElement + private initVideoEl: HTMLVideoElement private informationElement: HTMLDivElement constructor (private readonly videoWrapperId: string) { this.wrapperElement = document.getElementById(this.videoWrapperId) } - getPlayerElement () { - return this.playerElement + getInitVideoEl () { + return this.initVideoEl } - setPlayerElement (playerElement: HTMLVideoElement) { - this.playerElement = playerElement + setInitVideoEl (playerElement: HTMLVideoElement) { + this.initVideoEl = playerElement } - removePlayerElement () { - this.playerElement = null - } - - addPlayerElementToDOM () { - this.wrapperElement.appendChild(this.playerElement) + addInitVideoElToDOM () { + this.wrapperElement.appendChild(this.initVideoEl) } displayError (text: string, translations: Translations) { logger.error(text) // Remove video element - if (this.playerElement) { - this.removeElement(this.playerElement) - this.playerElement = undefined + if (this.initVideoEl) { + this.removeElement(this.initVideoEl) + this.initVideoEl = undefined } const translatedText = peertubeTranslate(text, translations) diff --git a/client/src/standalone/videos/shared/player-options-builder.ts b/client/src/standalone/videos/shared/player-options-builder.ts index 0cd65f721..ef493eae8 100644 --- a/client/src/standalone/videos/shared/player-options-builder.ts +++ b/client/src/standalone/videos/shared/player-options-builder.ts @@ -196,7 +196,7 @@ export class PlayerOptionsBuilder { authorizationHeader, - playerElement: () => this.playerHTML.getPlayerElement(), + playerElement: () => this.playerHTML.getInitVideoEl(), enableHotkeys: true, peertubeLink: () => this.peertubeLink, diff --git a/client/src/standalone/videos/test-embed.ts b/client/src/standalone/videos/test-embed.ts index 70376c383..2d3df0c7f 100644 --- a/client/src/standalone/videos/test-embed.ts +++ b/client/src/standalone/videos/test-embed.ts @@ -32,6 +32,13 @@ window.addEventListener('load', async () => { await player.ready logger.info('Player is ready.') + const updatePlaylistPosition = () => { + player.getCurrentPosition() + .then(position => { + document.getElementById('playlist-position').innerHTML = position + '' + }) + } + const monitoredEvents = [ 'pause', 'play', @@ -40,15 +47,19 @@ window.addEventListener('load', async () => { ] monitoredEvents.forEach(e => { - player.addEventListener(e as PlayerEventType, (param) => logger.info(`PLAYER: event '${e}' received`, { param })) - logger.info(`PLAYER: now listening for event '${e}'`) + player.addEventListener(e as PlayerEventType, param => { + logger.info(`PLAYER: event '${e}' received`, { param }) + + if (e === 'playbackStatusChange' && isPlaylist) { + updatePlaylistPosition() + } + }) if (isPlaylist) { - player.getCurrentPosition() - .then(position => { - document.getElementById('playlist-position').innerHTML = position + '' - }) + updatePlaylistPosition() } + + logger.info(`PLAYER: now listening for event '${e}'`) }) let playbackRates: number[] = []