]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Add channel hooks
authorChocobozzz <me@florianbigard.com>
Wed, 3 Aug 2022 08:39:40 +0000 (10:39 +0200)
committerChocobozzz <me@florianbigard.com>
Wed, 3 Aug 2022 08:39:40 +0000 (10:39 +0200)
12 files changed:
client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts
client/src/app/+manage/video-channel-edit/video-channel-create.component.ts
client/src/app/+manage/video-channel-edit/video-channel-update.component.ts
client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts
client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.html
client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts
client/src/app/core/plugins/hooks.service.ts
client/src/app/shared/shared-video-miniature/videos-list.component.ts
client/src/root-helpers/plugins-manager.ts
shared/models/plugins/client/client-hook.model.ts
shared/models/plugins/client/plugin-client-scope.type.ts

index 1a40f6c651864143adcb0529d5ef21b473cfb530..ec02cfcd9a344b89afe9e7efa08d7d3266879f16 100644 (file)
@@ -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) {
index 5f8e0278e3c2fd78c85c78e2115c7c684d376ebc..8211451a402d3d6ad69ccd6bb47e724c56c5c3bf 100644 (file)
@@ -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
 
index 6b494791273671b6608f6a8a8a344f6fdeab9d58..7e8d6ffe68eb8c734602d99e4ab86055325239c0 100644 (file)
@@ -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()
   }
index 14465bb8dd6947b52816a560b54c3eacfd0b402b..82af650265be57d0ed98fe752f9e3998981f0a4d 100644 (file)
@@ -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.hooks.runAction('action:video-channel-playlists.playlists.loaded', 'video-channel', { playlists: this.videoPlaylists })
 
-          this.onDataSubject.next(res.data)
-        })
+        this.onDataSubject.next(res.data)
+      })
   }
 }
index 0a6c5fcb2cd0de56aa241c068929da173bc9c6a6..9e9e98c99b6aca6ac8f4eeec1f76a108ae2b3fab 100644 (file)
@@ -19,5 +19,7 @@
   [loadUserVideoPreferences]="true"
 
   [disabled]="disabled"
+
+  (videosLoaded)="onVideosLoaded($event)"
 >
 </my-videos-list>
index 43fce475d2422709c330e26ac38d1da6263090cf..5e3946bf5e93937204135e0c08244ee55c760afa 100644 (file)
@@ -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 })
+  }
 }
index 108ad63e33fac46387d582477dbf1e7e831aed86..28edcfdcb8d24869a7bacdb3422eeaf9e535c9ba 100644 (file)
@@ -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)
index 7fd56d92e833a980eb3177fb2b59507eb0f6b536..29db75d89bea8b7d24ddb073d517cdb4bee4fc6f 100644 (file)
@@ -49,9 +49,12 @@ export class HooksService {
   }
 
   runAction<T, U extends ClientActionHookName> (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<T, U extends ClientFilterHookName> (result: T, scope: PluginClientScope, hookName: U) {
index 508a189fdaaf5fa6ccdff4fa49040b02481f96a9..d5cdd958e1dbd1fa3d2986f5233b2466731196da 100644 (file)
@@ -76,6 +76,7 @@ export class VideosListComponent implements OnInit, OnChanges, OnDestroy {
   @Input() disabled = false
 
   @Output() filtersChanged = new EventEmitter<VideoFilters>()
+  @Output() videosLoaded = new EventEmitter<Video[]>()
 
   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 => {
index 300f174b42a6d5e8209a08642a593007f382e4d7..6c64e2b014167f3559a74d1180e265a8f2737c47 100644 (file)
@@ -69,7 +69,8 @@ class PluginsManager {
     login: new ReplaySubject<boolean>(1),
     'video-edit': new ReplaySubject<boolean>(1),
     embed: new ReplaySubject<boolean>(1),
-    'my-library': new ReplaySubject<boolean>(1)
+    'my-library': new ReplaySubject<boolean>(1),
+    'video-channel': new ReplaySubject<boolean>(1)
   }
 
   private readonly peertubeHelpersFactory: PeertubeHelpersFactory
index 466be89466e24f6908538f7c21f29a1956a7a4eb..dda03124d0e68984bfecdd2938892213f3533b8b 100644 (file)
@@ -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,
 
index 92734533df83e3ef4464730cbf782c1494b3f54f..c09a453b863aa52e1bda3be751fad70b6cafe7d8 100644 (file)
@@ -7,4 +7,5 @@ export type PluginClientScope =
   'embed' |
   'video-edit' |
   'admin-plugin' |
-  'my-library'
+  'my-library' |
+  'video-channel'