aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/shared/shared-custom-markup/custom-markup-container.component.html2
-rw-r--r--client/src/app/shared/shared-custom-markup/custom-markup-container.component.ts13
-rw-r--r--client/src/app/shared/shared-custom-markup/custom-markup.service.ts36
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/button-markup.component.ts4
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts17
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/embed-markup.component.ts5
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/playlist-miniature-markup.component.ts13
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/shared/custom-markup.component.ts5
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/shared/index.ts1
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts13
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/videos-list-markup.component.ts13
11 files changed, 90 insertions, 32 deletions
diff --git a/client/src/app/shared/shared-custom-markup/custom-markup-container.component.html b/client/src/app/shared/shared-custom-markup/custom-markup-container.component.html
index 6bf2294a3..685efc9ab 100644
--- a/client/src/app/shared/shared-custom-markup/custom-markup-container.component.html
+++ b/client/src/app/shared/shared-custom-markup/custom-markup-container.component.html
@@ -1 +1 @@
<div class="custom-markup-container" #contentWrapper></div> <div [hidden]="!displayed" class="custom-markup-container" #contentWrapper></div>
diff --git a/client/src/app/shared/shared-custom-markup/custom-markup-container.component.ts b/client/src/app/shared/shared-custom-markup/custom-markup-container.component.ts
index 3d49c6768..4e802b14d 100644
--- a/client/src/app/shared/shared-custom-markup/custom-markup-container.component.ts
+++ b/client/src/app/shared/shared-custom-markup/custom-markup-container.component.ts
@@ -10,6 +10,8 @@ export class CustomMarkupContainerComponent implements OnChanges {
10 10
11 @Input() content: string 11 @Input() content: string
12 12
13 displayed = false
14
13 constructor ( 15 constructor (
14 private customMarkupService: CustomMarkupService 16 private customMarkupService: CustomMarkupService
15 ) { } 17 ) { }
@@ -19,8 +21,13 @@ export class CustomMarkupContainerComponent implements OnChanges {
19 } 21 }
20 22
21 private async buildElement () { 23 private async buildElement () {
22 const element = await this.customMarkupService.buildElement(this.content) 24 if (!this.content) return
23 this.contentWrapper.nativeElement.appendChild(element) 25
24 } 26 const { rootElement, componentsLoaded } = await this.customMarkupService.buildElement(this.content)
27 this.contentWrapper.nativeElement.appendChild(rootElement)
25 28
29 await componentsLoaded
30
31 this.displayed = true
32 }
26} 33}
diff --git a/client/src/app/shared/shared-custom-markup/custom-markup.service.ts b/client/src/app/shared/shared-custom-markup/custom-markup.service.ts
index cb1110593..15da94709 100644
--- a/client/src/app/shared/shared-custom-markup/custom-markup.service.ts
+++ b/client/src/app/shared/shared-custom-markup/custom-markup.service.ts
@@ -1,3 +1,4 @@
1import { first } from 'rxjs/operators'
1import { ComponentRef, Injectable } from '@angular/core' 2import { ComponentRef, Injectable } from '@angular/core'
2import { MarkdownService } from '@app/core' 3import { MarkdownService } from '@app/core'
3import { 4import {
@@ -19,8 +20,9 @@ import {
19 VideoMiniatureMarkupComponent, 20 VideoMiniatureMarkupComponent,
20 VideosListMarkupComponent 21 VideosListMarkupComponent
21} from './peertube-custom-tags' 22} from './peertube-custom-tags'
23import { CustomMarkupComponent } from './peertube-custom-tags/shared'
22 24
23type AngularBuilderFunction = (el: HTMLElement) => ComponentRef<any> 25type AngularBuilderFunction = (el: HTMLElement) => ComponentRef<CustomMarkupComponent>
24type HTMLBuilderFunction = (el: HTMLElement) => HTMLElement 26type HTMLBuilderFunction = (el: HTMLElement) => HTMLElement
25 27
26@Injectable() 28@Injectable()
@@ -45,7 +47,10 @@ export class CustomMarkupService {
45 private dynamicElementService: DynamicElementService, 47 private dynamicElementService: DynamicElementService,
46 private markdown: MarkdownService 48 private markdown: MarkdownService
47 ) { 49 ) {
48 this.customMarkdownRenderer = async (text: string) => this.buildElement(text) 50 this.customMarkdownRenderer = (text: string) => {
51 return this.buildElement(text)
52 .then(({ rootElement }) => rootElement)
53 }
49 } 54 }
50 55
51 getCustomMarkdownRenderer () { 56 getCustomMarkdownRenderer () {
@@ -60,23 +65,30 @@ export class CustomMarkupService {
60 65
61 for (const selector of Object.keys(this.htmlBuilders)) { 66 for (const selector of Object.keys(this.htmlBuilders)) {
62 rootElement.querySelectorAll(selector) 67 rootElement.querySelectorAll(selector)
63 .forEach((e: HTMLElement) => { 68 .forEach((e: HTMLElement) => {
64 try { 69 try {
65 const element = this.execHTMLBuilder(selector, e) 70 const element = this.execHTMLBuilder(selector, e)
66 // Insert as first child 71 // Insert as first child
67 e.insertBefore(element, e.firstChild) 72 e.insertBefore(element, e.firstChild)
68 } catch (err) { 73 } catch (err) {
69 console.error('Cannot inject component %s.', selector, err) 74 console.error('Cannot inject component %s.', selector, err)
70 } 75 }
71 }) 76 })
72 } 77 }
73 78
79 const loadedPromises: Promise<boolean>[] = []
80
74 for (const selector of Object.keys(this.angularBuilders)) { 81 for (const selector of Object.keys(this.angularBuilders)) {
75 rootElement.querySelectorAll(selector) 82 rootElement.querySelectorAll(selector)
76 .forEach((e: HTMLElement) => { 83 .forEach((e: HTMLElement) => {
77 try { 84 try {
78 const component = this.execAngularBuilder(selector, e) 85 const component = this.execAngularBuilder(selector, e)
79 86
87 if (component.instance.loaded) {
88 const p = component.instance.loaded.pipe(first()).toPromise()
89 loadedPromises.push(p)
90 }
91
80 this.dynamicElementService.injectElement(e, component) 92 this.dynamicElementService.injectElement(e, component)
81 } catch (err) { 93 } catch (err) {
82 console.error('Cannot inject component %s.', selector, err) 94 console.error('Cannot inject component %s.', selector, err)
@@ -84,7 +96,7 @@ export class CustomMarkupService {
84 }) 96 })
85 } 97 }
86 98
87 return rootElement 99 return { rootElement, componentsLoaded: Promise.all(loadedPromises) }
88 } 100 }
89 101
90 private getSupportedTags () { 102 private getSupportedTags () {
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/button-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/button-markup.component.ts
index 987b37d19..1af060548 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/button-markup.component.ts
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/button-markup.component.ts
@@ -1,5 +1,6 @@
1import { Component, Input } from '@angular/core' 1import { Component, Input } from '@angular/core'
2import { VideoChannel } from '../../shared-main' 2import { VideoChannel } from '../../shared-main'
3import { CustomMarkupComponent } from './shared'
3 4
4/* 5/*
5 * Markup component that creates a button 6 * Markup component that creates a button
@@ -10,13 +11,14 @@ import { VideoChannel } from '../../shared-main'
10 templateUrl: 'button-markup.component.html', 11 templateUrl: 'button-markup.component.html',
11 styleUrls: [ 'button-markup.component.scss' ] 12 styleUrls: [ 'button-markup.component.scss' ]
12}) 13})
13export class ButtonMarkupComponent { 14export class ButtonMarkupComponent implements CustomMarkupComponent {
14 @Input() theme: 'primary' | 'secondary' 15 @Input() theme: 'primary' | 'secondary'
15 @Input() href: string 16 @Input() href: string
16 @Input() label: string 17 @Input() label: string
17 @Input() blankTarget?: boolean 18 @Input() blankTarget?: boolean
18 19
19 channel: VideoChannel 20 channel: VideoChannel
21 loaded: undefined
20 22
21 getTarget () { 23 getTarget () {
22 if (this.blankTarget === true) return '_blank' 24 if (this.blankTarget === true) return '_blank'
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts
index 87caec8a5..a91debbef 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts
@@ -1,8 +1,9 @@
1import { map, switchMap } from 'rxjs/operators' 1import { map, switchMap } from 'rxjs/operators'
2import { Component, Input, OnInit } from '@angular/core' 2import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
3import { MarkdownService, UserService } from '@app/core' 3import { MarkdownService, UserService } from '@app/core'
4import { Video, VideoSortField } from '@shared/models/videos' 4import { Video, VideoSortField } from '@shared/models/videos'
5import { VideoChannel, VideoChannelService, VideoService } from '../../shared-main' 5import { VideoChannel, VideoChannelService, VideoService } from '../../shared-main'
6import { CustomMarkupComponent } from './shared'
6 7
7/* 8/*
8 * Markup component that creates a channel miniature only 9 * Markup component that creates a channel miniature only
@@ -13,11 +14,13 @@ import { VideoChannel, VideoChannelService, VideoService } from '../../shared-ma
13 templateUrl: 'channel-miniature-markup.component.html', 14 templateUrl: 'channel-miniature-markup.component.html',
14 styleUrls: [ 'channel-miniature-markup.component.scss' ] 15 styleUrls: [ 'channel-miniature-markup.component.scss' ]
15}) 16})
16export class ChannelMiniatureMarkupComponent implements OnInit { 17export class ChannelMiniatureMarkupComponent implements CustomMarkupComponent, OnInit {
17 @Input() name: string 18 @Input() name: string
18 @Input() displayLatestVideo: boolean 19 @Input() displayLatestVideo: boolean
19 @Input() displayDescription: boolean 20 @Input() displayDescription: boolean
20 21
22 @Output() loaded = new EventEmitter<boolean>()
23
21 channel: VideoChannel 24 channel: VideoChannel
22 descriptionHTML: string 25 descriptionHTML: string
23 totalVideos: number 26 totalVideos: number
@@ -61,9 +64,13 @@ export class ChannelMiniatureMarkupComponent implements OnInit {
61 map(user => user.nsfwPolicy), 64 map(user => user.nsfwPolicy),
62 switchMap(nsfwPolicy => this.videoService.getVideoChannelVideos({ ...videoOptions, nsfwPolicy })) 65 switchMap(nsfwPolicy => this.videoService.getVideoChannelVideos({ ...videoOptions, nsfwPolicy }))
63 ) 66 )
64 .subscribe(({ total, data }) => { 67 .subscribe({
65 this.totalVideos = total 68 next: ({ total, data }) => {
66 this.video = data[0] 69 this.totalVideos = total
70 this.video = data[0]
71 },
72
73 complete: () => this.loaded.emit(true)
67 }) 74 })
68 } 75 }
69} 76}
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 a854d89f6..4462903db 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
@@ -1,15 +1,18 @@
1import { buildPlaylistLink, buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils' 1import { buildPlaylistLink, buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
2import { environment } from 'src/environments/environment' 2import { environment } from 'src/environments/environment'
3import { Component, ElementRef, Input, OnInit } from '@angular/core' 3import { Component, ElementRef, Input, OnInit } from '@angular/core'
4import { CustomMarkupComponent } from './shared'
4 5
5@Component({ 6@Component({
6 selector: 'my-embed-markup', 7 selector: 'my-embed-markup',
7 template: '' 8 template: ''
8}) 9})
9export class EmbedMarkupComponent implements OnInit { 10export class EmbedMarkupComponent implements CustomMarkupComponent, OnInit {
10 @Input() uuid: string 11 @Input() uuid: string
11 @Input() type: 'video' | 'playlist' = 'video' 12 @Input() type: 'video' | 'playlist' = 'video'
12 13
14 loaded: undefined
15
13 constructor (private el: ElementRef) { } 16 constructor (private el: ElementRef) { }
14 17
15 ngOnInit () { 18 ngOnInit () {
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/playlist-miniature-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/playlist-miniature-markup.component.ts
index eddc3636e..42a42d711 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/playlist-miniature-markup.component.ts
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/playlist-miniature-markup.component.ts
@@ -1,6 +1,7 @@
1import { Component, Input, OnInit } from '@angular/core' 1import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
2import { MiniatureDisplayOptions } from '../../shared-video-miniature' 2import { MiniatureDisplayOptions } from '../../shared-video-miniature'
3import { VideoPlaylist, VideoPlaylistService } from '../../shared-video-playlist' 3import { VideoPlaylist, VideoPlaylistService } from '../../shared-video-playlist'
4import { CustomMarkupComponent } from './shared'
4 5
5/* 6/*
6 * Markup component that creates a playlist miniature only 7 * Markup component that creates a playlist miniature only
@@ -11,9 +12,11 @@ import { VideoPlaylist, VideoPlaylistService } from '../../shared-video-playlist
11 templateUrl: 'playlist-miniature-markup.component.html', 12 templateUrl: 'playlist-miniature-markup.component.html',
12 styleUrls: [ 'playlist-miniature-markup.component.scss' ] 13 styleUrls: [ 'playlist-miniature-markup.component.scss' ]
13}) 14})
14export class PlaylistMiniatureMarkupComponent implements OnInit { 15export class PlaylistMiniatureMarkupComponent implements CustomMarkupComponent, OnInit {
15 @Input() uuid: string 16 @Input() uuid: string
16 17
18 @Output() loaded = new EventEmitter<boolean>()
19
17 playlist: VideoPlaylist 20 playlist: VideoPlaylist
18 21
19 displayOptions: MiniatureDisplayOptions = { 22 displayOptions: MiniatureDisplayOptions = {
@@ -33,6 +36,10 @@ export class PlaylistMiniatureMarkupComponent implements OnInit {
33 36
34 ngOnInit () { 37 ngOnInit () {
35 this.playlistService.getVideoPlaylist(this.uuid) 38 this.playlistService.getVideoPlaylist(this.uuid)
36 .subscribe(playlist => this.playlist = playlist) 39 .subscribe({
40 next: playlist => this.playlist = playlist,
41
42 complete: () => this.loaded.emit(true)
43 })
37 } 44 }
38} 45}
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/shared/custom-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/shared/custom-markup.component.ts
new file mode 100644
index 000000000..adfd48c55
--- /dev/null
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/shared/custom-markup.component.ts
@@ -0,0 +1,5 @@
1import { EventEmitter } from '@angular/core'
2
3export interface CustomMarkupComponent {
4 loaded: EventEmitter<boolean> | undefined
5}
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/shared/index.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/shared/index.ts
new file mode 100644
index 000000000..a6a7bbd92
--- /dev/null
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/shared/index.ts
@@ -0,0 +1 @@
export * from './custom-markup.component'
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts
index dfb4c497f..6ee5123e0 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts
@@ -1,7 +1,8 @@
1import { Component, Input, OnInit } from '@angular/core' 1import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
2import { AuthService } from '@app/core' 2import { AuthService } from '@app/core'
3import { Video, VideoService } from '../../shared-main' 3import { Video, VideoService } from '../../shared-main'
4import { MiniatureDisplayOptions } from '../../shared-video-miniature' 4import { MiniatureDisplayOptions } from '../../shared-video-miniature'
5import { CustomMarkupComponent } from './shared'
5 6
6/* 7/*
7 * Markup component that creates a video miniature only 8 * Markup component that creates a video miniature only
@@ -12,10 +13,12 @@ import { MiniatureDisplayOptions } from '../../shared-video-miniature'
12 templateUrl: 'video-miniature-markup.component.html', 13 templateUrl: 'video-miniature-markup.component.html',
13 styleUrls: [ 'video-miniature-markup.component.scss' ] 14 styleUrls: [ 'video-miniature-markup.component.scss' ]
14}) 15})
15export class VideoMiniatureMarkupComponent implements OnInit { 16export class VideoMiniatureMarkupComponent implements CustomMarkupComponent, OnInit {
16 @Input() uuid: string 17 @Input() uuid: string
17 @Input() onlyDisplayTitle: boolean 18 @Input() onlyDisplayTitle: boolean
18 19
20 @Output() loaded = new EventEmitter<boolean>()
21
19 video: Video 22 video: Video
20 23
21 displayOptions: MiniatureDisplayOptions = { 24 displayOptions: MiniatureDisplayOptions = {
@@ -46,6 +49,10 @@ export class VideoMiniatureMarkupComponent implements OnInit {
46 } 49 }
47 50
48 this.videoService.getVideo({ videoId: this.uuid }) 51 this.videoService.getVideo({ videoId: this.uuid })
49 .subscribe(video => this.video = video) 52 .subscribe({
53 next: video => this.video = video,
54
55 complete: () => this.loaded.emit(true)
56 })
50 } 57 }
51} 58}
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/videos-list-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/videos-list-markup.component.ts
index d4402dd9f..02738022e 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/videos-list-markup.component.ts
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/videos-list-markup.component.ts
@@ -1,8 +1,9 @@
1import { Component, Input, OnInit } from '@angular/core' 1import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
2import { AuthService } from '@app/core' 2import { AuthService } from '@app/core'
3import { VideoFilter, VideoSortField } from '@shared/models' 3import { VideoFilter, VideoSortField } from '@shared/models'
4import { Video, VideoService } from '../../shared-main' 4import { Video, VideoService } from '../../shared-main'
5import { MiniatureDisplayOptions } from '../../shared-video-miniature' 5import { MiniatureDisplayOptions } from '../../shared-video-miniature'
6import { CustomMarkupComponent } from './shared'
6 7
7/* 8/*
8 * Markup component list videos depending on criterias 9 * Markup component list videos depending on criterias
@@ -13,7 +14,7 @@ import { MiniatureDisplayOptions } from '../../shared-video-miniature'
13 templateUrl: 'videos-list-markup.component.html', 14 templateUrl: 'videos-list-markup.component.html',
14 styleUrls: [ 'videos-list-markup.component.scss' ] 15 styleUrls: [ 'videos-list-markup.component.scss' ]
15}) 16})
16export class VideosListMarkupComponent implements OnInit { 17export class VideosListMarkupComponent implements CustomMarkupComponent, OnInit {
17 @Input() sort: string 18 @Input() sort: string
18 @Input() categoryOneOf: number[] 19 @Input() categoryOneOf: number[]
19 @Input() languageOneOf: string[] 20 @Input() languageOneOf: string[]
@@ -22,6 +23,8 @@ export class VideosListMarkupComponent implements OnInit {
22 @Input() filter: VideoFilter 23 @Input() filter: VideoFilter
23 @Input() maxRows: number 24 @Input() maxRows: number
24 25
26 @Output() loaded = new EventEmitter<boolean>()
27
25 videos: Video[] 28 videos: Video[]
26 29
27 displayOptions: MiniatureDisplayOptions = { 30 displayOptions: MiniatureDisplayOptions = {
@@ -73,6 +76,10 @@ export class VideosListMarkupComponent implements OnInit {
73 } 76 }
74 77
75 this.videoService.getVideos(options) 78 this.videoService.getVideos(options)
76 .subscribe(({ data }) => this.videos = data) 79 .subscribe({
80 next: ({ data }) => this.videos = data,
81
82 complete: () => this.loaded.emit(true)
83 })
77 } 84 }
78} 85}