diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts index 033305a2b..8d67e9beb 100644 --- a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts +++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts @@ -145,15 +145,15 @@ export class VideoBlockListComponent extends RestTable implements OnInit { } getVideoEmbed (entry: VideoBlacklist) { - return buildVideoOrPlaylistEmbed( - decorateVideoLink({ + return buildVideoOrPlaylistEmbed({ + embedUrl: decorateVideoLink({ url: buildVideoEmbedLink(entry.video, environment.originServerUrl), title: false, warningTitle: false }), - entry.video.name - ) + embedTitle: entry.video.name + }) } protected reloadData () { diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/embed-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/embed-markup.component.ts index 955b0af18..0baf2428b 100644 --- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/embed-markup.component.ts +++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/embed-markup.component.ts @@ -21,6 +21,6 @@ export class EmbedMarkupComponent implements CustomMarkupComponent, OnInit { ? buildVideoEmbedLink({ uuid: this.uuid }, environment.originServerUrl) : buildPlaylistEmbedLink({ uuid: this.uuid }, environment.originServerUrl) - this.el.nativeElement.innerHTML = buildVideoOrPlaylistEmbed(link, this.uuid) + this.el.nativeElement.innerHTML = buildVideoOrPlaylistEmbed({ embedUrl: link, embedTitle: this.uuid }) } } diff --git a/client/src/app/shared/shared-main/video/embed.component.ts b/client/src/app/shared/shared-main/video/embed.component.ts index 123000834..43e350197 100644 --- a/client/src/app/shared/shared-main/video/embed.component.ts +++ b/client/src/app/shared/shared-main/video/embed.component.ts @@ -20,15 +20,15 @@ export class EmbedComponent implements OnInit { } ngOnInit () { - const html = buildVideoOrPlaylistEmbed( - decorateVideoLink({ + const html = buildVideoOrPlaylistEmbed({ + embedUrl: decorateVideoLink({ url: buildVideoEmbedLink(this.video, environment.originServerUrl), title: false, warningTitle: false }), - this.video.name - ) + embedTitle: this.video.name + }) this.embedHTML = this.sanitizer.bypassSecurityTrustHtml(html) } diff --git a/client/src/app/shared/shared-share-modal/video-share.component.html b/client/src/app/shared/shared-share-modal/video-share.component.html index b163d3581..f4d249b41 100644 --- a/client/src/app/shared/shared-share-modal/video-share.component.html +++ b/client/src/app/shared/shared-share-modal/video-share.component.html @@ -25,7 +25,7 @@ @@ -35,7 +35,7 @@ @@ -46,7 +46,7 @@ -
+
@@ -67,7 +67,7 @@
@@ -80,6 +80,7 @@ > + @@ -102,7 +103,7 @@ @@ -112,7 +113,7 @@ @@ -123,7 +124,7 @@ -
+
@@ -176,6 +177,8 @@ i18n-labelText labelText="Only display embed URL" > + +
diff --git a/client/src/app/shared/shared-share-modal/video-share.component.ts b/client/src/app/shared/shared-share-modal/video-share.component.ts index e0c98008c..e1db4a3b8 100644 --- a/client/src/app/shared/shared-share-modal/video-share.component.ts +++ b/client/src/app/shared/shared-share-modal/video-share.component.ts @@ -1,6 +1,6 @@ import { Component, ElementRef, Input, ViewChild } from '@angular/core' import { DomSanitizer, SafeHtml } from '@angular/platform-browser' -import { ServerService } from '@app/core' +import { HooksService, ServerService } from '@app/core' import { VideoDetails } from '@app/shared/shared-main' import { VideoPlaylist } from '@app/shared/shared-video-playlist' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' @@ -29,6 +29,8 @@ type Customizations = { warningTitle: boolean controlBar: boolean peertubeLink: boolean + + includeVideoInPlaylist: boolean } type TabId = 'url' | 'qrcode' | 'embed' @@ -51,15 +53,23 @@ export class VideoShareComponent { customizations: Customizations isAdvancedCustomizationCollapsed = true - includeVideoInPlaylist = false - playlistEmbedHTML: SafeHtml - videoEmbedHTML: SafeHtml + videoUrl: string + playlistUrl: string + + videoEmbedUrl: string + playlistEmbedUrl: string + + videoEmbedHTML: string + videoEmbedSafeHTML: SafeHtml + playlistEmbedHTML: string + playlistEmbedSafeHTML: SafeHtml constructor ( private modalService: NgbModal, private sanitizer: DomSanitizer, - private server: ServerService + private server: ServerService, + private hooks: HooksService ) { } show (currentVideoTimestamp?: number, currentPlaylistPosition?: number) { @@ -89,7 +99,9 @@ export class VideoShareComponent { title: true, warningTitle: true, controlBar: true, - peertubeLink: true + peertubeLink: true, + + includeVideoInPlaylist: false }, { set: (target, prop, value) => { target[prop] = value @@ -99,7 +111,7 @@ export class VideoShareComponent { this.customizations.warningTitle = value } - this.updateEmbedCode() + this.onUpdate() return true } @@ -107,50 +119,101 @@ export class VideoShareComponent { this.playlistPosition = currentPlaylistPosition - this.updateEmbedCode() + this.onUpdate() - this.modalService.open(this.modal, { centered: true }) + this.modalService.open(this.modal, { centered: true }).shown.subscribe(() => { + this.hooks.runAction('action:modal.share.shown', 'video-watch', { video: this.video, playlist: this.playlist }) + }) } - getVideoIframeCode () { - return buildVideoOrPlaylistEmbed(this.getVideoEmbedUrl(), this.video.name) - } - - getVideoEmbedUrl () { - return decorateVideoLink({ url: this.video.embedUrl, ...this.getVideoOptions(true) }) - } - - getPlaylistEmbedUrl () { - return decoratePlaylistLink({ url: this.playlist.embedUrl, ...this.getPlaylistOptions() }) - } - - getPlaylistIframeCode () { - return buildVideoOrPlaylistEmbed(this.getPlaylistEmbedUrl(), this.playlist.displayName) - } + // --------------------------------------------------------------------------- getVideoUrl () { const url = this.customizations.originUrl ? this.video.url : buildVideoLink(this.video, window.location.origin) - return decorateVideoLink({ - url, - - ...this.getVideoOptions(false) - }) + return this.hooks.wrapFun( + decorateVideoLink, + { url, ...this.getVideoOptions(false) }, + 'video-watch', + 'filter:share.video-url.build.params', + 'filter:share.video-url.build.result' + ) } + getVideoEmbedUrl () { + return this.hooks.wrapFun( + decorateVideoLink, + { url: this.video.embedUrl, ...this.getVideoOptions(true) }, + 'video-watch', + 'filter:share.video-embed-url.build.params', + 'filter:share.video-embed-url.build.result' + ) + } + + async getVideoIframeCode () { + return this.hooks.wrapFun( + buildVideoOrPlaylistEmbed, + { embedUrl: await this.getVideoEmbedUrl(), embedTitle: this.video.name }, + 'video-watch', + 'filter:share.video-embed-code.build.params', + 'filter:share.video-embed-code.build.result' + ) + } + + // --------------------------------------------------------------------------- + getPlaylistUrl () { const url = buildPlaylistLink(this.playlist) - if (!this.includeVideoInPlaylist) return url - return decoratePlaylistLink({ url, playlistPosition: this.playlistPosition }) + return this.hooks.wrapFun( + decoratePlaylistLink, + { url, ...this.getPlaylistOptions() }, + 'video-watch', + 'filter:share.video-playlist-url.build.params', + 'filter:share.video-playlist-url.build.result' + ) } - updateEmbedCode () { - if (this.playlist) this.playlistEmbedHTML = this.sanitizer.bypassSecurityTrustHtml(this.getPlaylistIframeCode()) + getPlaylistEmbedUrl () { + return this.hooks.wrapFun( + decoratePlaylistLink, + { url: this.playlist.embedUrl, ...this.getPlaylistOptions() }, + 'video-watch', + 'filter:share.video-playlist-embed-url.build.params', + 'filter:share.video-playlist-embed-url.build.result' + ) + } - if (this.video) this.videoEmbedHTML = this.sanitizer.bypassSecurityTrustHtml(this.getVideoIframeCode()) + async getPlaylistEmbedCode () { + return this.hooks.wrapFun( + buildVideoOrPlaylistEmbed, + { embedUrl: await this.getPlaylistEmbedUrl(), embedTitle: this.playlist.displayName }, + 'video-watch', + 'filter:share.video-playlist-embed-code.build.params', + 'filter:share.video-playlist-embed-code.build.result' + ) + } + + // --------------------------------------------------------------------------- + + async onUpdate () { + console.log('on update') + + if (this.playlist) { + this.playlistUrl = await this.getPlaylistUrl() + this.playlistEmbedUrl = await this.getPlaylistEmbedUrl() + this.playlistEmbedHTML = await this.getPlaylistEmbedCode() + this.playlistEmbedSafeHTML = this.sanitizer.bypassSecurityTrustHtml(this.playlistEmbedHTML) + } + + if (this.video) { + this.videoUrl = await this.getVideoUrl() + this.videoEmbedUrl = await this.getVideoEmbedUrl() + this.videoEmbedHTML = await this.getVideoIframeCode() + this.videoEmbedSafeHTML = this.sanitizer.bypassSecurityTrustHtml(this.videoEmbedHTML) + } } notSecure () { @@ -181,7 +244,9 @@ export class VideoShareComponent { return { baseUrl, - playlistPosition: this.playlistPosition || undefined + playlistPosition: this.playlistPosition && this.customizations.includeVideoInPlaylist + ? this.playlistPosition + : undefined } } diff --git a/client/src/assets/player/shared/manager-options/manager-options-builder.ts b/client/src/assets/player/shared/manager-options/manager-options-builder.ts index e454c719e..bc70bb12f 100644 --- a/client/src/assets/player/shared/manager-options/manager-options-builder.ts +++ b/client/src/assets/player/shared/manager-options/manager-options-builder.ts @@ -142,7 +142,7 @@ export class ManagerOptionsBuilder { icon: 'code', label: player.localize('Copy embed code'), listener: () => { - copyToClipboard(buildVideoOrPlaylistEmbed(commonOptions.embedUrl, commonOptions.embedTitle)) + copyToClipboard(buildVideoOrPlaylistEmbed({ embedUrl: commonOptions.embedUrl, embedTitle: commonOptions.embedTitle })) } } ] diff --git a/client/src/root-helpers/video.ts b/client/src/root-helpers/video.ts index 4290992aa..ba84e49ea 100644 --- a/client/src/root-helpers/video.ts +++ b/client/src/root-helpers/video.ts @@ -1,6 +1,11 @@ import { HTMLServerConfig, Video } from '@shared/models' -function buildVideoOrPlaylistEmbed (embedUrl: string, embedTitle: string) { +function buildVideoOrPlaylistEmbed (options: { + embedUrl: string + embedTitle: string +}) { + const { embedUrl, embedTitle } = options + const iframe = document.createElement('iframe') iframe.title = embedTitle diff --git a/shared/models/plugins/client/client-hook.model.ts b/shared/models/plugins/client/client-hook.model.ts index dda03124d..e6313b60e 100644 --- a/shared/models/plugins/client/client-hook.model.ts +++ b/shared/models/plugins/client/client-hook.model.ts @@ -72,6 +72,21 @@ export const clientFilterHookObject = { 'filter:login.instance-about-plugin-panels.create.result': true, 'filter:signup.instance-about-plugin-panels.create.result': true, + 'filter:share.video-embed-code.build.params': true, + 'filter:share.video-embed-code.build.result': true, + 'filter:share.video-playlist-embed-code.build.params': true, + 'filter:share.video-playlist-embed-code.build.result': true, + + 'filter:share.video-embed-url.build.params': true, + 'filter:share.video-embed-url.build.result': true, + 'filter:share.video-playlist-embed-url.build.params': true, + 'filter:share.video-playlist-embed-url.build.result': true, + + 'filter:share.video-url.build.params': true, + 'filter:share.video-url.build.result': true, + 'filter:share.video-playlist-url.build.params': true, + 'filter:share.video-playlist-url.build.result': true, + // Filter videojs options built for PeerTube player 'filter:internal.player.videojs.options.result': true } @@ -146,6 +161,8 @@ export const clientActionHookObject = { // Fired when the modal to download a video/caption is shown 'action:modal.video-download.shown': true, + // Fired when the modal to share a video/playlist is shown + 'action:modal.share.shown': true, // ####### Embed hooks ####### // /!\ In embed scope, peertube helpers are not available diff --git a/shared/models/plugins/client/plugin-element-placeholder.type.ts b/shared/models/plugins/client/plugin-element-placeholder.type.ts index 129099c62..7b8a2605b 100644 --- a/shared/models/plugins/client/plugin-element-placeholder.type.ts +++ b/shared/models/plugins/client/plugin-element-placeholder.type.ts @@ -1 +1,4 @@ -export type PluginElementPlaceholder = 'player-next' +export type PluginElementPlaceholder = + 'player-next' | + 'share-modal-playlist-settings' | + 'share-modal-video-settings'