1 import { Component, ElementRef, Input, ViewChild } from '@angular/core'
2 import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
3 import { ServerService } from '@app/core'
4 import { VideoDetails } from '@app/shared/shared-main'
5 import { VideoPlaylist } from '@app/shared/shared-video-playlist'
6 import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
7 import { buildVideoOrPlaylistEmbed } from '@root-helpers/video'
8 import { buildPlaylistLink, buildVideoLink, decoratePlaylistLink, decorateVideoLink } from '@shared/core-utils'
9 import { VideoCaption, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
11 type Customizations = {
12 startAtCheckbox: boolean
15 stopAtCheckbox: boolean
18 subtitleCheckbox: boolean
34 type TabId = 'url' | 'qrcode' | 'embed'
37 selector: 'my-video-share',
38 templateUrl: './video-share.component.html',
39 styleUrls: [ './video-share.component.scss' ]
41 export class VideoShareComponent {
42 @ViewChild('modal', { static: true }) modal: ElementRef
44 @Input() video: VideoDetails = null
45 @Input() videoCaptions: VideoCaption[] = []
46 @Input() playlist: VideoPlaylist = null
47 @Input() playlistPosition: number = null
49 activeVideoId: TabId = 'url'
50 activePlaylistId: TabId = 'url'
52 customizations: Customizations
53 isAdvancedCustomizationCollapsed = true
54 includeVideoInPlaylist = false
56 playlistEmbedHTML: SafeHtml
57 videoEmbedHTML: SafeHtml
60 private modalService: NgbModal,
61 private sanitizer: DomSanitizer,
62 private server: ServerService
65 show (currentVideoTimestamp?: number, currentPlaylistPosition?: number) {
67 if (this.videoCaptions && this.videoCaptions.length !== 0) {
68 subtitle = this.videoCaptions[0].language.id
71 this.customizations = new Proxy({
72 startAtCheckbox: false,
73 startAt: currentVideoTimestamp ? Math.floor(currentVideoTimestamp) : 0,
75 stopAtCheckbox: false,
76 stopAt: this.video?.duration,
78 subtitleCheckbox: false,
87 embedP2P: this.server.getHTMLConfig().defaults.p2p.embed.enabled,
94 set: (target, prop, value) => {
97 if (prop === 'embedP2P') {
98 // Auto enabled warning title if P2P is enabled
99 this.customizations.warningTitle = value
102 this.updateEmbedCode()
108 this.playlistPosition = currentPlaylistPosition
110 this.updateEmbedCode()
112 this.modalService.open(this.modal, { centered: true })
115 getVideoIframeCode () {
116 return buildVideoOrPlaylistEmbed(this.getVideoEmbedUrl(), this.video.name)
119 getVideoEmbedUrl () {
120 return decorateVideoLink({ url: this.video.embedUrl, ...this.getVideoOptions(true) })
123 getPlaylistEmbedUrl () {
124 return decoratePlaylistLink({ url: this.playlist.embedUrl, ...this.getPlaylistOptions() })
127 getPlaylistIframeCode () {
128 return buildVideoOrPlaylistEmbed(this.getPlaylistEmbedUrl(), this.playlist.displayName)
132 const url = this.customizations.originUrl
134 : buildVideoLink(this.video, window.location.origin)
136 return decorateVideoLink({
139 ...this.getVideoOptions(false)
144 const url = buildPlaylistLink(this.playlist)
145 if (!this.includeVideoInPlaylist) return url
147 return decoratePlaylistLink({ url, playlistPosition: this.playlistPosition })
151 if (this.playlist) this.playlistEmbedHTML = this.sanitizer.bypassSecurityTrustHtml(this.getPlaylistIframeCode())
153 if (this.video) this.videoEmbedHTML = this.sanitizer.bypassSecurityTrustHtml(this.getVideoIframeCode())
157 return window.location.protocol === 'http:'
160 isInVideoEmbedTab () {
161 return this.activeVideoId === 'embed'
164 isInPlaylistEmbedTab () {
165 return this.activePlaylistId === 'embed'
169 return this.video.isLocal
173 return this.video.privacy.id === VideoPrivacy.PRIVATE
176 isPrivatePlaylist () {
177 return this.playlist.privacy.id === VideoPlaylistPrivacy.PRIVATE
180 private getPlaylistOptions (baseUrl?: string) {
184 playlistPosition: this.playlistPosition || undefined
188 private getVideoOptions (forEmbed: boolean) {
189 const embedOptions = forEmbed
191 title: this.customizations.title,
192 warningTitle: this.customizations.warningTitle,
193 controlBar: this.customizations.controlBar,
194 peertubeLink: this.customizations.peertubeLink,
196 // If using default value, we don't need to specify it
197 p2p: this.customizations.embedP2P === this.server.getHTMLConfig().defaults.p2p.embed.enabled
199 : this.customizations.embedP2P
204 startTime: this.customizations.startAtCheckbox ? this.customizations.startAt : undefined,
205 stopTime: this.customizations.stopAtCheckbox ? this.customizations.stopAt : undefined,
207 subtitle: this.customizations.subtitleCheckbox ? this.customizations.subtitle : undefined,
209 loop: this.customizations.loop,
210 autoplay: this.customizations.autoplay,
211 muted: this.customizations.muted,