diff --git a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts index 1a40f6c65..ec02cfcd9 100644 --- a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts +++ b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts @@ -111,7 +111,7 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit this.form.patchValue(settingsValues) - setTimeout(() => this.hooks.runAction('action:admin-plugin-settings.init', 'admin-plugin', { npmName: this.npmName })) + this.hooks.runAction('action:admin-plugin-settings.init', 'admin-plugin', { npmName: this.npmName }) } private getSetting (name: string) { diff --git a/client/src/app/+manage/video-channel-edit/video-channel-create.component.ts b/client/src/app/+manage/video-channel-edit/video-channel-create.component.ts index 5f8e0278e..8211451a4 100644 --- a/client/src/app/+manage/video-channel-edit/video-channel-create.component.ts +++ b/client/src/app/+manage/video-channel-edit/video-channel-create.component.ts @@ -1,8 +1,8 @@ import { of } from 'rxjs' import { switchMap } from 'rxjs/operators' -import { Component, OnInit } from '@angular/core' +import { AfterViewInit, Component, OnInit } from '@angular/core' import { Router } from '@angular/router' -import { AuthService, Notifier } from '@app/core' +import { AuthService, HooksService, Notifier } from '@app/core' import { VIDEO_CHANNEL_DESCRIPTION_VALIDATOR, VIDEO_CHANNEL_DISPLAY_NAME_VALIDATOR, @@ -18,7 +18,7 @@ import { VideoChannelEdit } from './video-channel-edit' templateUrl: './video-channel-edit.component.html', styleUrls: [ './video-channel-edit.component.scss' ] }) -export class VideoChannelCreateComponent extends VideoChannelEdit implements OnInit { +export class VideoChannelCreateComponent extends VideoChannelEdit implements OnInit, AfterViewInit { error: string videoChannel = new VideoChannel({}) @@ -30,7 +30,8 @@ export class VideoChannelCreateComponent extends VideoChannelEdit implements OnI private authService: AuthService, private notifier: Notifier, private router: Router, - private videoChannelService: VideoChannelService + private videoChannelService: VideoChannelService, + private hooks: HooksService ) { super() } @@ -44,6 +45,10 @@ export class VideoChannelCreateComponent extends VideoChannelEdit implements OnI }) } + ngAfterViewInit () { + this.hooks.runAction('action:video-channel-create.init', 'video-channel') + } + formValidated () { this.error = undefined diff --git a/client/src/app/+manage/video-channel-edit/video-channel-update.component.ts b/client/src/app/+manage/video-channel-edit/video-channel-update.component.ts index 6b4947912..7e8d6ffe6 100644 --- a/client/src/app/+manage/video-channel-edit/video-channel-update.component.ts +++ b/client/src/app/+manage/video-channel-edit/video-channel-update.component.ts @@ -1,8 +1,8 @@ import { Subscription } from 'rxjs' import { HttpErrorResponse } from '@angular/common/http' -import { Component, OnDestroy, OnInit } from '@angular/core' -import { ActivatedRoute, Router } from '@angular/router' -import { AuthService, Notifier, RedirectService, ServerService } from '@app/core' +import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core' +import { ActivatedRoute } from '@angular/router' +import { AuthService, HooksService, Notifier, RedirectService, ServerService } from '@app/core' import { genericUploadErrorHandler } from '@app/helpers' import { VIDEO_CHANNEL_DESCRIPTION_VALIDATOR, @@ -19,7 +19,7 @@ import { VideoChannelEdit } from './video-channel-edit' templateUrl: './video-channel-edit.component.html', styleUrls: [ './video-channel-edit.component.scss' ] }) -export class VideoChannelUpdateComponent extends VideoChannelEdit implements OnInit, OnDestroy { +export class VideoChannelUpdateComponent extends VideoChannelEdit implements OnInit, AfterViewInit, OnDestroy { error: string videoChannel: VideoChannel @@ -31,11 +31,11 @@ export class VideoChannelUpdateComponent extends VideoChannelEdit implements OnI protected formValidatorService: FormValidatorService, private authService: AuthService, private notifier: Notifier, - private router: Router, private route: ActivatedRoute, private videoChannelService: VideoChannelService, private serverService: ServerService, - private redirectService: RedirectService + private redirectService: RedirectService, + private hooks: HooksService ) { super() } @@ -58,6 +58,8 @@ export class VideoChannelUpdateComponent extends VideoChannelEdit implements OnI next: videoChannelToUpdate => { this.videoChannel = videoChannelToUpdate + this.hooks.runAction('action:video-channel-update.video-channel.loaded', 'video-channel', { videoChannel: this.videoChannel }) + this.oldSupportField = videoChannelToUpdate.support this.form.patchValue({ @@ -74,6 +76,10 @@ export class VideoChannelUpdateComponent extends VideoChannelEdit implements OnI }) } + ngAfterViewInit () { + this.hooks.runAction('action:video-channel-update.init', 'video-channel') + } + ngOnDestroy () { if (this.paramsSub) this.paramsSub.unsubscribe() } diff --git a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts index 14465bb8d..82af65026 100644 --- a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts +++ b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts @@ -1,6 +1,6 @@ import { Subject, Subscription } from 'rxjs' -import { Component, OnDestroy, OnInit } from '@angular/core' -import { ComponentPagination, hasMoreItems, ScreenService } from '@app/core' +import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core' +import { ComponentPagination, hasMoreItems, HooksService, ScreenService } from '@app/core' import { VideoChannel, VideoChannelService } from '@app/shared/shared-main' import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist' @@ -9,7 +9,7 @@ import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-pl templateUrl: './video-channel-playlists.component.html', styleUrls: [ './video-channel-playlists.component.scss' ] }) -export class VideoChannelPlaylistsComponent implements OnInit, OnDestroy { +export class VideoChannelPlaylistsComponent implements OnInit, AfterViewInit, OnDestroy { videoPlaylists: VideoPlaylist[] = [] pagination: ComponentPagination = { @@ -26,16 +26,24 @@ export class VideoChannelPlaylistsComponent implements OnInit, OnDestroy { constructor ( private videoPlaylistService: VideoPlaylistService, private videoChannelService: VideoChannelService, - private screenService: ScreenService + private screenService: ScreenService, + private hooks: HooksService ) {} ngOnInit () { // Parent get the video channel for us this.videoChannelSub = this.videoChannelService.videoChannelLoaded - .subscribe(videoChannel => { - this.videoChannel = videoChannel - this.loadVideoPlaylists() - }) + .subscribe(videoChannel => { + this.videoChannel = videoChannel + + this.hooks.runAction('action:video-channel-playlists.video-channel.loaded', 'video-channel', { videoChannel }) + + this.loadVideoPlaylists() + }) + } + + ngAfterViewInit () { + this.hooks.runAction('action:video-channel-playlists.init', 'video-channel') } ngOnDestroy () { @@ -55,11 +63,13 @@ export class VideoChannelPlaylistsComponent implements OnInit, OnDestroy { private loadVideoPlaylists () { this.videoPlaylistService.listChannelPlaylists(this.videoChannel, this.pagination) - .subscribe(res => { - this.videoPlaylists = this.videoPlaylists.concat(res.data) - this.pagination.totalItems = res.total + .subscribe(res => { + this.videoPlaylists = this.videoPlaylists.concat(res.data) + this.pagination.totalItems = res.total - this.onDataSubject.next(res.data) - }) + this.hooks.runAction('action:video-channel-playlists.playlists.loaded', 'video-channel', { playlists: this.videoPlaylists }) + + this.onDataSubject.next(res.data) + }) } } diff --git a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.html b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.html index 0a6c5fcb2..9e9e98c99 100644 --- a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.html +++ b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.html @@ -19,5 +19,7 @@ [loadUserVideoPreferences]="true" [disabled]="disabled" + + (videosLoaded)="onVideosLoaded($event)" > diff --git a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts index 43fce475d..5e3946bf5 100644 --- a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts +++ b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts @@ -1,16 +1,16 @@ import { Subscription } from 'rxjs' import { first } from 'rxjs/operators' -import { Component, OnDestroy, OnInit } from '@angular/core' -import { ComponentPaginationLight, DisableForReuseHook, ScreenService } from '@app/core' +import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core' +import { ComponentPaginationLight, DisableForReuseHook, HooksService, ScreenService } from '@app/core' import { VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main' import { MiniatureDisplayOptions, VideoFilters } from '@app/shared/shared-video-miniature' -import { VideoSortField } from '@shared/models/videos' +import { Video, VideoSortField } from '@shared/models' @Component({ selector: 'my-video-channel-videos', templateUrl: './video-channel-videos.component.html' }) -export class VideoChannelVideosComponent implements OnInit, OnDestroy, DisableForReuseHook { +export class VideoChannelVideosComponent implements OnInit, AfterViewInit, OnDestroy, DisableForReuseHook { getVideosObservableFunction = this.getVideosObservable.bind(this) getSyndicationItemsFunction = this.getSyndicationItems.bind(this) @@ -36,7 +36,8 @@ export class VideoChannelVideosComponent implements OnInit, OnDestroy, DisableFo constructor ( private screenService: ScreenService, private videoChannelService: VideoChannelService, - private videoService: VideoService + private videoService: VideoService, + private hooks: HooksService ) { } @@ -45,9 +46,15 @@ export class VideoChannelVideosComponent implements OnInit, OnDestroy, DisableFo this.videoChannelService.videoChannelLoaded.pipe(first()) .subscribe(videoChannel => { this.videoChannel = videoChannel + + this.hooks.runAction('action:video-channel-videos.video-channel.loaded', 'video-channel', { videoChannel }) }) } + ngAfterViewInit () { + this.hooks.runAction('action:video-channel-videos.init', 'video-channel') + } + ngOnDestroy () { if (this.videoChannelSub) this.videoChannelSub.unsubscribe() } @@ -79,4 +86,8 @@ export class VideoChannelVideosComponent implements OnInit, OnDestroy, DisableFo enabledForReuse () { this.disabled = false } + + onVideosLoaded (videos: Video[]) { + this.hooks.runAction('action:video-channel-videos.videos.loaded', 'video-channel', { videos }) + } } diff --git a/client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts b/client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts index 108ad63e3..28edcfdcb 100644 --- a/client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts +++ b/client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts @@ -139,7 +139,7 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy { this.onDataSubject.next(res.data) - setTimeout(() => this.hooks.runAction('action:video-watch.video-threads.loaded', 'video-watch', { data: this.componentPagination })) + this.hooks.runAction('action:video-watch.video-threads.loaded', 'video-watch', { data: this.componentPagination }) }, error: err => this.notifier.error(err.message) diff --git a/client/src/app/core/plugins/hooks.service.ts b/client/src/app/core/plugins/hooks.service.ts index 7fd56d92e..29db75d89 100644 --- a/client/src/app/core/plugins/hooks.service.ts +++ b/client/src/app/core/plugins/hooks.service.ts @@ -49,9 +49,12 @@ export class HooksService { } runAction (hookName: U, scope: PluginClientScope, params?: T) { - this.pluginService.ensurePluginsAreLoaded(scope) + // Use setTimeout to give priority to Angular change detector + setTimeout(() => { + this.pluginService.ensurePluginsAreLoaded(scope) .then(() => this.pluginService.runHook(hookName, undefined, params)) .catch((err: any) => logger.error('Fatal hook error.', err)) + }) } async wrapObject (result: T, scope: PluginClientScope, hookName: U) { diff --git a/client/src/app/shared/shared-video-miniature/videos-list.component.ts b/client/src/app/shared/shared-video-miniature/videos-list.component.ts index 508a189fd..d5cdd958e 100644 --- a/client/src/app/shared/shared-video-miniature/videos-list.component.ts +++ b/client/src/app/shared/shared-video-miniature/videos-list.component.ts @@ -76,6 +76,7 @@ export class VideosListComponent implements OnInit, OnChanges, OnDestroy { @Input() disabled = false @Output() filtersChanged = new EventEmitter() + @Output() videosLoaded = new EventEmitter() videos: Video[] = [] filters: VideoFilters @@ -241,6 +242,7 @@ export class VideosListComponent implements OnInit, OnChanges, OnDestroy { if (this.groupByDate) this.buildGroupedDateLabels() this.onDataSubject.next(data) + this.videosLoaded.emit(this.videos) }, error: err => { diff --git a/client/src/root-helpers/plugins-manager.ts b/client/src/root-helpers/plugins-manager.ts index 300f174b4..6c64e2b01 100644 --- a/client/src/root-helpers/plugins-manager.ts +++ b/client/src/root-helpers/plugins-manager.ts @@ -69,7 +69,8 @@ class PluginsManager { login: new ReplaySubject(1), 'video-edit': new ReplaySubject(1), embed: new ReplaySubject(1), - 'my-library': new ReplaySubject(1) + 'my-library': new ReplaySubject(1), + 'video-channel': new ReplaySubject(1) } private readonly peertubeHelpersFactory: PeertubeHelpersFactory diff --git a/shared/models/plugins/client/client-hook.model.ts b/shared/models/plugins/client/client-hook.model.ts index 466be8946..dda03124d 100644 --- a/shared/models/plugins/client/client-hook.model.ts +++ b/shared/models/plugins/client/client-hook.model.ts @@ -93,6 +93,23 @@ export const clientActionHookObject = { // Fired when a user click on 'View x replies' and they're loaded 'action:video-watch.video-thread-replies.loaded': true, + // Fired when the video channel creation page is being initialized + 'action:video-channel-create.init': true, + + // Fired when the video channel update page is being initialized + 'action:video-channel-update.init': true, + 'action:video-channel-update.video-channel.loaded': true, + + // Fired when the page that list video channel videos is being initialized + 'action:video-channel-videos.init': true, + 'action:video-channel-videos.video-channel.loaded': true, + 'action:video-channel-videos.videos.loaded': true, + + // Fired when the page that list video channel playlists is being initialized + 'action:video-channel-playlists.init': true, + 'action:video-channel-playlists.video-channel.loaded': true, + 'action:video-channel-playlists.playlists.loaded': true, + // Fired when the video edit page (upload, URL/torrent import, update) is being initialized 'action:video-edit.init': true, diff --git a/shared/models/plugins/client/plugin-client-scope.type.ts b/shared/models/plugins/client/plugin-client-scope.type.ts index 92734533d..c09a453b8 100644 --- a/shared/models/plugins/client/plugin-client-scope.type.ts +++ b/shared/models/plugins/client/plugin-client-scope.type.ts @@ -7,4 +7,5 @@ export type PluginClientScope = 'embed' | 'video-edit' | 'admin-plugin' | - 'my-library' + 'my-library' | + 'video-channel'