Only display homepage when components are loaded

pull/4218/head
Chocobozzz 2021-06-29 16:16:12 +02:00
parent 76b8d72e32
commit 0ca454e3bd
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
11 changed files with 90 additions and 32 deletions

View File

@ -1 +1 @@
<div class="custom-markup-container" #contentWrapper></div>
<div [hidden]="!displayed" class="custom-markup-container" #contentWrapper></div>

View File

@ -10,6 +10,8 @@ export class CustomMarkupContainerComponent implements OnChanges {
@Input() content: string
displayed = false
constructor (
private customMarkupService: CustomMarkupService
) { }
@ -19,8 +21,13 @@ export class CustomMarkupContainerComponent implements OnChanges {
}
private async buildElement () {
const element = await this.customMarkupService.buildElement(this.content)
this.contentWrapper.nativeElement.appendChild(element)
}
if (!this.content) return
const { rootElement, componentsLoaded } = await this.customMarkupService.buildElement(this.content)
this.contentWrapper.nativeElement.appendChild(rootElement)
await componentsLoaded
this.displayed = true
}
}

View File

@ -1,3 +1,4 @@
import { first } from 'rxjs/operators'
import { ComponentRef, Injectable } from '@angular/core'
import { MarkdownService } from '@app/core'
import {
@ -19,8 +20,9 @@ import {
VideoMiniatureMarkupComponent,
VideosListMarkupComponent
} 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
@Injectable()
@ -45,7 +47,10 @@ export class CustomMarkupService {
private dynamicElementService: DynamicElementService,
private markdown: MarkdownService
) {
this.customMarkdownRenderer = async (text: string) => this.buildElement(text)
this.customMarkdownRenderer = (text: string) => {
return this.buildElement(text)
.then(({ rootElement }) => rootElement)
}
}
getCustomMarkdownRenderer () {
@ -60,23 +65,30 @@ export class CustomMarkupService {
for (const selector of Object.keys(this.htmlBuilders)) {
rootElement.querySelectorAll(selector)
.forEach((e: HTMLElement) => {
try {
const element = this.execHTMLBuilder(selector, e)
// Insert as first child
e.insertBefore(element, e.firstChild)
} catch (err) {
console.error('Cannot inject component %s.', selector, err)
}
})
.forEach((e: HTMLElement) => {
try {
const element = this.execHTMLBuilder(selector, e)
// Insert as first child
e.insertBefore(element, e.firstChild)
} catch (err) {
console.error('Cannot inject component %s.', selector, err)
}
})
}
const loadedPromises: Promise<boolean>[] = []
for (const selector of Object.keys(this.angularBuilders)) {
rootElement.querySelectorAll(selector)
.forEach((e: HTMLElement) => {
try {
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)
} catch (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 () {

View File

@ -1,5 +1,6 @@
import { Component, Input } from '@angular/core'
import { VideoChannel } from '../../shared-main'
import { CustomMarkupComponent } from './shared'
/*
* Markup component that creates a button
@ -10,13 +11,14 @@ import { VideoChannel } from '../../shared-main'
templateUrl: 'button-markup.component.html',
styleUrls: [ 'button-markup.component.scss' ]
})
export class ButtonMarkupComponent {
export class ButtonMarkupComponent implements CustomMarkupComponent {
@Input() theme: 'primary' | 'secondary'
@Input() href: string
@Input() label: string
@Input() blankTarget?: boolean
channel: VideoChannel
loaded: undefined
getTarget () {
if (this.blankTarget === true) return '_blank'

View File

@ -1,8 +1,9 @@
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 { Video, VideoSortField } from '@shared/models/videos'
import { VideoChannel, VideoChannelService, VideoService } from '../../shared-main'
import { CustomMarkupComponent } from './shared'
/*
* 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',
styleUrls: [ 'channel-miniature-markup.component.scss' ]
})
export class ChannelMiniatureMarkupComponent implements OnInit {
export class ChannelMiniatureMarkupComponent implements CustomMarkupComponent, OnInit {
@Input() name: string
@Input() displayLatestVideo: boolean
@Input() displayDescription: boolean
@Output() loaded = new EventEmitter<boolean>()
channel: VideoChannel
descriptionHTML: string
totalVideos: number
@ -61,9 +64,13 @@ export class ChannelMiniatureMarkupComponent implements OnInit {
map(user => user.nsfwPolicy),
switchMap(nsfwPolicy => this.videoService.getVideoChannelVideos({ ...videoOptions, nsfwPolicy }))
)
.subscribe(({ total, data }) => {
this.totalVideos = total
this.video = data[0]
.subscribe({
next: ({ total, data }) => {
this.totalVideos = total
this.video = data[0]
},
complete: () => this.loaded.emit(true)
})
}
}

View File

@ -1,15 +1,18 @@
import { buildPlaylistLink, buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
import { environment } from 'src/environments/environment'
import { Component, ElementRef, Input, OnInit } from '@angular/core'
import { CustomMarkupComponent } from './shared'
@Component({
selector: 'my-embed-markup',
template: ''
})
export class EmbedMarkupComponent implements OnInit {
export class EmbedMarkupComponent implements CustomMarkupComponent, OnInit {
@Input() uuid: string
@Input() type: 'video' | 'playlist' = 'video'
loaded: undefined
constructor (private el: ElementRef) { }
ngOnInit () {

View File

@ -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 { VideoPlaylist, VideoPlaylistService } from '../../shared-video-playlist'
import { CustomMarkupComponent } from './shared'
/*
* 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',
styleUrls: [ 'playlist-miniature-markup.component.scss' ]
})
export class PlaylistMiniatureMarkupComponent implements OnInit {
export class PlaylistMiniatureMarkupComponent implements CustomMarkupComponent, OnInit {
@Input() uuid: string
@Output() loaded = new EventEmitter<boolean>()
playlist: VideoPlaylist
displayOptions: MiniatureDisplayOptions = {
@ -33,6 +36,10 @@ export class PlaylistMiniatureMarkupComponent implements OnInit {
ngOnInit () {
this.playlistService.getVideoPlaylist(this.uuid)
.subscribe(playlist => this.playlist = playlist)
.subscribe({
next: playlist => this.playlist = playlist,
complete: () => this.loaded.emit(true)
})
}
}

View File

@ -0,0 +1,5 @@
import { EventEmitter } from '@angular/core'
export interface CustomMarkupComponent {
loaded: EventEmitter<boolean> | undefined
}

View File

@ -0,0 +1 @@
export * from './custom-markup.component'

View File

@ -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 { Video, VideoService } from '../../shared-main'
import { MiniatureDisplayOptions } from '../../shared-video-miniature'
import { CustomMarkupComponent } from './shared'
/*
* Markup component that creates a video miniature only
@ -12,10 +13,12 @@ import { MiniatureDisplayOptions } from '../../shared-video-miniature'
templateUrl: 'video-miniature-markup.component.html',
styleUrls: [ 'video-miniature-markup.component.scss' ]
})
export class VideoMiniatureMarkupComponent implements OnInit {
export class VideoMiniatureMarkupComponent implements CustomMarkupComponent, OnInit {
@Input() uuid: string
@Input() onlyDisplayTitle: boolean
@Output() loaded = new EventEmitter<boolean>()
video: Video
displayOptions: MiniatureDisplayOptions = {
@ -46,6 +49,10 @@ export class VideoMiniatureMarkupComponent implements OnInit {
}
this.videoService.getVideo({ videoId: this.uuid })
.subscribe(video => this.video = video)
.subscribe({
next: video => this.video = video,
complete: () => this.loaded.emit(true)
})
}
}

View File

@ -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 { VideoFilter, VideoSortField } from '@shared/models'
import { Video, VideoService } from '../../shared-main'
import { MiniatureDisplayOptions } from '../../shared-video-miniature'
import { CustomMarkupComponent } from './shared'
/*
* Markup component list videos depending on criterias
@ -13,7 +14,7 @@ import { MiniatureDisplayOptions } from '../../shared-video-miniature'
templateUrl: 'videos-list-markup.component.html',
styleUrls: [ 'videos-list-markup.component.scss' ]
})
export class VideosListMarkupComponent implements OnInit {
export class VideosListMarkupComponent implements CustomMarkupComponent, OnInit {
@Input() sort: string
@Input() categoryOneOf: number[]
@Input() languageOneOf: string[]
@ -22,6 +23,8 @@ export class VideosListMarkupComponent implements OnInit {
@Input() filter: VideoFilter
@Input() maxRows: number
@Output() loaded = new EventEmitter<boolean>()
videos: Video[]
displayOptions: MiniatureDisplayOptions = {
@ -73,6 +76,10 @@ export class VideosListMarkupComponent implements OnInit {
}
this.videoService.getVideos(options)
.subscribe(({ data }) => this.videos = data)
.subscribe({
next: ({ data }) => this.videos = data,
complete: () => this.loaded.emit(true)
})
}
}