Support plugin hooks in embed
This commit is contained in:
parent
a9f6802e7d
commit
f95628636b
|
@ -7,38 +7,22 @@ import { Notifier } from '@app/core/notification'
|
||||||
import { MarkdownService } from '@app/core/renderer'
|
import { MarkdownService } from '@app/core/renderer'
|
||||||
import { RestExtractor } from '@app/core/rest'
|
import { RestExtractor } from '@app/core/rest'
|
||||||
import { ServerService } from '@app/core/server/server.service'
|
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 { 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 { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n'
|
||||||
import { getHookType, internalRunHook } from '@shared/core-utils/plugins/hooks'
|
|
||||||
import {
|
import {
|
||||||
ClientHook,
|
ClientHook,
|
||||||
ClientHookName,
|
ClientHookName,
|
||||||
clientHookObject,
|
|
||||||
ClientScript,
|
|
||||||
PluginClientScope,
|
PluginClientScope,
|
||||||
PluginTranslation,
|
PluginTranslation,
|
||||||
PluginType,
|
PluginType,
|
||||||
PublicServerSetting,
|
PublicServerSetting,
|
||||||
RegisterClientHookOptions,
|
|
||||||
ServerConfigPlugin
|
ServerConfigPlugin
|
||||||
} from '@shared/models'
|
} from '@shared/models'
|
||||||
import { environment } from '../../../environments/environment'
|
import { environment } from '../../../environments/environment'
|
||||||
import { ClientScript as ClientScriptModule } from '../../../types/client-script.model'
|
|
||||||
import { RegisterClientHelpers } from '../../../types/register-client-option.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()
|
@Injectable()
|
||||||
export class PluginService implements ClientHook {
|
export class PluginService implements ClientHook {
|
||||||
private static BASE_PLUGIN_API_URL = environment.apiUrl + '/api/v1/plugins'
|
private static BASE_PLUGIN_API_URL = environment.apiUrl + '/api/v1/plugins'
|
||||||
|
@ -51,7 +35,8 @@ export class PluginService implements ClientHook {
|
||||||
search: new ReplaySubject<boolean>(1),
|
search: new ReplaySubject<boolean>(1),
|
||||||
'video-watch': new ReplaySubject<boolean>(1),
|
'video-watch': new ReplaySubject<boolean>(1),
|
||||||
signup: new ReplaySubject<boolean>(1),
|
signup: new ReplaySubject<boolean>(1),
|
||||||
login: new ReplaySubject<boolean>(1)
|
login: new ReplaySubject<boolean>(1),
|
||||||
|
embed: new ReplaySubject<boolean>(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
translationsObservable: Observable<PluginTranslation>
|
translationsObservable: Observable<PluginTranslation>
|
||||||
|
@ -64,7 +49,7 @@ export class PluginService implements ClientHook {
|
||||||
private loadedScopes: PluginClientScope[] = []
|
private loadedScopes: PluginClientScope[] = []
|
||||||
private loadingScopes: { [id in PluginClientScope]?: boolean } = {}
|
private loadingScopes: { [id in PluginClientScope]?: boolean } = {}
|
||||||
|
|
||||||
private hooks: { [ name: string ]: HookStructValue[] } = {}
|
private hooks: Hooks = {}
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
@ -120,7 +105,7 @@ export class PluginService implements ClientHook {
|
||||||
this.scopes[scope].push({
|
this.scopes[scope].push({
|
||||||
plugin,
|
plugin,
|
||||||
clientScript: {
|
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
|
scopes: clientScript.scopes
|
||||||
},
|
},
|
||||||
pluginType: isTheme ? PluginType.THEME : PluginType.PLUGIN,
|
pluginType: isTheme ? PluginType.THEME : PluginType.PLUGIN,
|
||||||
|
@ -184,20 +169,8 @@ export class PluginService implements ClientHook {
|
||||||
}
|
}
|
||||||
|
|
||||||
runHook <T> (hookName: ClientHookName, result?: T, params?: any): Promise<T> {
|
runHook <T> (hookName: ClientHookName, result?: T, params?: any): Promise<T> {
|
||||||
return this.zone.runOutsideAngular(async () => {
|
return this.zone.runOutsideAngular(() => {
|
||||||
if (!this.hooks[ hookName ]) return result
|
return runHook(this.hooks, hookName, result, params)
|
||||||
|
|
||||||
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
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,34 +189,8 @@ export class PluginService implements ClientHook {
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadPlugin (pluginInfo: PluginInfo) {
|
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 this.zone.runOutsideAngular(() => {
|
||||||
return importModule(clientScript.script)
|
return loadPlugin(this.hooks, pluginInfo, pluginInfo => this.buildPeerTubeHelpers(pluginInfo))
|
||||||
.then((script: ClientScriptModule) => script.register({ registerHook, peertubeHelpers }))
|
|
||||||
.then(() => this.sortHooksByPriority())
|
|
||||||
.catch(err => console.error('Cannot import or register plugin %s.', pluginInfo.plugin.name, err))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
private buildPeerTubeHelpers (pluginInfo: PluginInfo): RegisterClientHelpers {
|
||||||
const { plugin } = pluginInfo
|
const { plugin } = pluginInfo
|
||||||
const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType)
|
const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType)
|
||||||
|
|
|
@ -148,41 +148,6 @@ function scrollToTop () {
|
||||||
window.scroll(0, 0)
|
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) {
|
function isInViewport (el: HTMLElement) {
|
||||||
const bounding = el.getBoundingClientRect()
|
const bounding = el.getBoundingClientRect()
|
||||||
return (
|
return (
|
||||||
|
@ -216,7 +181,6 @@ export {
|
||||||
getAbsoluteEmbedUrl,
|
getAbsoluteEmbedUrl,
|
||||||
objectLineFeedToHtml,
|
objectLineFeedToHtml,
|
||||||
removeElementFromArray,
|
removeElementFromArray,
|
||||||
importModule,
|
|
||||||
scrollToTop,
|
scrollToTop,
|
||||||
isInViewport,
|
isInViewport,
|
||||||
isXPercentInViewport
|
isXPercentInViewport
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
import 'core-js/features/reflect'
|
import 'core-js/features/reflect'
|
||||||
|
|
||||||
export const environment = {
|
export const environment = {
|
||||||
production: false,
|
production: true,
|
||||||
hmr: false,
|
hmr: false,
|
||||||
apiUrl: 'http://localhost:9000',
|
apiUrl: '',
|
||||||
embedUrl: 'http://localhost:9000'
|
embedUrl: ''
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
import { getHookType, internalRunHook } from '@shared/core-utils/plugins/hooks'
|
||||||
|
import { ClientHookName, ClientScript, RegisterClientHookOptions, ServerConfigPlugin, PluginType, clientHookObject } from '../../../shared/models'
|
||||||
|
import { RegisterClientHelpers } from 'src/types/register-client-option.model'
|
||||||
|
import { ClientScript as ClientScriptModule } from '../types/client-script.model'
|
||||||
|
import { importModule } from './utils'
|
||||||
|
|
||||||
|
interface HookStructValue extends RegisterClientHookOptions {
|
||||||
|
plugin: ServerConfigPlugin
|
||||||
|
clientScript: ClientScript
|
||||||
|
}
|
||||||
|
|
||||||
|
type Hooks = { [ name: string ]: HookStructValue[] }
|
||||||
|
|
||||||
|
type PluginInfo = {
|
||||||
|
plugin: ServerConfigPlugin
|
||||||
|
clientScript: ClientScript
|
||||||
|
pluginType: PluginType
|
||||||
|
isTheme: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runHook<T> (hooks: Hooks, hookName: ClientHookName, result?: T, params?: any) {
|
||||||
|
if (!hooks[hookName]) return result
|
||||||
|
|
||||||
|
const hookType = getHookType(hookName)
|
||||||
|
|
||||||
|
for (const hook of 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
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadPlugin (hooks: Hooks, pluginInfo: PluginInfo, peertubeHelpersFactory: (pluginInfo: PluginInfo) => RegisterClientHelpers) {
|
||||||
|
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 (!hooks[options.target]) hooks[options.target] = []
|
||||||
|
|
||||||
|
hooks[options.target].push({
|
||||||
|
plugin,
|
||||||
|
clientScript,
|
||||||
|
target: options.target,
|
||||||
|
handler: options.handler,
|
||||||
|
priority: options.priority || 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const peertubeHelpers = peertubeHelpersFactory(pluginInfo)
|
||||||
|
|
||||||
|
console.log('Loading script %s of plugin %s.', clientScript.script, plugin.name)
|
||||||
|
|
||||||
|
return importModule(clientScript.script)
|
||||||
|
.then((script: ClientScriptModule) => script.register({ registerHook, peertubeHelpers }))
|
||||||
|
.then(() => sortHooksByPriority(hooks))
|
||||||
|
.catch(err => console.error('Cannot import or register plugin %s.', pluginInfo.plugin.name, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
HookStructValue,
|
||||||
|
Hooks,
|
||||||
|
PluginInfo,
|
||||||
|
loadPlugin,
|
||||||
|
runHook
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortHooksByPriority (hooks: Hooks) {
|
||||||
|
for (const hookName of Object.keys(hooks)) {
|
||||||
|
hooks[hookName].sort((a, b) => {
|
||||||
|
return b.priority - a.priority
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { environment } from '../environments/environment'
|
||||||
|
|
||||||
function objectToUrlEncoded (obj: any) {
|
function objectToUrlEncoded (obj: any) {
|
||||||
const str: string[] = []
|
const str: string[] = []
|
||||||
for (const key of Object.keys(obj)) {
|
for (const key of Object.keys(obj)) {
|
||||||
|
@ -7,6 +9,42 @@ function objectToUrlEncoded (obj: any) {
|
||||||
return str.join('&')
|
return str.join('&')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
importModule,
|
||||||
objectToUrlEncoded
|
objectToUrlEncoded
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import './embed.scss'
|
import './embed.scss'
|
||||||
import videojs from 'video.js'
|
import videojs from 'video.js'
|
||||||
import { objectToUrlEncoded, peertubeLocalStorage } from '@root-helpers/index'
|
|
||||||
import { Tokens } from '@root-helpers/users'
|
|
||||||
import { peertubeTranslate } from '../../../../shared/core-utils/i18n'
|
import { peertubeTranslate } from '../../../../shared/core-utils/i18n'
|
||||||
import {
|
import {
|
||||||
ResultList,
|
ResultList,
|
||||||
|
@ -11,12 +9,19 @@ import {
|
||||||
VideoDetails,
|
VideoDetails,
|
||||||
VideoPlaylist,
|
VideoPlaylist,
|
||||||
VideoPlaylistElement,
|
VideoPlaylistElement,
|
||||||
VideoStreamingPlaylistType
|
VideoStreamingPlaylistType,
|
||||||
|
PluginType,
|
||||||
|
ClientHookName
|
||||||
} from '../../../../shared/models'
|
} from '../../../../shared/models'
|
||||||
import { P2PMediaLoaderOptions, PeertubePlayerManagerOptions, PlayerMode } from '../../assets/player/peertube-player-manager'
|
import { P2PMediaLoaderOptions, PeertubePlayerManagerOptions, PlayerMode } from '../../assets/player/peertube-player-manager'
|
||||||
import { VideoJSCaption } from '../../assets/player/peertube-videojs-typings'
|
import { VideoJSCaption } from '../../assets/player/peertube-videojs-typings'
|
||||||
import { TranslationsManager } from '../../assets/player/translations-manager'
|
import { TranslationsManager } from '../../assets/player/translations-manager'
|
||||||
|
import { Hooks, loadPlugin, runHook } from '../../root-helpers/plugins'
|
||||||
|
import { Tokens } from '../../root-helpers/users'
|
||||||
|
import { peertubeLocalStorage } from '../../root-helpers/peertube-web-storage'
|
||||||
|
import { objectToUrlEncoded } from '../../root-helpers/utils'
|
||||||
import { PeerTubeEmbedApi } from './embed-api'
|
import { PeerTubeEmbedApi } from './embed-api'
|
||||||
|
import { RegisterClientHelpers } from '../../types/register-client-option.model'
|
||||||
|
|
||||||
type Translations = { [ id: string ]: string }
|
type Translations = { [ id: string ]: string }
|
||||||
|
|
||||||
|
@ -60,6 +65,9 @@ export class PeerTubeEmbed {
|
||||||
|
|
||||||
private wrapperElement: HTMLElement
|
private wrapperElement: HTMLElement
|
||||||
|
|
||||||
|
private peertubeHooks: Hooks = {}
|
||||||
|
private loadedScripts = new Set<string>()
|
||||||
|
|
||||||
static async main () {
|
static async main () {
|
||||||
const videoContainerId = 'video-wrapper'
|
const videoContainerId = 'video-wrapper'
|
||||||
const embed = new PeerTubeEmbed(videoContainerId)
|
const embed = new PeerTubeEmbed(videoContainerId)
|
||||||
|
@ -473,6 +481,8 @@ export class PeerTubeEmbed {
|
||||||
this.PeertubePlayerManagerModulePromise
|
this.PeertubePlayerManagerModulePromise
|
||||||
])
|
])
|
||||||
|
|
||||||
|
await this.ensurePluginsAreLoaded(config, serverTranslations)
|
||||||
|
|
||||||
const videoInfo: VideoDetails = videoInfoTmp
|
const videoInfo: VideoDetails = videoInfoTmp
|
||||||
|
|
||||||
const PeertubePlayerManager = PeertubePlayerManagerModule.PeertubePlayerManager
|
const PeertubePlayerManager = PeertubePlayerManagerModule.PeertubePlayerManager
|
||||||
|
@ -577,6 +587,8 @@ export class PeerTubeEmbed {
|
||||||
this.playNextVideo()
|
this.playNextVideo()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.runHook('action:embed.player.loaded', undefined, { player: this.player })
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initCore () {
|
private async initCore () {
|
||||||
|
@ -714,6 +726,69 @@ export class PeerTubeEmbed {
|
||||||
private isPlaylistEmbed () {
|
private isPlaylistEmbed () {
|
||||||
return window.location.pathname.split('/')[1] === 'video-playlists'
|
return window.location.pathname.split('/')[1] === 'video-playlists'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async ensurePluginsAreLoaded (config: ServerConfig, translations?: { [ id: string ]: string }) {
|
||||||
|
if (config.plugin.registered.length === 0) return
|
||||||
|
|
||||||
|
for (const plugin of config.plugin.registered) {
|
||||||
|
for (const key of Object.keys(plugin.clientScripts)) {
|
||||||
|
const clientScript = plugin.clientScripts[key]
|
||||||
|
|
||||||
|
if (clientScript.scopes.includes('embed') === false) continue
|
||||||
|
|
||||||
|
const script = `/plugins/${plugin.name}/${plugin.version}/client-scripts/${clientScript.script}`
|
||||||
|
|
||||||
|
if (this.loadedScripts.has(script)) continue
|
||||||
|
|
||||||
|
const pluginInfo = {
|
||||||
|
plugin,
|
||||||
|
clientScript: {
|
||||||
|
script,
|
||||||
|
scopes: clientScript.scopes
|
||||||
|
},
|
||||||
|
pluginType: PluginType.PLUGIN,
|
||||||
|
isTheme: false
|
||||||
|
}
|
||||||
|
|
||||||
|
await loadPlugin(this.peertubeHooks, pluginInfo, _ => this.buildPeerTubeHelpers(translations))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildPeerTubeHelpers (translations?: { [ id: string ]: string }): RegisterClientHelpers {
|
||||||
|
function unimplemented (): any {
|
||||||
|
throw new Error('This helper is not implemented in embed.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
getBaseStaticRoute: unimplemented,
|
||||||
|
|
||||||
|
getSettings: unimplemented,
|
||||||
|
|
||||||
|
isLoggedIn: unimplemented,
|
||||||
|
|
||||||
|
notifier: {
|
||||||
|
info: unimplemented,
|
||||||
|
error: unimplemented,
|
||||||
|
success: unimplemented
|
||||||
|
},
|
||||||
|
|
||||||
|
showModal: unimplemented,
|
||||||
|
|
||||||
|
markdownRenderer: {
|
||||||
|
textMarkdownToHTML: unimplemented,
|
||||||
|
enhancedMarkdownToHTML: unimplemented
|
||||||
|
},
|
||||||
|
|
||||||
|
translate: (value: string) => {
|
||||||
|
return Promise.resolve(peertubeTranslate(value, translations))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private runHook <T> (hookName: ClientHookName, result?: T, params?: any): Promise<T> {
|
||||||
|
return runHook(this.peertubeHooks, hookName, result, params)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerTubeEmbed.main()
|
PeerTubeEmbed.main()
|
||||||
|
|
|
@ -80,7 +80,13 @@ export const clientActionHookObject = {
|
||||||
'action:router.navigation-end': true,
|
'action:router.navigation-end': true,
|
||||||
|
|
||||||
// Fired when the registration page is being initialized
|
// Fired when the registration page is being initialized
|
||||||
'action:signup.register.init': true
|
'action:signup.register.init': true,
|
||||||
|
|
||||||
|
// ####### Embed hooks #######
|
||||||
|
// In embed scope, peertube helpers are not available
|
||||||
|
|
||||||
|
// Fired when the embed loaded the player
|
||||||
|
'action:embed.player.loaded': true
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ClientActionHookName = keyof typeof clientActionHookObject
|
export type ClientActionHookName = keyof typeof clientActionHookObject
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export type PluginClientScope = 'common' | 'video-watch' | 'search' | 'signup' | 'login'
|
export type PluginClientScope = 'common' | 'video-watch' | 'search' | 'signup' | 'login' | 'embed'
|
||||||
|
|
Loading…
Reference in New Issue