diff options
Diffstat (limited to 'client/src/standalone/videos/embed.ts')
-rw-r--r-- | client/src/standalone/videos/embed.ts | 276 |
1 files changed, 132 insertions, 144 deletions
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index cc4274b99..78b812ffd 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts | |||
@@ -1,18 +1,26 @@ | |||
1 | import './embed.scss' | 1 | import './embed.scss' |
2 | import '../../assets/player/shared/dock/peertube-dock-component' | 2 | import '../../assets/player/shared/dock/peertube-dock-component' |
3 | import '../../assets/player/shared/dock/peertube-dock-plugin' | 3 | import '../../assets/player/shared/dock/peertube-dock-plugin' |
4 | import { PeerTubeServerError } from 'src/types' | ||
4 | import videojs from 'video.js' | 5 | import videojs from 'video.js' |
5 | import { peertubeTranslate } from '../../../../shared/core-utils/i18n' | 6 | import { |
6 | import { HTMLServerConfig, ResultList, VideoDetails, VideoPlaylist, VideoPlaylistElement, VideoState } from '../../../../shared/models' | 7 | HTMLServerConfig, |
7 | import { PeertubePlayerManager } from '../../assets/player' | 8 | ResultList, |
9 | ServerErrorCode, | ||
10 | VideoDetails, | ||
11 | VideoPlaylist, | ||
12 | VideoPlaylistElement, | ||
13 | VideoState | ||
14 | } from '../../../../shared/models' | ||
15 | import { PeerTubePlayer } from '../../assets/player/peertube-player' | ||
8 | import { TranslationsManager } from '../../assets/player/translations-manager' | 16 | import { TranslationsManager } from '../../assets/player/translations-manager' |
9 | import { getParamString, logger, videoRequiresAuth } from '../../root-helpers' | 17 | import { getParamString, logger, videoRequiresFileToken } from '../../root-helpers' |
10 | import { PeerTubeEmbedApi } from './embed-api' | 18 | import { PeerTubeEmbedApi } from './embed-api' |
11 | import { | 19 | import { |
12 | AuthHTTP, | 20 | AuthHTTP, |
13 | LiveManager, | 21 | LiveManager, |
14 | PeerTubePlugin, | 22 | PeerTubePlugin, |
15 | PlayerManagerOptions, | 23 | PlayerOptionsBuilder, |
16 | PlaylistFetcher, | 24 | PlaylistFetcher, |
17 | PlaylistTracker, | 25 | PlaylistTracker, |
18 | Translations, | 26 | Translations, |
@@ -27,18 +35,26 @@ export class PeerTubeEmbed { | |||
27 | config: HTMLServerConfig | 35 | config: HTMLServerConfig |
28 | 36 | ||
29 | private translationsPromise: Promise<{ [id: string]: string }> | 37 | private translationsPromise: Promise<{ [id: string]: string }> |
30 | private PeertubePlayerManagerModulePromise: Promise<any> | 38 | private PeerTubePlayerManagerModulePromise: Promise<any> |
31 | 39 | ||
32 | private readonly http: AuthHTTP | 40 | private readonly http: AuthHTTP |
33 | private readonly videoFetcher: VideoFetcher | 41 | private readonly videoFetcher: VideoFetcher |
34 | private readonly playlistFetcher: PlaylistFetcher | 42 | private readonly playlistFetcher: PlaylistFetcher |
35 | private readonly peertubePlugin: PeerTubePlugin | 43 | private readonly peertubePlugin: PeerTubePlugin |
36 | private readonly playerHTML: PlayerHTML | 44 | private readonly playerHTML: PlayerHTML |
37 | private readonly playerManagerOptions: PlayerManagerOptions | 45 | private readonly playerOptionsBuilder: PlayerOptionsBuilder |
38 | private readonly liveManager: LiveManager | 46 | private readonly liveManager: LiveManager |
39 | 47 | ||
48 | private peertubePlayer: PeerTubePlayer | ||
49 | |||
40 | private playlistTracker: PlaylistTracker | 50 | private playlistTracker: PlaylistTracker |
41 | 51 | ||
52 | private alreadyInitialized = false | ||
53 | private alreadyPlayed = false | ||
54 | |||
55 | private videoPassword: string | ||
56 | private requiresPassword: boolean | ||
57 | |||
42 | constructor (videoWrapperId: string) { | 58 | constructor (videoWrapperId: string) { |
43 | logger.registerServerSending(window.location.origin) | 59 | logger.registerServerSending(window.location.origin) |
44 | 60 | ||
@@ -48,8 +64,9 @@ export class PeerTubeEmbed { | |||
48 | this.playlistFetcher = new PlaylistFetcher(this.http) | 64 | this.playlistFetcher = new PlaylistFetcher(this.http) |
49 | this.peertubePlugin = new PeerTubePlugin(this.http) | 65 | this.peertubePlugin = new PeerTubePlugin(this.http) |
50 | this.playerHTML = new PlayerHTML(videoWrapperId) | 66 | this.playerHTML = new PlayerHTML(videoWrapperId) |
51 | this.playerManagerOptions = new PlayerManagerOptions(this.playerHTML, this.videoFetcher, this.peertubePlugin) | 67 | this.playerOptionsBuilder = new PlayerOptionsBuilder(this.playerHTML, this.videoFetcher, this.peertubePlugin) |
52 | this.liveManager = new LiveManager(this.playerHTML) | 68 | this.liveManager = new LiveManager(this.playerHTML) |
69 | this.requiresPassword = false | ||
53 | 70 | ||
54 | try { | 71 | try { |
55 | this.config = JSON.parse((window as any)['PeerTubeServerConfig']) | 72 | this.config = JSON.parse((window as any)['PeerTubeServerConfig']) |
@@ -69,14 +86,14 @@ export class PeerTubeEmbed { | |||
69 | } | 86 | } |
70 | 87 | ||
71 | getScope () { | 88 | getScope () { |
72 | return this.playerManagerOptions.getScope() | 89 | return this.playerOptionsBuilder.getScope() |
73 | } | 90 | } |
74 | 91 | ||
75 | // --------------------------------------------------------------------------- | 92 | // --------------------------------------------------------------------------- |
76 | 93 | ||
77 | async init () { | 94 | async init () { |
78 | this.translationsPromise = TranslationsManager.getServerTranslations(window.location.origin, navigator.language) | 95 | this.translationsPromise = TranslationsManager.getServerTranslations(window.location.origin, navigator.language) |
79 | this.PeertubePlayerManagerModulePromise = import('../../assets/player/peertube-player-manager') | 96 | this.PeerTubePlayerManagerModulePromise = import('../../assets/player/peertube-player') |
80 | 97 | ||
81 | // Issue when we parsed config from HTML, fallback to API | 98 | // Issue when we parsed config from HTML, fallback to API |
82 | if (!this.config) { | 99 | if (!this.config) { |
@@ -90,7 +107,7 @@ export class PeerTubeEmbed { | |||
90 | 107 | ||
91 | if (!videoId) return | 108 | if (!videoId) return |
92 | 109 | ||
93 | return this.loadVideoAndBuildPlayer({ uuid: videoId, autoplayFromPreviousVideo: false, forceAutoplay: false }) | 110 | return this.loadVideoAndBuildPlayer({ uuid: videoId, forceAutoplay: false }) |
94 | } | 111 | } |
95 | 112 | ||
96 | private async initPlaylist () { | 113 | private async initPlaylist () { |
@@ -125,7 +142,7 @@ export class PeerTubeEmbed { | |||
125 | } | 142 | } |
126 | 143 | ||
127 | private initializeApi () { | 144 | private initializeApi () { |
128 | if (this.playerManagerOptions.hasAPIEnabled()) { | 145 | if (this.playerOptionsBuilder.hasAPIEnabled()) { |
129 | if (this.api) { | 146 | if (this.api) { |
130 | this.api.reInit() | 147 | this.api.reInit() |
131 | return | 148 | return |
@@ -147,7 +164,7 @@ export class PeerTubeEmbed { | |||
147 | 164 | ||
148 | this.playlistTracker.setCurrentElement(next) | 165 | this.playlistTracker.setCurrentElement(next) |
149 | 166 | ||
150 | return this.loadVideoAndBuildPlayer({ uuid: next.video.uuid, autoplayFromPreviousVideo: true, forceAutoplay: false }) | 167 | return this.loadVideoAndBuildPlayer({ uuid: next.video.uuid, forceAutoplay: false }) |
151 | } | 168 | } |
152 | 169 | ||
153 | async playPreviousPlaylistVideo () { | 170 | async playPreviousPlaylistVideo () { |
@@ -159,7 +176,7 @@ export class PeerTubeEmbed { | |||
159 | 176 | ||
160 | this.playlistTracker.setCurrentElement(previous) | 177 | this.playlistTracker.setCurrentElement(previous) |
161 | 178 | ||
162 | await this.loadVideoAndBuildPlayer({ uuid: previous.video.uuid, autoplayFromPreviousVideo: true, forceAutoplay: false }) | 179 | await this.loadVideoAndBuildPlayer({ uuid: previous.video.uuid, forceAutoplay: false }) |
163 | } | 180 | } |
164 | 181 | ||
165 | getCurrentPlaylistPosition () { | 182 | getCurrentPlaylistPosition () { |
@@ -170,123 +187,124 @@ export class PeerTubeEmbed { | |||
170 | 187 | ||
171 | private async loadVideoAndBuildPlayer (options: { | 188 | private async loadVideoAndBuildPlayer (options: { |
172 | uuid: string | 189 | uuid: string |
173 | autoplayFromPreviousVideo: boolean | ||
174 | forceAutoplay: boolean | 190 | forceAutoplay: boolean |
175 | }) { | 191 | }) { |
176 | const { uuid, autoplayFromPreviousVideo, forceAutoplay } = options | 192 | const { uuid, forceAutoplay } = options |
177 | 193 | ||
178 | try { | 194 | try { |
179 | const { videoResponse, captionsPromise } = await this.videoFetcher.loadVideo(uuid) | 195 | const { |
196 | videoResponse, | ||
197 | captionsPromise, | ||
198 | storyboardsPromise | ||
199 | } = await this.videoFetcher.loadVideo({ videoId: uuid, videoPassword: this.videoPassword }) | ||
180 | 200 | ||
181 | return this.buildVideoPlayer({ videoResponse, captionsPromise, autoplayFromPreviousVideo, forceAutoplay }) | 201 | return this.buildVideoPlayer({ videoResponse, captionsPromise, storyboardsPromise, forceAutoplay }) |
182 | } catch (err) { | 202 | } catch (err) { |
183 | this.playerHTML.displayError(err.message, await this.translationsPromise) | 203 | |
204 | if (await this.handlePasswordError(err)) this.loadVideoAndBuildPlayer({ ...options }) | ||
205 | else this.playerHTML.displayError(err.message, await this.translationsPromise) | ||
184 | } | 206 | } |
185 | } | 207 | } |
186 | 208 | ||
187 | private async buildVideoPlayer (options: { | 209 | private async buildVideoPlayer (options: { |
188 | videoResponse: Response | 210 | videoResponse: Response |
211 | storyboardsPromise: Promise<Response> | ||
189 | captionsPromise: Promise<Response> | 212 | captionsPromise: Promise<Response> |
190 | autoplayFromPreviousVideo: boolean | ||
191 | forceAutoplay: boolean | 213 | forceAutoplay: boolean |
192 | }) { | 214 | }) { |
193 | const { videoResponse, captionsPromise, autoplayFromPreviousVideo, forceAutoplay } = options | 215 | const { videoResponse, captionsPromise, storyboardsPromise, forceAutoplay } = options |
194 | |||
195 | this.resetPlayerElement() | ||
196 | 216 | ||
197 | const videoInfoPromise = videoResponse.json() | 217 | const videoInfoPromise = videoResponse.json() |
198 | .then(async (videoInfo: VideoDetails) => { | 218 | .then(async (videoInfo: VideoDetails) => { |
199 | this.playerManagerOptions.loadParams(this.config, videoInfo) | 219 | this.playerOptionsBuilder.loadParams(this.config, videoInfo) |
200 | 220 | ||
201 | if (!autoplayFromPreviousVideo && !this.playerManagerOptions.hasAutoplay()) { | ||
202 | this.playerHTML.buildPlaceholder(videoInfo) | ||
203 | } | ||
204 | const live = videoInfo.isLive | 221 | const live = videoInfo.isLive |
205 | ? await this.videoFetcher.loadLive(videoInfo) | 222 | ? await this.videoFetcher.loadLive(videoInfo) |
206 | : undefined | 223 | : undefined |
207 | 224 | ||
208 | const videoFileToken = videoRequiresAuth(videoInfo) | 225 | const videoFileToken = videoRequiresFileToken(videoInfo) |
209 | ? await this.videoFetcher.loadVideoToken(videoInfo) | 226 | ? await this.videoFetcher.loadVideoToken(videoInfo, this.videoPassword) |
210 | : undefined | 227 | : undefined |
211 | 228 | ||
212 | return { live, video: videoInfo, videoFileToken } | 229 | return { live, video: videoInfo, videoFileToken } |
213 | }) | 230 | }) |
214 | 231 | ||
215 | const [ { video, live, videoFileToken }, translations, captionsResponse, PeertubePlayerManagerModule ] = await Promise.all([ | 232 | const [ |
233 | { video, live, videoFileToken }, | ||
234 | translations, | ||
235 | captionsResponse, | ||
236 | storyboardsResponse | ||
237 | ] = await Promise.all([ | ||
216 | videoInfoPromise, | 238 | videoInfoPromise, |
217 | this.translationsPromise, | 239 | this.translationsPromise, |
218 | captionsPromise, | 240 | captionsPromise, |
219 | this.PeertubePlayerManagerModulePromise | 241 | storyboardsPromise, |
242 | this.buildPlayerIfNeeded() | ||
220 | ]) | 243 | ]) |
221 | 244 | ||
222 | await this.peertubePlugin.loadPlugins(this.config, translations) | 245 | // If already played, we are in a playlist so we don't want to display the poster between videos |
246 | if (!this.alreadyPlayed) { | ||
247 | this.peertubePlayer.setPoster(window.location.origin + video.previewPath) | ||
248 | } | ||
249 | |||
250 | const playlist = this.playlistTracker | ||
251 | ? { | ||
252 | onVideoUpdate: (uuid: string) => this.loadVideoAndBuildPlayer({ uuid, forceAutoplay: false }), | ||
223 | 253 | ||
224 | const PlayerManager: typeof PeertubePlayerManager = PeertubePlayerManagerModule.PeertubePlayerManager | 254 | playlistTracker: this.playlistTracker, |
255 | playNext: () => this.playNextPlaylistVideo(), | ||
256 | playPrevious: () => this.playPreviousPlaylistVideo() | ||
257 | } | ||
258 | : undefined | ||
225 | 259 | ||
226 | const playerOptions = await this.playerManagerOptions.getPlayerOptions({ | 260 | const loadOptions = await this.playerOptionsBuilder.getPlayerLoadOptions({ |
227 | video, | 261 | video, |
228 | captionsResponse, | 262 | captionsResponse, |
229 | autoplayFromPreviousVideo, | ||
230 | translations, | 263 | translations, |
231 | serverConfig: this.config, | ||
232 | 264 | ||
233 | authorizationHeader: () => this.http.getHeaderTokenValue(), | 265 | storyboardsResponse, |
234 | videoFileToken: () => videoFileToken, | ||
235 | 266 | ||
236 | onVideoUpdate: (uuid: string) => this.loadVideoAndBuildPlayer({ uuid, autoplayFromPreviousVideo: true, forceAutoplay: false }), | 267 | videoFileToken: () => videoFileToken, |
268 | videoPassword: () => this.videoPassword, | ||
269 | requiresPassword: this.requiresPassword, | ||
237 | 270 | ||
238 | playlistTracker: this.playlistTracker, | 271 | playlist, |
239 | playNextPlaylistVideo: () => this.playNextPlaylistVideo(), | ||
240 | playPreviousPlaylistVideo: () => this.playPreviousPlaylistVideo(), | ||
241 | 272 | ||
242 | live, | 273 | live, |
243 | forceAutoplay | 274 | forceAutoplay, |
275 | alreadyPlayed: this.alreadyPlayed | ||
244 | }) | 276 | }) |
277 | await this.peertubePlayer.load(loadOptions) | ||
245 | 278 | ||
246 | this.player = await PlayerManager.initialize(this.playerManagerOptions.getMode(), playerOptions, (player: videojs.Player) => { | 279 | if (!this.alreadyInitialized) { |
247 | this.player = player | 280 | this.player = this.peertubePlayer.getPlayer(); |
248 | }) | ||
249 | 281 | ||
250 | this.player.on('customError', (event: any, data: any) => { | 282 | (window as any)['videojsPlayer'] = this.player |
251 | const message = data?.err?.message || '' | ||
252 | if (!message.includes('from xs param')) return | ||
253 | 283 | ||
254 | this.player.dispose() | 284 | this.buildCSS() |
255 | this.playerHTML.removePlayerElement() | 285 | this.initializeApi() |
256 | this.playerHTML.displayError('This video is not available because the remote instance is not responding.', translations) | 286 | } |
257 | }); | ||
258 | |||
259 | (window as any)['videojsPlayer'] = this.player | ||
260 | |||
261 | this.buildCSS() | ||
262 | this.buildPlayerDock(video) | ||
263 | this.initializeApi() | ||
264 | 287 | ||
265 | this.playerHTML.removePlaceholder() | 288 | this.alreadyInitialized = true |
266 | 289 | ||
267 | if (this.isPlaylistEmbed()) { | 290 | this.player.one('play', () => { |
268 | await this.buildPlayerPlaylistUpnext() | 291 | this.alreadyPlayed = true |
292 | }) | ||
269 | 293 | ||
270 | this.player.playlist().updateSelected() | 294 | if (this.videoPassword) this.playerHTML.removeVideoPasswordBlock() |
271 | |||
272 | this.player.on('stopped', () => { | ||
273 | this.playNextPlaylistVideo() | ||
274 | }) | ||
275 | } | ||
276 | 295 | ||
277 | if (video.isLive) { | 296 | if (video.isLive) { |
278 | this.liveManager.listenForChanges({ | 297 | this.liveManager.listenForChanges({ |
279 | video, | 298 | video, |
280 | onPublishedVideo: () => { | 299 | onPublishedVideo: () => { |
281 | this.liveManager.stopListeningForChanges(video) | 300 | this.liveManager.stopListeningForChanges(video) |
282 | this.loadVideoAndBuildPlayer({ uuid: video.uuid, autoplayFromPreviousVideo: false, forceAutoplay: true }) | 301 | this.loadVideoAndBuildPlayer({ uuid: video.uuid, forceAutoplay: true }) |
283 | } | 302 | } |
284 | }) | 303 | }) |
285 | 304 | ||
286 | if (video.state.id === VideoState.WAITING_FOR_LIVE || video.state.id === VideoState.LIVE_ENDED) { | 305 | if (video.state.id === VideoState.WAITING_FOR_LIVE || video.state.id === VideoState.LIVE_ENDED) { |
287 | this.liveManager.displayInfo({ state: video.state.id, translations }) | 306 | this.liveManager.displayInfo({ state: video.state.id, translations }) |
288 | 307 | this.peertubePlayer.disable() | |
289 | this.disablePlayer() | ||
290 | } else { | 308 | } else { |
291 | this.correctlyHandleLiveEnding(translations) | 309 | this.correctlyHandleLiveEnding(translations) |
292 | } | 310 | } |
@@ -295,74 +313,15 @@ export class PeerTubeEmbed { | |||
295 | this.peertubePlugin.getPluginsManager().runHook('action:embed.player.loaded', undefined, { player: this.player, videojs, video }) | 313 | this.peertubePlugin.getPluginsManager().runHook('action:embed.player.loaded', undefined, { player: this.player, videojs, video }) |
296 | } | 314 | } |
297 | 315 | ||
298 | private resetPlayerElement () { | ||
299 | if (this.player) { | ||
300 | this.player.dispose() | ||
301 | this.player = undefined | ||
302 | } | ||
303 | |||
304 | const playerElement = document.createElement('video') | ||
305 | playerElement.className = 'video-js vjs-peertube-skin' | ||
306 | playerElement.setAttribute('playsinline', 'true') | ||
307 | |||
308 | this.playerHTML.setPlayerElement(playerElement) | ||
309 | this.playerHTML.addPlayerElementToDOM() | ||
310 | } | ||
311 | |||
312 | private async buildPlayerPlaylistUpnext () { | ||
313 | const translations = await this.translationsPromise | ||
314 | |||
315 | this.player.upnext({ | ||
316 | timeout: 10000, // 10s | ||
317 | headText: peertubeTranslate('Up Next', translations), | ||
318 | cancelText: peertubeTranslate('Cancel', translations), | ||
319 | suspendedText: peertubeTranslate('Autoplay is suspended', translations), | ||
320 | getTitle: () => this.playlistTracker.nextVideoTitle(), | ||
321 | next: () => this.playNextPlaylistVideo(), | ||
322 | condition: () => !!this.playlistTracker.getNextPlaylistElement(), | ||
323 | suspended: () => false | ||
324 | }) | ||
325 | } | ||
326 | |||
327 | private buildPlayerDock (videoInfo: VideoDetails) { | ||
328 | if (!this.playerManagerOptions.hasControls()) return | ||
329 | |||
330 | // On webtorrent fallback, player may have been disposed | ||
331 | if (!this.player.player_) return | ||
332 | |||
333 | const title = this.playerManagerOptions.hasTitle() | ||
334 | ? videoInfo.name | ||
335 | : undefined | ||
336 | |||
337 | const description = this.playerManagerOptions.hasWarningTitle() && this.playerManagerOptions.hasP2PEnabled() | ||
338 | ? '<span class="text">' + peertubeTranslate('Watching this video may reveal your IP address to others.') + '</span>' | ||
339 | : undefined | ||
340 | |||
341 | if (!title && !description) return | ||
342 | |||
343 | const availableAvatars = videoInfo.channel.avatars.filter(a => a.width < 50) | ||
344 | const avatar = availableAvatars.length !== 0 | ||
345 | ? availableAvatars[0] | ||
346 | : undefined | ||
347 | |||
348 | this.player.peertubeDock({ | ||
349 | title, | ||
350 | description, | ||
351 | avatarUrl: title && avatar | ||
352 | ? avatar.path | ||
353 | : undefined | ||
354 | }) | ||
355 | } | ||
356 | |||
357 | private buildCSS () { | 316 | private buildCSS () { |
358 | const body = document.getElementById('custom-css') | 317 | const body = document.getElementById('custom-css') |
359 | 318 | ||
360 | if (this.playerManagerOptions.hasBigPlayBackgroundColor()) { | 319 | if (this.playerOptionsBuilder.hasBigPlayBackgroundColor()) { |
361 | body.style.setProperty('--embedBigPlayBackgroundColor', this.playerManagerOptions.getBigPlayBackgroundColor()) | 320 | body.style.setProperty('--embedBigPlayBackgroundColor', this.playerOptionsBuilder.getBigPlayBackgroundColor()) |
362 | } | 321 | } |
363 | 322 | ||
364 | if (this.playerManagerOptions.hasForegroundColor()) { | 323 | if (this.playerOptionsBuilder.hasForegroundColor()) { |
365 | body.style.setProperty('--embedForegroundColor', this.playerManagerOptions.getForegroundColor()) | 324 | body.style.setProperty('--embedForegroundColor', this.playerOptionsBuilder.getForegroundColor()) |
366 | } | 325 | } |
367 | } | 326 | } |
368 | 327 | ||
@@ -384,23 +343,52 @@ export class PeerTubeEmbed { | |||
384 | // Display the live ended information | 343 | // Display the live ended information |
385 | this.liveManager.displayInfo({ state: VideoState.LIVE_ENDED, translations }) | 344 | this.liveManager.displayInfo({ state: VideoState.LIVE_ENDED, translations }) |
386 | 345 | ||
387 | this.disablePlayer() | 346 | this.peertubePlayer.disable() |
388 | }) | 347 | }) |
389 | } | 348 | } |
390 | 349 | ||
391 | private disablePlayer () { | 350 | private async handlePasswordError (err: PeerTubeServerError) { |
392 | if (this.player.isFullscreen()) { | 351 | let incorrectPassword: boolean = null |
393 | this.player.exitFullscreen() | 352 | if (err.serverCode === ServerErrorCode.VIDEO_REQUIRES_PASSWORD) incorrectPassword = false |
394 | } | 353 | else if (err.serverCode === ServerErrorCode.INCORRECT_VIDEO_PASSWORD) incorrectPassword = true |
395 | 354 | ||
396 | // Disable player | 355 | if (incorrectPassword === null) return false |
397 | this.player.hasStarted(false) | ||
398 | this.player.removeClass('vjs-has-autoplay') | ||
399 | this.player.bigPlayButton.hide(); | ||
400 | 356 | ||
401 | (this.player.el() as HTMLElement).style.pointerEvents = 'none' | 357 | this.requiresPassword = true |
358 | this.videoPassword = await this.playerHTML.askVideoPassword({ | ||
359 | incorrectPassword, | ||
360 | translations: await this.translationsPromise | ||
361 | }) | ||
362 | return true | ||
402 | } | 363 | } |
403 | 364 | ||
365 | private async buildPlayerIfNeeded () { | ||
366 | if (this.peertubePlayer) { | ||
367 | this.peertubePlayer.enable() | ||
368 | |||
369 | return | ||
370 | } | ||
371 | |||
372 | const playerElement = document.createElement('video') | ||
373 | playerElement.className = 'video-js vjs-peertube-skin' | ||
374 | playerElement.setAttribute('playsinline', 'true') | ||
375 | |||
376 | this.playerHTML.setPlayerElement(playerElement) | ||
377 | this.playerHTML.addPlayerElementToDOM() | ||
378 | |||
379 | const [ { PeerTubePlayer } ] = await Promise.all([ | ||
380 | this.PeerTubePlayerManagerModulePromise, | ||
381 | this.peertubePlugin.loadPlugins(this.config, await this.translationsPromise) | ||
382 | ]) | ||
383 | |||
384 | const constructorOptions = this.playerOptionsBuilder.getPlayerConstructorOptions({ | ||
385 | serverConfig: this.config, | ||
386 | authorizationHeader: () => this.http.getHeaderTokenValue() | ||
387 | }) | ||
388 | this.peertubePlayer = new PeerTubePlayer(constructorOptions) | ||
389 | |||
390 | this.player = this.peertubePlayer.getPlayer() | ||
391 | } | ||
404 | } | 392 | } |
405 | 393 | ||
406 | PeerTubeEmbed.main() | 394 | PeerTubeEmbed.main() |