From f95628636b6ccdf3eae2449ca718e075b072f678 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 20 Aug 2020 11:46:25 +0200 Subject: Support plugin hooks in embed --- client/src/app/core/plugins/plugin.service.ts | 79 +++------------------------ client/src/app/helpers/utils.ts | 36 ------------ 2 files changed, 9 insertions(+), 106 deletions(-) (limited to 'client/src/app') diff --git a/client/src/app/core/plugins/plugin.service.ts b/client/src/app/core/plugins/plugin.service.ts index dc115c0e1..871613b89 100644 --- a/client/src/app/core/plugins/plugin.service.ts +++ b/client/src/app/core/plugins/plugin.service.ts @@ -7,38 +7,22 @@ import { Notifier } from '@app/core/notification' import { MarkdownService } from '@app/core/renderer' import { RestExtractor } from '@app/core/rest' import { ServerService } from '@app/core/server/server.service' -import { getDevLocale, importModule, isOnDevLocale } from '@app/helpers' +import { getDevLocale, isOnDevLocale } from '@app/helpers' import { CustomModalComponent } from '@app/modal/custom-modal.component' +import { Hooks, loadPlugin, PluginInfo, runHook } from '@root-helpers/plugins' import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n' -import { getHookType, internalRunHook } from '@shared/core-utils/plugins/hooks' import { ClientHook, ClientHookName, - clientHookObject, - ClientScript, PluginClientScope, PluginTranslation, PluginType, PublicServerSetting, - RegisterClientHookOptions, ServerConfigPlugin } from '@shared/models' import { environment } from '../../../environments/environment' -import { ClientScript as ClientScriptModule } from '../../../types/client-script.model' import { RegisterClientHelpers } from '../../../types/register-client-option.model' -interface HookStructValue extends RegisterClientHookOptions { - plugin: ServerConfigPlugin - clientScript: ClientScript -} - -type PluginInfo = { - plugin: ServerConfigPlugin - clientScript: ClientScript - pluginType: PluginType - isTheme: boolean -} - @Injectable() export class PluginService implements ClientHook { private static BASE_PLUGIN_API_URL = environment.apiUrl + '/api/v1/plugins' @@ -51,7 +35,8 @@ export class PluginService implements ClientHook { search: new ReplaySubject(1), 'video-watch': new ReplaySubject(1), signup: new ReplaySubject(1), - login: new ReplaySubject(1) + login: new ReplaySubject(1), + embed: new ReplaySubject(1) } translationsObservable: Observable @@ -64,7 +49,7 @@ export class PluginService implements ClientHook { private loadedScopes: PluginClientScope[] = [] private loadingScopes: { [id in PluginClientScope]?: boolean } = {} - private hooks: { [ name: string ]: HookStructValue[] } = {} + private hooks: Hooks = {} constructor ( private authService: AuthService, @@ -120,7 +105,7 @@ export class PluginService implements ClientHook { this.scopes[scope].push({ plugin, clientScript: { - script: environment.apiUrl + `${pathPrefix}/${plugin.name}/${plugin.version}/client-scripts/${clientScript.script}`, + script: `${pathPrefix}/${plugin.name}/${plugin.version}/client-scripts/${clientScript.script}`, scopes: clientScript.scopes }, pluginType: isTheme ? PluginType.THEME : PluginType.PLUGIN, @@ -184,20 +169,8 @@ export class PluginService implements ClientHook { } runHook (hookName: ClientHookName, result?: T, params?: any): Promise { - return this.zone.runOutsideAngular(async () => { - if (!this.hooks[ hookName ]) return result - - const hookType = getHookType(hookName) - - for (const hook of this.hooks[ hookName ]) { - console.log('Running hook %s of plugin %s.', hookName, hook.plugin.name) - - result = await internalRunHook(hook.handler, hookType, result, params, err => { - console.error('Cannot run hook %s of script %s of plugin %s.', hookName, hook.clientScript.script, hook.plugin.name, err) - }) - } - - return result + return this.zone.runOutsideAngular(() => { + return runHook(this.hooks, hookName, result, params) }) } @@ -216,34 +189,8 @@ export class PluginService implements ClientHook { } private loadPlugin (pluginInfo: PluginInfo) { - const { plugin, clientScript } = pluginInfo - - const registerHook = (options: RegisterClientHookOptions) => { - if (clientHookObject[options.target] !== true) { - console.error('Unknown hook %s of plugin %s. Skipping.', options.target, plugin.name) - return - } - - if (!this.hooks[options.target]) this.hooks[options.target] = [] - - this.hooks[options.target].push({ - plugin, - clientScript, - target: options.target, - handler: options.handler, - priority: options.priority || 0 - }) - } - - const peertubeHelpers = this.buildPeerTubeHelpers(pluginInfo) - - console.log('Loading script %s of plugin %s.', clientScript.script, plugin.name) - return this.zone.runOutsideAngular(() => { - return importModule(clientScript.script) - .then((script: ClientScriptModule) => script.register({ registerHook, peertubeHelpers })) - .then(() => this.sortHooksByPriority()) - .catch(err => console.error('Cannot import or register plugin %s.', pluginInfo.plugin.name, err)) + return loadPlugin(this.hooks, pluginInfo, pluginInfo => this.buildPeerTubeHelpers(pluginInfo)) }) } @@ -253,14 +200,6 @@ export class PluginService implements ClientHook { } } - private sortHooksByPriority () { - for (const hookName of Object.keys(this.hooks)) { - this.hooks[hookName].sort((a, b) => { - return b.priority - a.priority - }) - } - } - private buildPeerTubeHelpers (pluginInfo: PluginInfo): RegisterClientHelpers { const { plugin } = pluginInfo const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType) diff --git a/client/src/app/helpers/utils.ts b/client/src/app/helpers/utils.ts index d05541ca9..d9007dd77 100644 --- a/client/src/app/helpers/utils.ts +++ b/client/src/app/helpers/utils.ts @@ -148,41 +148,6 @@ function scrollToTop () { window.scroll(0, 0) } -// Thanks: https://github.com/uupaa/dynamic-import-polyfill -function importModule (path: string) { - return new Promise((resolve, reject) => { - const vector = '$importModule$' + Math.random().toString(32).slice(2) - const script = document.createElement('script') - - const destructor = () => { - delete window[ vector ] - script.onerror = null - script.onload = null - script.remove() - URL.revokeObjectURL(script.src) - script.src = '' - } - - script.defer = true - script.type = 'module' - - script.onerror = () => { - reject(new Error(`Failed to import: ${path}`)) - destructor() - } - script.onload = () => { - resolve(window[ vector ]) - destructor() - } - const absURL = (environment.apiUrl || window.location.origin) + path - const loader = `import * as m from "${absURL}"; window.${vector} = m;` // export Module - const blob = new Blob([ loader ], { type: 'text/javascript' }) - script.src = URL.createObjectURL(blob) - - document.head.appendChild(script) - }) -} - function isInViewport (el: HTMLElement) { const bounding = el.getBoundingClientRect() return ( @@ -216,7 +181,6 @@ export { getAbsoluteEmbedUrl, objectLineFeedToHtml, removeElementFromArray, - importModule, scrollToTop, isInViewport, isXPercentInViewport -- cgit v1.2.3