Only display homepage when components are loaded
This commit is contained in:
parent
76b8d72e32
commit
0ca454e3bd
|
@ -1 +1 @@
|
||||||
<div class="custom-markup-container" #contentWrapper></div>
|
<div [hidden]="!displayed" class="custom-markup-container" #contentWrapper></div>
|
||||||
|
|
|
@ -10,6 +10,8 @@ export class CustomMarkupContainerComponent implements OnChanges {
|
||||||
|
|
||||||
@Input() content: string
|
@Input() content: string
|
||||||
|
|
||||||
|
displayed = false
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private customMarkupService: CustomMarkupService
|
private customMarkupService: CustomMarkupService
|
||||||
) { }
|
) { }
|
||||||
|
@ -19,8 +21,13 @@ export class CustomMarkupContainerComponent implements OnChanges {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async buildElement () {
|
private async buildElement () {
|
||||||
const element = await this.customMarkupService.buildElement(this.content)
|
if (!this.content) return
|
||||||
this.contentWrapper.nativeElement.appendChild(element)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const { rootElement, componentsLoaded } = await this.customMarkupService.buildElement(this.content)
|
||||||
|
this.contentWrapper.nativeElement.appendChild(rootElement)
|
||||||
|
|
||||||
|
await componentsLoaded
|
||||||
|
|
||||||
|
this.displayed = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { first } from 'rxjs/operators'
|
||||||
import { ComponentRef, Injectable } from '@angular/core'
|
import { ComponentRef, Injectable } from '@angular/core'
|
||||||
import { MarkdownService } from '@app/core'
|
import { MarkdownService } from '@app/core'
|
||||||
import {
|
import {
|
||||||
|
@ -19,8 +20,9 @@ import {
|
||||||
VideoMiniatureMarkupComponent,
|
VideoMiniatureMarkupComponent,
|
||||||
VideosListMarkupComponent
|
VideosListMarkupComponent
|
||||||
} from './peertube-custom-tags'
|
} from './peertube-custom-tags'
|
||||||
|
import { CustomMarkupComponent } from './peertube-custom-tags/shared'
|
||||||
|
|
||||||
type AngularBuilderFunction = (el: HTMLElement) => ComponentRef<any>
|
type AngularBuilderFunction = (el: HTMLElement) => ComponentRef<CustomMarkupComponent>
|
||||||
type HTMLBuilderFunction = (el: HTMLElement) => HTMLElement
|
type HTMLBuilderFunction = (el: HTMLElement) => HTMLElement
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -45,7 +47,10 @@ export class CustomMarkupService {
|
||||||
private dynamicElementService: DynamicElementService,
|
private dynamicElementService: DynamicElementService,
|
||||||
private markdown: MarkdownService
|
private markdown: MarkdownService
|
||||||
) {
|
) {
|
||||||
this.customMarkdownRenderer = async (text: string) => this.buildElement(text)
|
this.customMarkdownRenderer = (text: string) => {
|
||||||
|
return this.buildElement(text)
|
||||||
|
.then(({ rootElement }) => rootElement)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getCustomMarkdownRenderer () {
|
getCustomMarkdownRenderer () {
|
||||||
|
@ -71,12 +76,19 @@ export class CustomMarkupService {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadedPromises: Promise<boolean>[] = []
|
||||||
|
|
||||||
for (const selector of Object.keys(this.angularBuilders)) {
|
for (const selector of Object.keys(this.angularBuilders)) {
|
||||||
rootElement.querySelectorAll(selector)
|
rootElement.querySelectorAll(selector)
|
||||||
.forEach((e: HTMLElement) => {
|
.forEach((e: HTMLElement) => {
|
||||||
try {
|
try {
|
||||||
const component = this.execAngularBuilder(selector, e)
|
const component = this.execAngularBuilder(selector, e)
|
||||||
|
|
||||||
|
if (component.instance.loaded) {
|
||||||
|
const p = component.instance.loaded.pipe(first()).toPromise()
|
||||||
|
loadedPromises.push(p)
|
||||||
|
}
|
||||||
|
|
||||||
this.dynamicElementService.injectElement(e, component)
|
this.dynamicElementService.injectElement(e, component)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Cannot inject component %s.', selector, err)
|
console.error('Cannot inject component %s.', selector, err)
|
||||||
|
@ -84,7 +96,7 @@ export class CustomMarkupService {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootElement
|
return { rootElement, componentsLoaded: Promise.all(loadedPromises) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private getSupportedTags () {
|
private getSupportedTags () {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Component, Input } from '@angular/core'
|
import { Component, Input } from '@angular/core'
|
||||||
import { VideoChannel } from '../../shared-main'
|
import { VideoChannel } from '../../shared-main'
|
||||||
|
import { CustomMarkupComponent } from './shared'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Markup component that creates a button
|
* Markup component that creates a button
|
||||||
|
@ -10,13 +11,14 @@ import { VideoChannel } from '../../shared-main'
|
||||||
templateUrl: 'button-markup.component.html',
|
templateUrl: 'button-markup.component.html',
|
||||||
styleUrls: [ 'button-markup.component.scss' ]
|
styleUrls: [ 'button-markup.component.scss' ]
|
||||||
})
|
})
|
||||||
export class ButtonMarkupComponent {
|
export class ButtonMarkupComponent implements CustomMarkupComponent {
|
||||||
@Input() theme: 'primary' | 'secondary'
|
@Input() theme: 'primary' | 'secondary'
|
||||||
@Input() href: string
|
@Input() href: string
|
||||||
@Input() label: string
|
@Input() label: string
|
||||||
@Input() blankTarget?: boolean
|
@Input() blankTarget?: boolean
|
||||||
|
|
||||||
channel: VideoChannel
|
channel: VideoChannel
|
||||||
|
loaded: undefined
|
||||||
|
|
||||||
getTarget () {
|
getTarget () {
|
||||||
if (this.blankTarget === true) return '_blank'
|
if (this.blankTarget === true) return '_blank'
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { map, switchMap } from 'rxjs/operators'
|
import { map, switchMap } from 'rxjs/operators'
|
||||||
import { Component, Input, OnInit } from '@angular/core'
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
|
||||||
import { MarkdownService, UserService } from '@app/core'
|
import { MarkdownService, UserService } from '@app/core'
|
||||||
import { Video, VideoSortField } from '@shared/models/videos'
|
import { Video, VideoSortField } from '@shared/models/videos'
|
||||||
import { VideoChannel, VideoChannelService, VideoService } from '../../shared-main'
|
import { VideoChannel, VideoChannelService, VideoService } from '../../shared-main'
|
||||||
|
import { CustomMarkupComponent } from './shared'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Markup component that creates a channel miniature only
|
* Markup component that creates a channel miniature only
|
||||||
|
@ -13,11 +14,13 @@ import { VideoChannel, VideoChannelService, VideoService } from '../../shared-ma
|
||||||
templateUrl: 'channel-miniature-markup.component.html',
|
templateUrl: 'channel-miniature-markup.component.html',
|
||||||
styleUrls: [ 'channel-miniature-markup.component.scss' ]
|
styleUrls: [ 'channel-miniature-markup.component.scss' ]
|
||||||
})
|
})
|
||||||
export class ChannelMiniatureMarkupComponent implements OnInit {
|
export class ChannelMiniatureMarkupComponent implements CustomMarkupComponent, OnInit {
|
||||||
@Input() name: string
|
@Input() name: string
|
||||||
@Input() displayLatestVideo: boolean
|
@Input() displayLatestVideo: boolean
|
||||||
@Input() displayDescription: boolean
|
@Input() displayDescription: boolean
|
||||||
|
|
||||||
|
@Output() loaded = new EventEmitter<boolean>()
|
||||||
|
|
||||||
channel: VideoChannel
|
channel: VideoChannel
|
||||||
descriptionHTML: string
|
descriptionHTML: string
|
||||||
totalVideos: number
|
totalVideos: number
|
||||||
|
@ -61,9 +64,13 @@ export class ChannelMiniatureMarkupComponent implements OnInit {
|
||||||
map(user => user.nsfwPolicy),
|
map(user => user.nsfwPolicy),
|
||||||
switchMap(nsfwPolicy => this.videoService.getVideoChannelVideos({ ...videoOptions, nsfwPolicy }))
|
switchMap(nsfwPolicy => this.videoService.getVideoChannelVideos({ ...videoOptions, nsfwPolicy }))
|
||||||
)
|
)
|
||||||
.subscribe(({ total, data }) => {
|
.subscribe({
|
||||||
|
next: ({ total, data }) => {
|
||||||
this.totalVideos = total
|
this.totalVideos = total
|
||||||
this.video = data[0]
|
this.video = data[0]
|
||||||
|
},
|
||||||
|
|
||||||
|
complete: () => this.loaded.emit(true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
import { buildPlaylistLink, buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
|
import { buildPlaylistLink, buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
|
||||||
import { environment } from 'src/environments/environment'
|
import { environment } from 'src/environments/environment'
|
||||||
import { Component, ElementRef, Input, OnInit } from '@angular/core'
|
import { Component, ElementRef, Input, OnInit } from '@angular/core'
|
||||||
|
import { CustomMarkupComponent } from './shared'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-embed-markup',
|
selector: 'my-embed-markup',
|
||||||
template: ''
|
template: ''
|
||||||
})
|
})
|
||||||
export class EmbedMarkupComponent implements OnInit {
|
export class EmbedMarkupComponent implements CustomMarkupComponent, OnInit {
|
||||||
@Input() uuid: string
|
@Input() uuid: string
|
||||||
@Input() type: 'video' | 'playlist' = 'video'
|
@Input() type: 'video' | 'playlist' = 'video'
|
||||||
|
|
||||||
|
loaded: undefined
|
||||||
|
|
||||||
constructor (private el: ElementRef) { }
|
constructor (private el: ElementRef) { }
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Component, Input, OnInit } from '@angular/core'
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
|
||||||
import { MiniatureDisplayOptions } from '../../shared-video-miniature'
|
import { MiniatureDisplayOptions } from '../../shared-video-miniature'
|
||||||
import { VideoPlaylist, VideoPlaylistService } from '../../shared-video-playlist'
|
import { VideoPlaylist, VideoPlaylistService } from '../../shared-video-playlist'
|
||||||
|
import { CustomMarkupComponent } from './shared'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Markup component that creates a playlist miniature only
|
* Markup component that creates a playlist miniature only
|
||||||
|
@ -11,9 +12,11 @@ import { VideoPlaylist, VideoPlaylistService } from '../../shared-video-playlist
|
||||||
templateUrl: 'playlist-miniature-markup.component.html',
|
templateUrl: 'playlist-miniature-markup.component.html',
|
||||||
styleUrls: [ 'playlist-miniature-markup.component.scss' ]
|
styleUrls: [ 'playlist-miniature-markup.component.scss' ]
|
||||||
})
|
})
|
||||||
export class PlaylistMiniatureMarkupComponent implements OnInit {
|
export class PlaylistMiniatureMarkupComponent implements CustomMarkupComponent, OnInit {
|
||||||
@Input() uuid: string
|
@Input() uuid: string
|
||||||
|
|
||||||
|
@Output() loaded = new EventEmitter<boolean>()
|
||||||
|
|
||||||
playlist: VideoPlaylist
|
playlist: VideoPlaylist
|
||||||
|
|
||||||
displayOptions: MiniatureDisplayOptions = {
|
displayOptions: MiniatureDisplayOptions = {
|
||||||
|
@ -33,6 +36,10 @@ export class PlaylistMiniatureMarkupComponent implements OnInit {
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this.playlistService.getVideoPlaylist(this.uuid)
|
this.playlistService.getVideoPlaylist(this.uuid)
|
||||||
.subscribe(playlist => this.playlist = playlist)
|
.subscribe({
|
||||||
|
next: playlist => this.playlist = playlist,
|
||||||
|
|
||||||
|
complete: () => this.loaded.emit(true)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { EventEmitter } from '@angular/core'
|
||||||
|
|
||||||
|
export interface CustomMarkupComponent {
|
||||||
|
loaded: EventEmitter<boolean> | undefined
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './custom-markup.component'
|
|
@ -1,7 +1,8 @@
|
||||||
import { Component, Input, OnInit } from '@angular/core'
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
|
||||||
import { AuthService } from '@app/core'
|
import { AuthService } from '@app/core'
|
||||||
import { Video, VideoService } from '../../shared-main'
|
import { Video, VideoService } from '../../shared-main'
|
||||||
import { MiniatureDisplayOptions } from '../../shared-video-miniature'
|
import { MiniatureDisplayOptions } from '../../shared-video-miniature'
|
||||||
|
import { CustomMarkupComponent } from './shared'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Markup component that creates a video miniature only
|
* Markup component that creates a video miniature only
|
||||||
|
@ -12,10 +13,12 @@ import { MiniatureDisplayOptions } from '../../shared-video-miniature'
|
||||||
templateUrl: 'video-miniature-markup.component.html',
|
templateUrl: 'video-miniature-markup.component.html',
|
||||||
styleUrls: [ 'video-miniature-markup.component.scss' ]
|
styleUrls: [ 'video-miniature-markup.component.scss' ]
|
||||||
})
|
})
|
||||||
export class VideoMiniatureMarkupComponent implements OnInit {
|
export class VideoMiniatureMarkupComponent implements CustomMarkupComponent, OnInit {
|
||||||
@Input() uuid: string
|
@Input() uuid: string
|
||||||
@Input() onlyDisplayTitle: boolean
|
@Input() onlyDisplayTitle: boolean
|
||||||
|
|
||||||
|
@Output() loaded = new EventEmitter<boolean>()
|
||||||
|
|
||||||
video: Video
|
video: Video
|
||||||
|
|
||||||
displayOptions: MiniatureDisplayOptions = {
|
displayOptions: MiniatureDisplayOptions = {
|
||||||
|
@ -46,6 +49,10 @@ export class VideoMiniatureMarkupComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.videoService.getVideo({ videoId: this.uuid })
|
this.videoService.getVideo({ videoId: this.uuid })
|
||||||
.subscribe(video => this.video = video)
|
.subscribe({
|
||||||
|
next: video => this.video = video,
|
||||||
|
|
||||||
|
complete: () => this.loaded.emit(true)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { Component, Input, OnInit } from '@angular/core'
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
|
||||||
import { AuthService } from '@app/core'
|
import { AuthService } from '@app/core'
|
||||||
import { VideoFilter, VideoSortField } from '@shared/models'
|
import { VideoFilter, VideoSortField } from '@shared/models'
|
||||||
import { Video, VideoService } from '../../shared-main'
|
import { Video, VideoService } from '../../shared-main'
|
||||||
import { MiniatureDisplayOptions } from '../../shared-video-miniature'
|
import { MiniatureDisplayOptions } from '../../shared-video-miniature'
|
||||||
|
import { CustomMarkupComponent } from './shared'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Markup component list videos depending on criterias
|
* Markup component list videos depending on criterias
|
||||||
|
@ -13,7 +14,7 @@ import { MiniatureDisplayOptions } from '../../shared-video-miniature'
|
||||||
templateUrl: 'videos-list-markup.component.html',
|
templateUrl: 'videos-list-markup.component.html',
|
||||||
styleUrls: [ 'videos-list-markup.component.scss' ]
|
styleUrls: [ 'videos-list-markup.component.scss' ]
|
||||||
})
|
})
|
||||||
export class VideosListMarkupComponent implements OnInit {
|
export class VideosListMarkupComponent implements CustomMarkupComponent, OnInit {
|
||||||
@Input() sort: string
|
@Input() sort: string
|
||||||
@Input() categoryOneOf: number[]
|
@Input() categoryOneOf: number[]
|
||||||
@Input() languageOneOf: string[]
|
@Input() languageOneOf: string[]
|
||||||
|
@ -22,6 +23,8 @@ export class VideosListMarkupComponent implements OnInit {
|
||||||
@Input() filter: VideoFilter
|
@Input() filter: VideoFilter
|
||||||
@Input() maxRows: number
|
@Input() maxRows: number
|
||||||
|
|
||||||
|
@Output() loaded = new EventEmitter<boolean>()
|
||||||
|
|
||||||
videos: Video[]
|
videos: Video[]
|
||||||
|
|
||||||
displayOptions: MiniatureDisplayOptions = {
|
displayOptions: MiniatureDisplayOptions = {
|
||||||
|
@ -73,6 +76,10 @@ export class VideosListMarkupComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.videoService.getVideos(options)
|
this.videoService.getVideos(options)
|
||||||
.subscribe(({ data }) => this.videos = data)
|
.subscribe({
|
||||||
|
next: ({ data }) => this.videos = data,
|
||||||
|
|
||||||
|
complete: () => this.loaded.emit(true)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue