feat(plugins): add doAction increment/decrement loader

Support for plugins to show application loader.
This commit is contained in:
kontrollanten 2024-10-25 06:10:48 +02:00
parent 8c5c8b7032
commit 373052c2ec
5 changed files with 63 additions and 3 deletions

View File

@ -1,7 +1,7 @@
import { delay, forkJoin } from 'rxjs' import { delay, forkJoin, from } from 'rxjs'
import { filter, first, map } from 'rxjs/operators' import { filter, first, map } from 'rxjs/operators'
import { DOCUMENT, getLocaleDirection, PlatformLocation, NgIf, NgClass } from '@angular/common' import { DOCUMENT, getLocaleDirection, PlatformLocation, NgIf, NgClass } from '@angular/common'
import { AfterViewInit, Component, Inject, LOCALE_ID, OnInit, ViewChild } from '@angular/core' import { AfterViewInit, Component, Inject, LOCALE_ID, OnDestroy, OnInit, ViewChild } from '@angular/core'
import { DomSanitizer, SafeHtml } from '@angular/platform-browser' import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
import { Event, GuardsCheckStart, RouteConfigLoadEnd, RouteConfigLoadStart, Router, RouterLink, RouterOutlet } from '@angular/router' import { Event, GuardsCheckStart, RouteConfigLoadEnd, RouteConfigLoadStart, Router, RouterLink, RouterOutlet } from '@angular/router'
import { import {
@ -65,7 +65,7 @@ import { InstanceService } from './shared/shared-main/instance/instance.service'
CustomModalComponent CustomModalComponent
] ]
}) })
export class AppComponent implements OnInit, AfterViewInit { export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
private static BROADCAST_MESSAGE_KEY = 'app-broadcast-message-dismissed' private static BROADCAST_MESSAGE_KEY = 'app-broadcast-message-dismissed'
@ViewChild('accountSetupWarningModal') accountSetupWarningModal: AccountSetupWarningModalComponent @ViewChild('accountSetupWarningModal') accountSetupWarningModal: AccountSetupWarningModalComponent
@ -152,12 +152,28 @@ export class AppComponent implements OnInit, AfterViewInit {
this.document.documentElement.lang = getShortLocale(this.localeId) this.document.documentElement.lang = getShortLocale(this.localeId)
this.document.documentElement.dir = getLocaleDirection(this.localeId) this.document.documentElement.dir = getLocaleDirection(this.localeId)
this.pluginService.addAction('application:increment-loader', () => {
this.loadingBar.useRef('plugins').start()
return from([])
})
this.pluginService.addAction('application:decrement-loader', () => {
this.loadingBar.useRef('plugins').complete()
return from([])
})
} }
ngAfterViewInit () { ngAfterViewInit () {
this.pluginService.initializeCustomModal(this.customModal) this.pluginService.initializeCustomModal(this.customModal)
} }
ngOnDestroy () {
this.pluginService.removeAction('application:increment-loader')
this.pluginService.removeAction('application:decrement-loader')
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
getDefaultRoute () { getDefaultRoute () {

View File

@ -12,6 +12,8 @@ import { getDevLocale, isOnDevLocale } from '@app/helpers'
import { CustomModalComponent } from '@app/modal/custom-modal.component' import { CustomModalComponent } from '@app/modal/custom-modal.component'
import { getCompleteLocale, getKeys, isDefaultLocale, peertubeTranslate } from '@peertube/peertube-core-utils' import { getCompleteLocale, getKeys, isDefaultLocale, peertubeTranslate } from '@peertube/peertube-core-utils'
import { import {
ClientDoActionCallback,
ClientDoActionName,
ClientHook, ClientHook,
ClientHookName, ClientHookName,
PluginClientScope, PluginClientScope,
@ -28,6 +30,7 @@ import {
import { PluginInfo, PluginsManager } from '@root-helpers/plugins-manager' import { PluginInfo, PluginsManager } from '@root-helpers/plugins-manager'
import { environment } from '../../../environments/environment' import { environment } from '../../../environments/environment'
import { RegisterClientHelpers } from '../../../types/register-client-option.model' import { RegisterClientHelpers } from '../../../types/register-client-option.model'
import { logger } from '@root-helpers/logger'
type FormFields = { type FormFields = {
video: { video: {
@ -58,6 +61,8 @@ export class PluginService implements ClientHook {
private pluginsManager: PluginsManager private pluginsManager: PluginsManager
private actions: { [name in ClientDoActionName]?: ClientDoActionCallback } = {}
constructor ( constructor (
private authService: AuthService, private authService: AuthService,
private notifier: Notifier, private notifier: Notifier,
@ -71,6 +76,7 @@ export class PluginService implements ClientHook {
this.loadTranslations() this.loadTranslations()
this.pluginsManager = new PluginsManager({ this.pluginsManager = new PluginsManager({
doAction: this.doAction.bind(this),
peertubeHelpersFactory: this.buildPeerTubeHelpers.bind(this), peertubeHelpersFactory: this.buildPeerTubeHelpers.bind(this),
onFormFields: this.onFormFields.bind(this), onFormFields: this.onFormFields.bind(this),
onSettingsScripts: this.onSettingsScripts.bind(this), onSettingsScripts: this.onSettingsScripts.bind(this),
@ -78,6 +84,14 @@ export class PluginService implements ClientHook {
}) })
} }
addAction (actionName: ClientDoActionName, callback: ClientDoActionCallback) {
this.actions[actionName] = callback
}
removeAction (actionName: ClientDoActionName) {
delete this.actions[actionName]
}
initializePlugins () { initializePlugins () {
this.pluginsManager.loadPluginsList(this.server.getHTMLConfig()) this.pluginsManager.loadPluginsList(this.server.getHTMLConfig())
@ -184,6 +198,14 @@ export class PluginService implements ClientHook {
return firstValueFrom(obs) return firstValueFrom(obs)
} }
private doAction (actionName: ClientDoActionName) {
try {
return this.actions[actionName]()
} catch (err: any) {
logger.warn(`Plugin tried to do unknown action: ${actionName}`)
}
}
private onFormFields ( private onFormFields (
pluginInfo: PluginInfo, pluginInfo: PluginInfo,
commonOptions: RegisterClientFormFieldOptions, commonOptions: RegisterClientFormFieldOptions,

View File

@ -5,6 +5,7 @@ import { first, shareReplay } from 'rxjs/operators'
import { RegisterClientHelpers } from 'src/types/register-client-option.model' import { RegisterClientHelpers } from 'src/types/register-client-option.model'
import { getExternalAuthHref, getHookType, internalRunHook } from '@peertube/peertube-core-utils' import { getExternalAuthHref, getHookType, internalRunHook } from '@peertube/peertube-core-utils'
import { import {
ClientDoAction,
ClientHookName, ClientHookName,
clientHookObject, clientHookObject,
ClientScriptJSON, ClientScriptJSON,
@ -76,17 +77,20 @@ class PluginsManager {
'admin-comments': new ReplaySubject<boolean>(1) 'admin-comments': new ReplaySubject<boolean>(1)
} }
private readonly doAction: ClientDoAction
private readonly peertubeHelpersFactory: PeertubeHelpersFactory private readonly peertubeHelpersFactory: PeertubeHelpersFactory
private readonly onFormFields: OnFormFields private readonly onFormFields: OnFormFields
private readonly onSettingsScripts: OnSettingsScripts private readonly onSettingsScripts: OnSettingsScripts
private readonly onClientRoute: OnClientRoute private readonly onClientRoute: OnClientRoute
constructor (options: { constructor (options: {
doAction: ClientDoAction
peertubeHelpersFactory: PeertubeHelpersFactory peertubeHelpersFactory: PeertubeHelpersFactory
onFormFields?: OnFormFields onFormFields?: OnFormFields
onSettingsScripts?: OnSettingsScripts onSettingsScripts?: OnSettingsScripts
onClientRoute?: OnClientRoute onClientRoute?: OnClientRoute
}) { }) {
this.doAction = options.doAction
this.peertubeHelpersFactory = options.peertubeHelpersFactory this.peertubeHelpersFactory = options.peertubeHelpersFactory
this.onFormFields = options.onFormFields this.onFormFields = options.onFormFields
this.onSettingsScripts = options.onSettingsScripts this.onSettingsScripts = options.onSettingsScripts
@ -270,6 +274,8 @@ class PluginsManager {
return this.onClientRoute(options) return this.onClientRoute(options)
} }
const doAction = this.doAction
const peertubeHelpers = this.peertubeHelpersFactory(pluginInfo) const peertubeHelpers = this.peertubeHelpersFactory(pluginInfo)
logger.info(`Loading script ${clientScript.script} of plugin ${plugin.name}`) logger.info(`Loading script ${clientScript.script} of plugin ${plugin.name}`)
@ -278,6 +284,7 @@ class PluginsManager {
return dynamicImport(absURL) return dynamicImport(absURL)
.then((script: ClientScript) => { .then((script: ClientScript) => {
return script.register({ return script.register({
doAction,
registerHook, registerHook,
registerVideoField, registerVideoField,
registerSettingsScript, registerSettingsScript,

View File

@ -1,4 +1,5 @@
import { import {
ClientDoAction,
MyUser, MyUser,
RegisterClientFormFieldOptions, RegisterClientFormFieldOptions,
RegisterClientHookOptions, RegisterClientHookOptions,
@ -9,6 +10,8 @@ import {
} from '@peertube/peertube-models' } from '@peertube/peertube-models'
export type RegisterClientOptions = { export type RegisterClientOptions = {
doAction: ClientDoAction
registerHook: (options: RegisterClientHookOptions) => void registerHook: (options: RegisterClientHookOptions) => void
registerVideoField: (commonOptions: RegisterClientFormFieldOptions, videoFormOptions: RegisterClientVideoFieldOptions) => void registerVideoField: (commonOptions: RegisterClientFormFieldOptions, videoFormOptions: RegisterClientVideoFieldOptions) => void

View File

@ -1,3 +1,5 @@
import { Observable } from 'rxjs'
// Data from API hooks: {hookType}:api.{location}.{elementType}.{actionType}.{target} // Data from API hooks: {hookType}:api.{location}.{elementType}.{actionType}.{target}
// Data in internal functions: {hookType}:{location}.{elementType}.{actionType}.{target} // Data in internal functions: {hookType}:{location}.{elementType}.{actionType}.{target}
@ -208,3 +210,13 @@ export type ClientHookName = keyof typeof clientHookObject
export interface ClientHook { export interface ClientHook {
runHook <T> (hookName: ClientHookName, result?: T, params?: any): Promise<T> runHook <T> (hookName: ClientHookName, result?: T, params?: any): Promise<T>
} }
export const clientDoActionObject = {
'application:increment-loader': true,
'application:decrement-loader': true
}
export type ClientDoActionName = keyof typeof clientDoActionObject
export type ClientDoActionCallback = () => Observable<any>
export type ClientDoAction = (actionName: ClientDoActionName) => Observable<any>