+
+ private async buildDock (videoInfo: VideoDetails, config: ServerConfig) {
+ if (!this.controls) return
+
+ // On webtorrent fallback, player may have been disposed
+ if (!this.player.player_) return
+
+ const title = this.title ? videoInfo.name : undefined
+
+ const description = config.tracker.enabled && this.warningTitle
+ ? '<span class="text">' + peertubeTranslate('Watching this video may reveal your IP address to others.') + '</span>'
+ : undefined
+
+ if (title || description) {
+ this.player.dock({
+ title,
+ description
+ })
+ }
+ }
+
+ private buildCSS () {
+ const body = document.getElementById('custom-css')
+
+ if (this.bigPlayBackgroundColor) {
+ body.style.setProperty('--embedBigPlayBackgroundColor', this.bigPlayBackgroundColor)
+ }
+
+ if (this.foregroundColor) {
+ body.style.setProperty('--embedForegroundColor', this.foregroundColor)
+ }
+ }
+
+ private async buildCaptions (serverTranslations: any, captionsResponse: Response): Promise<VideoJSCaption[]> {
+ if (captionsResponse.ok) {
+ const { data } = (await captionsResponse.json()) as ResultList<VideoCaption>
+
+ return data.map(c => ({
+ label: peertubeTranslate(c.language.label, serverTranslations),
+ language: c.language.id,
+ src: window.location.origin + c.captionPath
+ }))
+ }
+
+ return []
+ }
+
+ private loadPlaceholder (video: VideoDetails) {
+ const placeholder = this.getPlaceholderElement()
+
+ const url = window.location.origin + video.previewPath
+ placeholder.style.backgroundImage = `url("${url}")`
+ placeholder.style.display = 'block'
+ }
+
+ private removePlaceholder () {
+ const placeholder = this.getPlaceholderElement()
+ placeholder.style.display = 'none'
+ }
+
+ private getPlaceholderElement () {
+ return document.getElementById('placeholder-preview')
+ }
+
+ private setHeadersFromTokens () {
+ this.headers.set('Authorization', `${this.userTokens.tokenType} ${this.userTokens.accessToken}`)
+ }
+
+ private removeTokensFromHeaders () {
+ this.headers.delete('Authorization')
+ }
+
+ private getResourceId () {
+ const urlParts = window.location.pathname.split('/')
+ return urlParts[ urlParts.length - 1 ]
+ }
+
+ private isPlaylistEmbed () {
+ return window.location.pathname.split('/')[1] === 'video-playlists'
+ }
+
+ private async ensurePluginsAreLoaded (config: ServerConfig, translations?: { [ id: string ]: string }) {
+ if (config.plugin.registered.length === 0) return
+
+ for (const plugin of config.plugin.registered) {
+ for (const key of Object.keys(plugin.clientScripts)) {
+ const clientScript = plugin.clientScripts[key]
+
+ if (clientScript.scopes.includes('embed') === false) continue
+
+ const script = `/plugins/${plugin.name}/${plugin.version}/client-scripts/${clientScript.script}`
+
+ if (this.loadedScripts.has(script)) continue
+
+ const pluginInfo = {
+ plugin,
+ clientScript: {
+ script,
+ scopes: clientScript.scopes
+ },
+ pluginType: PluginType.PLUGIN,
+ isTheme: false
+ }
+
+ await loadPlugin({
+ hooks: this.peertubeHooks,
+ pluginInfo,
+ peertubeHelpersFactory: _ => this.buildPeerTubeHelpers(translations)
+ })
+ }
+ }
+ }
+
+ private buildPeerTubeHelpers (translations?: { [ id: string ]: string }): RegisterClientHelpers {
+ function unimplemented (): any {
+ throw new Error('This helper is not implemented in embed.')
+ }
+
+ return {
+ getBaseStaticRoute: unimplemented,
+
+ getSettings: unimplemented,
+
+ isLoggedIn: unimplemented,
+
+ notifier: {
+ info: unimplemented,
+ error: unimplemented,
+ success: unimplemented
+ },
+
+ showModal: unimplemented,
+
+ getServerConfig: unimplemented,
+
+ markdownRenderer: {
+ textMarkdownToHTML: unimplemented,
+ enhancedMarkdownToHTML: unimplemented
+ },
+
+ translate: (value: string) => {
+ return Promise.resolve(peertubeTranslate(value, translations))
+ }
+ }
+ }
+
+ private runHook <T> (hookName: ClientHookName, result?: T, params?: any): Promise<T> {
+ return runHook(this.peertubeHooks, hookName, result, params)
+ }