]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/shared/shared-share-modal/video-share.component.ts
Merge branch 'release/5.1.0' into develop
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-share-modal / video-share.component.ts
1 import { Component, ElementRef, Input, ViewChild } from '@angular/core'
2 import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
3 import { HooksService, 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'
10
11 type Customizations = {
12 startAtCheckbox: boolean
13 startAt: number
14
15 stopAtCheckbox: boolean
16 stopAt: number
17
18 subtitleCheckbox: boolean
19 subtitle: string
20
21 loop: boolean
22 originUrl: boolean
23 autoplay: boolean
24 muted: boolean
25
26 embedP2P: boolean
27 onlyEmbedUrl: boolean
28 title: boolean
29 warningTitle: boolean
30 controlBar: boolean
31 peertubeLink: boolean
32 responsive: boolean
33
34 includeVideoInPlaylist: boolean
35 }
36
37 type TabId = 'url' | 'qrcode' | 'embed'
38
39 @Component({
40 selector: 'my-video-share',
41 templateUrl: './video-share.component.html',
42 styleUrls: [ './video-share.component.scss' ]
43 })
44 export class VideoShareComponent {
45 @ViewChild('modal', { static: true }) modal: ElementRef
46
47 @Input() video: VideoDetails = null
48 @Input() videoCaptions: VideoCaption[] = []
49 @Input() playlist: VideoPlaylist = null
50 @Input() playlistPosition: number = null
51
52 activeVideoId: TabId = 'url'
53 activePlaylistId: TabId = 'url'
54
55 customizations: Customizations
56 isAdvancedCustomizationCollapsed = true
57
58 videoUrl: string
59 playlistUrl: string
60
61 videoEmbedUrl: string
62 playlistEmbedUrl: string
63
64 videoEmbedHTML: string
65 videoEmbedSafeHTML: SafeHtml
66 playlistEmbedHTML: string
67 playlistEmbedSafeHTML: SafeHtml
68
69 constructor (
70 private modalService: NgbModal,
71 private sanitizer: DomSanitizer,
72 private server: ServerService,
73 private hooks: HooksService
74 ) { }
75
76 show (currentVideoTimestamp?: number, currentPlaylistPosition?: number) {
77 let subtitle: string
78 if (this.videoCaptions && this.videoCaptions.length !== 0) {
79 subtitle = this.videoCaptions[0].language.id
80 }
81
82 this.customizations = new Proxy({
83 startAtCheckbox: false,
84 startAt: currentVideoTimestamp ? Math.floor(currentVideoTimestamp) : 0,
85
86 stopAtCheckbox: false,
87 stopAt: this.video?.duration,
88
89 subtitleCheckbox: false,
90 subtitle,
91
92 loop: false,
93 originUrl: false,
94 autoplay: false,
95 muted: false,
96
97 // Embed options
98 embedP2P: this.server.getHTMLConfig().defaults.p2p.embed.enabled,
99 onlyEmbedUrl: false,
100 title: true,
101 warningTitle: true,
102 controlBar: true,
103 peertubeLink: true,
104 responsive: false,
105
106 includeVideoInPlaylist: false
107 }, {
108 set: (target, prop, value) => {
109 target[prop] = value
110
111 if (prop === 'embedP2P') {
112 // Auto enabled warning title if P2P is enabled
113 this.customizations.warningTitle = value
114 }
115
116 this.onUpdate()
117
118 return true
119 }
120 })
121
122 this.playlistPosition = currentPlaylistPosition
123
124 this.onUpdate()
125
126 this.modalService.open(this.modal, { centered: true }).shown.subscribe(() => {
127 this.hooks.runAction('action:modal.share.shown', 'video-watch', { video: this.video, playlist: this.playlist })
128 })
129 }
130
131 // ---------------------------------------------------------------------------
132
133 getVideoUrl () {
134 const url = this.customizations.originUrl
135 ? this.video.url
136 : buildVideoLink(this.video, window.location.origin)
137
138 return this.hooks.wrapFun(
139 decorateVideoLink,
140 { url, ...this.getVideoOptions(false) },
141 'video-watch',
142 'filter:share.video-url.build.params',
143 'filter:share.video-url.build.result'
144 )
145 }
146
147 getVideoEmbedUrl () {
148 return this.hooks.wrapFun(
149 decorateVideoLink,
150 { url: this.video.embedUrl, ...this.getVideoOptions(true) },
151 'video-watch',
152 'filter:share.video-embed-url.build.params',
153 'filter:share.video-embed-url.build.result'
154 )
155 }
156
157 async getVideoEmbedCode (options: { responsive: boolean }) {
158 const { responsive } = options
159 return this.hooks.wrapFun(
160 buildVideoOrPlaylistEmbed,
161 { embedUrl: await this.getVideoEmbedUrl(), embedTitle: this.video.name, responsive },
162 'video-watch',
163 'filter:share.video-embed-code.build.params',
164 'filter:share.video-embed-code.build.result'
165 )
166 }
167
168 // ---------------------------------------------------------------------------
169
170 getPlaylistUrl () {
171 const url = buildPlaylistLink(this.playlist)
172
173 return this.hooks.wrapFun(
174 decoratePlaylistLink,
175 { url, ...this.getPlaylistOptions() },
176 'video-watch',
177 'filter:share.video-playlist-url.build.params',
178 'filter:share.video-playlist-url.build.result'
179 )
180 }
181
182 getPlaylistEmbedUrl () {
183 return this.hooks.wrapFun(
184 decoratePlaylistLink,
185 { url: this.playlist.embedUrl, ...this.getPlaylistOptions() },
186 'video-watch',
187 'filter:share.video-playlist-embed-url.build.params',
188 'filter:share.video-playlist-embed-url.build.result'
189 )
190 }
191
192 async getPlaylistEmbedCode (options: { responsive: boolean }) {
193 const { responsive } = options
194 return this.hooks.wrapFun(
195 buildVideoOrPlaylistEmbed,
196 { embedUrl: await this.getPlaylistEmbedUrl(), embedTitle: this.playlist.displayName, responsive },
197 'video-watch',
198 'filter:share.video-playlist-embed-code.build.params',
199 'filter:share.video-playlist-embed-code.build.result'
200 )
201 }
202
203 // ---------------------------------------------------------------------------
204
205 async onUpdate () {
206 console.log('on update')
207
208 if (this.playlist) {
209 this.playlistUrl = await this.getPlaylistUrl()
210 this.playlistEmbedUrl = await this.getPlaylistEmbedUrl()
211 this.playlistEmbedHTML = await this.getPlaylistEmbedCode({ responsive: this.customizations.responsive })
212 this.playlistEmbedSafeHTML = this.sanitizer.bypassSecurityTrustHtml(await this.getPlaylistEmbedCode({ responsive: false }))
213 }
214
215 if (this.video) {
216 this.videoUrl = await this.getVideoUrl()
217 this.videoEmbedUrl = await this.getVideoEmbedUrl()
218 this.videoEmbedHTML = await this.getVideoEmbedCode({ responsive: this.customizations.responsive })
219 this.videoEmbedSafeHTML = this.sanitizer.bypassSecurityTrustHtml(await this.getVideoEmbedCode({ responsive: false }))
220 }
221 }
222
223 notSecure () {
224 return window.location.protocol === 'http:'
225 }
226
227 isInVideoEmbedTab () {
228 return this.activeVideoId === 'embed'
229 }
230
231 isInPlaylistEmbedTab () {
232 return this.activePlaylistId === 'embed'
233 }
234
235 isLocalVideo () {
236 return this.video.isLocal
237 }
238
239 isPrivateVideo () {
240 return this.video.privacy.id === VideoPrivacy.PRIVATE
241 }
242
243 isPrivatePlaylist () {
244 return this.playlist.privacy.id === VideoPlaylistPrivacy.PRIVATE
245 }
246
247 private getPlaylistOptions (baseUrl?: string) {
248 return {
249 baseUrl,
250
251 playlistPosition: this.playlistPosition && this.customizations.includeVideoInPlaylist
252 ? this.playlistPosition
253 : undefined
254 }
255 }
256
257 private getVideoOptions (forEmbed: boolean) {
258 const embedOptions = forEmbed
259 ? {
260 title: this.customizations.title,
261 warningTitle: this.customizations.warningTitle,
262 controlBar: this.customizations.controlBar,
263 peertubeLink: this.customizations.peertubeLink,
264
265 // If using default value, we don't need to specify it
266 p2p: this.customizations.embedP2P === this.server.getHTMLConfig().defaults.p2p.embed.enabled
267 ? undefined
268 : this.customizations.embedP2P
269 }
270 : {}
271
272 return {
273 startTime: this.customizations.startAtCheckbox ? this.customizations.startAt : undefined,
274 stopTime: this.customizations.stopAtCheckbox ? this.customizations.stopAt : undefined,
275
276 subtitle: this.customizations.subtitleCheckbox ? this.customizations.subtitle : undefined,
277
278 loop: this.customizations.loop,
279 autoplay: this.customizations.autoplay,
280 muted: this.customizations.muted,
281
282 ...embedOptions
283 }
284 }
285 }