Add plugin hooks/placeholder to share modal

This commit is contained in:
Chocobozzz 2022-08-11 15:28:11 +02:00
parent 2a95b88477
commit de61544582
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
9 changed files with 149 additions and 56 deletions

View File

@ -145,15 +145,15 @@ export class VideoBlockListComponent extends RestTable implements OnInit {
} }
getVideoEmbed (entry: VideoBlacklist) { getVideoEmbed (entry: VideoBlacklist) {
return buildVideoOrPlaylistEmbed( return buildVideoOrPlaylistEmbed({
decorateVideoLink({ embedUrl: decorateVideoLink({
url: buildVideoEmbedLink(entry.video, environment.originServerUrl), url: buildVideoEmbedLink(entry.video, environment.originServerUrl),
title: false, title: false,
warningTitle: false warningTitle: false
}), }),
entry.video.name embedTitle: entry.video.name
) })
} }
protected reloadData () { protected reloadData () {

View File

@ -21,6 +21,6 @@ export class EmbedMarkupComponent implements CustomMarkupComponent, OnInit {
? buildVideoEmbedLink({ uuid: this.uuid }, environment.originServerUrl) ? buildVideoEmbedLink({ uuid: this.uuid }, environment.originServerUrl)
: buildPlaylistEmbedLink({ 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 })
} }
} }

View File

@ -20,15 +20,15 @@ export class EmbedComponent implements OnInit {
} }
ngOnInit () { ngOnInit () {
const html = buildVideoOrPlaylistEmbed( const html = buildVideoOrPlaylistEmbed({
decorateVideoLink({ embedUrl: decorateVideoLink({
url: buildVideoEmbedLink(this.video, environment.originServerUrl), url: buildVideoEmbedLink(this.video, environment.originServerUrl),
title: false, title: false,
warningTitle: false warningTitle: false
}), }),
this.video.name embedTitle: this.video.name
) })
this.embedHTML = this.sanitizer.bypassSecurityTrustHtml(html) this.embedHTML = this.sanitizer.bypassSecurityTrustHtml(html)
} }

View File

@ -25,7 +25,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="nav-content"> <div class="nav-content">
<my-input-text [value]="getPlaylistUrl()" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-text> <my-input-text [value]="playlistUrl" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-text>
</div> </div>
</ng-template> </ng-template>
</ng-container> </ng-container>
@ -35,7 +35,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="nav-content"> <div class="nav-content">
<qrcode [qrdata]="getPlaylistUrl()" [width]="256" level="Q"></qrcode> <qrcode [qrdata]="playlistUrl" [width]="256" level="Q"></qrcode>
</div> </div>
</ng-template> </ng-template>
</ng-container> </ng-container>
@ -46,7 +46,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="nav-content"> <div class="nav-content">
<my-input-text <my-input-text
[value]="customizations.onlyEmbedUrl ? getPlaylistEmbedUrl() : getPlaylistIframeCode()" (change)="updateEmbedCode()" [value]="customizations.onlyEmbedUrl ? playlistEmbedUrl : playlistEmbedHTML" (change)="onUpdate()"
[withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"
></my-input-text> ></my-input-text>
@ -54,7 +54,7 @@
The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites). The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites).
</div> </div>
<div class="embed" [innerHTML]="playlistEmbedHTML"></div> <div class="embed" [innerHTML]="playlistEmbedSafeHTML"></div>
</div> </div>
</ng-template> </ng-template>
</ng-container> </ng-container>
@ -67,7 +67,7 @@
<div class="form-group" *ngIf="video"> <div class="form-group" *ngIf="video">
<my-peertube-checkbox <my-peertube-checkbox
inputName="includeVideoInPlaylist" [(ngModel)]="includeVideoInPlaylist" inputName="includeVideoInPlaylist" [(ngModel)]="customizations.includeVideoInPlaylist"
i18n-labelText labelText="Share the playlist at this video position" i18n-labelText labelText="Share the playlist at this video position"
></my-peertube-checkbox> ></my-peertube-checkbox>
</div> </div>
@ -80,6 +80,7 @@
></my-peertube-checkbox> ></my-peertube-checkbox>
</div> </div>
<my-plugin-placeholder pluginId="share-modal-playlist-settings"></my-plugin-placeholder>
</div> </div>
</div> </div>
@ -102,7 +103,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="nav-content"> <div class="nav-content">
<my-input-text [value]="getVideoUrl()" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-text> <my-input-text [value]="videoUrl" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-text>
</div> </div>
</ng-template> </ng-template>
</ng-container> </ng-container>
@ -112,7 +113,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="nav-content"> <div class="nav-content">
<qrcode [qrdata]="getVideoUrl()" [width]="256" level="Q"></qrcode> <qrcode [qrdata]="videoUrl" [width]="256" level="Q"></qrcode>
</div> </div>
</ng-template> </ng-template>
</ng-container> </ng-container>
@ -123,7 +124,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="nav-content"> <div class="nav-content">
<my-input-text <my-input-text
[value]="customizations.onlyEmbedUrl ? getVideoEmbedUrl() : getVideoIframeCode()" (ngModelChange)="updateEmbedCode()" [value]="customizations.onlyEmbedUrl ? videoEmbedUrl : videoEmbedHTML" (ngModelChange)="onUpdate()"
[withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"
></my-input-text> ></my-input-text>
@ -131,7 +132,7 @@
The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites). The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites).
</div> </div>
<div class="embed" [innerHTML]="videoEmbedHTML"></div> <div class="embed" [innerHTML]="videoEmbedSafeHTML"></div>
</div> </div>
</ng-template> </ng-template>
</ng-container> </ng-container>
@ -176,6 +177,8 @@
i18n-labelText labelText="Only display embed URL" i18n-labelText labelText="Only display embed URL"
></my-peertube-checkbox> ></my-peertube-checkbox>
</div> </div>
<my-plugin-placeholder pluginId="share-modal-video-settings"></my-plugin-placeholder>
</div> </div>
<div class="advanced-filters collapse-transition" [ngbCollapse]="isAdvancedCustomizationCollapsed"> <div class="advanced-filters collapse-transition" [ngbCollapse]="isAdvancedCustomizationCollapsed">

View File

@ -1,6 +1,6 @@
import { Component, ElementRef, Input, ViewChild } from '@angular/core' import { Component, ElementRef, Input, ViewChild } from '@angular/core'
import { DomSanitizer, SafeHtml } from '@angular/platform-browser' 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 { VideoDetails } from '@app/shared/shared-main'
import { VideoPlaylist } from '@app/shared/shared-video-playlist' import { VideoPlaylist } from '@app/shared/shared-video-playlist'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
@ -29,6 +29,8 @@ type Customizations = {
warningTitle: boolean warningTitle: boolean
controlBar: boolean controlBar: boolean
peertubeLink: boolean peertubeLink: boolean
includeVideoInPlaylist: boolean
} }
type TabId = 'url' | 'qrcode' | 'embed' type TabId = 'url' | 'qrcode' | 'embed'
@ -51,15 +53,23 @@ export class VideoShareComponent {
customizations: Customizations customizations: Customizations
isAdvancedCustomizationCollapsed = true isAdvancedCustomizationCollapsed = true
includeVideoInPlaylist = false
playlistEmbedHTML: SafeHtml videoUrl: string
videoEmbedHTML: SafeHtml playlistUrl: string
videoEmbedUrl: string
playlistEmbedUrl: string
videoEmbedHTML: string
videoEmbedSafeHTML: SafeHtml
playlistEmbedHTML: string
playlistEmbedSafeHTML: SafeHtml
constructor ( constructor (
private modalService: NgbModal, private modalService: NgbModal,
private sanitizer: DomSanitizer, private sanitizer: DomSanitizer,
private server: ServerService private server: ServerService,
private hooks: HooksService
) { } ) { }
show (currentVideoTimestamp?: number, currentPlaylistPosition?: number) { show (currentVideoTimestamp?: number, currentPlaylistPosition?: number) {
@ -89,7 +99,9 @@ export class VideoShareComponent {
title: true, title: true,
warningTitle: true, warningTitle: true,
controlBar: true, controlBar: true,
peertubeLink: true peertubeLink: true,
includeVideoInPlaylist: false
}, { }, {
set: (target, prop, value) => { set: (target, prop, value) => {
target[prop] = value target[prop] = value
@ -99,7 +111,7 @@ export class VideoShareComponent {
this.customizations.warningTitle = value this.customizations.warningTitle = value
} }
this.updateEmbedCode() this.onUpdate()
return true return true
} }
@ -107,50 +119,101 @@ export class VideoShareComponent {
this.playlistPosition = currentPlaylistPosition 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 () { getVideoUrl () {
const url = this.customizations.originUrl const url = this.customizations.originUrl
? this.video.url ? this.video.url
: buildVideoLink(this.video, window.location.origin) : buildVideoLink(this.video, window.location.origin)
return decorateVideoLink({ return this.hooks.wrapFun(
url, decorateVideoLink,
{ url, ...this.getVideoOptions(false) },
...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 () { getPlaylistUrl () {
const url = buildPlaylistLink(this.playlist) 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 () { getPlaylistEmbedUrl () {
if (this.playlist) this.playlistEmbedHTML = this.sanitizer.bypassSecurityTrustHtml(this.getPlaylistIframeCode()) 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 () { notSecure () {
@ -181,7 +244,9 @@ export class VideoShareComponent {
return { return {
baseUrl, baseUrl,
playlistPosition: this.playlistPosition || undefined playlistPosition: this.playlistPosition && this.customizations.includeVideoInPlaylist
? this.playlistPosition
: undefined
} }
} }

View File

@ -142,7 +142,7 @@ export class ManagerOptionsBuilder {
icon: 'code', icon: 'code',
label: player.localize('Copy embed code'), label: player.localize('Copy embed code'),
listener: () => { listener: () => {
copyToClipboard(buildVideoOrPlaylistEmbed(commonOptions.embedUrl, commonOptions.embedTitle)) copyToClipboard(buildVideoOrPlaylistEmbed({ embedUrl: commonOptions.embedUrl, embedTitle: commonOptions.embedTitle }))
} }
} }
] ]

View File

@ -1,6 +1,11 @@
import { HTMLServerConfig, Video } from '@shared/models' 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') const iframe = document.createElement('iframe')
iframe.title = embedTitle iframe.title = embedTitle

View File

@ -72,6 +72,21 @@ export const clientFilterHookObject = {
'filter:login.instance-about-plugin-panels.create.result': true, 'filter:login.instance-about-plugin-panels.create.result': true,
'filter:signup.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 videojs options built for PeerTube player
'filter:internal.player.videojs.options.result': true '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 // Fired when the modal to download a video/caption is shown
'action:modal.video-download.shown': true, 'action:modal.video-download.shown': true,
// Fired when the modal to share a video/playlist is shown
'action:modal.share.shown': true,
// ####### Embed hooks ####### // ####### Embed hooks #######
// /!\ In embed scope, peertube helpers are not available // /!\ In embed scope, peertube helpers are not available

View File

@ -1 +1,4 @@
export type PluginElementPlaceholder = 'player-next' export type PluginElementPlaceholder =
'player-next' |
'share-modal-playlist-settings' |
'share-modal-video-settings'