--- /dev/null
+export * from './plugin-pages-routing.module'
+export * from './plugin-pages.component'
+export * from './plugin-pages.module'
--- /dev/null
+import { NgModule } from '@angular/core'
+import { RouterModule, Routes } from '@angular/router'
+import { PluginPagesComponent } from './plugin-pages.component'
+
+const pluginPagesRoutes: Routes = [
+ {
+ path: '**',
+ component: PluginPagesComponent,
+ data: {
+ reloadOnSameNavigation: true
+ }
+ }
+]
+
+@NgModule({
+ imports: [ RouterModule.forChild(pluginPagesRoutes) ],
+ exports: [ RouterModule ]
+})
+export class PluginPagesRoutingModule {}
--- /dev/null
+<div #root></div>
--- /dev/null
+import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core'
+import { ActivatedRoute, Router } from '@angular/router'
+import { PluginService } from '@app/core'
+
+@Component({
+ templateUrl: './plugin-pages.component.html'
+})
+export class PluginPagesComponent implements AfterViewInit {
+ @ViewChild('root') root: ElementRef
+
+ constructor (
+ private route: ActivatedRoute,
+ private router: Router,
+ private pluginService: PluginService
+ ) {
+
+ }
+
+ ngAfterViewInit () {
+ const path = '/' + this.route.snapshot.url.map(u => u.path).join('/')
+
+ const registered = this.pluginService.getRegisteredClientRoute(path)
+ if (!registered) {
+ console.log('Could not find registered route %s.', path, this.pluginService.getAllRegisteredClientRoutes())
+
+ return this.router.navigate([ '/404' ], { skipLocationChange: true })
+ }
+
+ registered.onMount({ rootEl: this.root.nativeElement })
+ }
+}
--- /dev/null
+import { NgModule } from '@angular/core'
+import { PluginPagesRoutingModule } from './plugin-pages-routing.module'
+import { PluginPagesComponent } from './plugin-pages.component'
+
+@NgModule({
+ imports: [
+ PluginPagesRoutingModule
+ ],
+
+ declarations: [
+ PluginPagesComponent
+ ],
+
+ exports: [
+ PluginPagesComponent
+ ],
+
+ providers: [
+ ]
+})
+export class PluginPagesModule { }
canActivateChild: [ MetaGuard ]
},
+ {
+ path: 'p',
+ loadChildren: () => import('./+plugin-pages/plugin-pages.module').then(m => m.PluginPagesModule),
+ canActivateChild: [ MetaGuard ]
+ },
+
{
path: 'about',
loadChildren: () => import('./+about/about.module').then(m => m.AboutModule),
PluginType,
PublicServerSetting,
RegisterClientFormFieldOptions,
- RegisterClientSettingsScript,
+ RegisterClientSettingsScriptOptions,
+ RegisterClientRouteOptions,
RegisterClientVideoFieldOptions,
ServerConfigPlugin
} from '@shared/models'
private formFields: FormFields = {
video: []
}
- private settingsScripts: { [ npmName: string ]: RegisterClientSettingsScript } = {}
+ private settingsScripts: { [ npmName: string ]: RegisterClientSettingsScriptOptions } = {}
+ private clientRoutes: { [ route: string ]: RegisterClientRouteOptions } = {}
private pluginsManager: PluginsManager
this.pluginsManager = new PluginsManager({
peertubeHelpersFactory: this.buildPeerTubeHelpers.bind(this),
onFormFields: this.onFormFields.bind(this),
- onSettingsScripts: this.onSettingsScripts.bind(this)
+ onSettingsScripts: this.onSettingsScripts.bind(this),
+ onClientRoute: this.onClientRoute.bind(this)
})
}
return this.settingsScripts[npmName]
}
+ getRegisteredClientRoute (route: string) {
+ return this.clientRoutes[route]
+ }
+
+ getAllRegisteredClientRoutes () {
+ return Object.keys(this.clientRoutes)
+ }
+
translateBy (npmName: string, toTranslate: string) {
const helpers = this.helpers[npmName]
if (!helpers) {
})
}
- private onSettingsScripts (pluginInfo: PluginInfo, options: RegisterClientSettingsScript) {
+ private onSettingsScripts (pluginInfo: PluginInfo, options: RegisterClientSettingsScriptOptions) {
const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType)
this.settingsScripts[npmName] = options
}
+ private onClientRoute (options: RegisterClientRouteOptions) {
+ const route = options.route.startsWith('/')
+ ? options.route
+ : `/${options.route}`
+
+ this.clientRoutes[route] = options
+ }
+
private buildPeerTubeHelpers (pluginInfo: PluginInfo): RegisterClientHelpers {
const { plugin } = pluginInfo
const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType)
return environment.apiUrl + `${pathPrefix}/${plugin.name}/${plugin.version}/router`
},
+ getBasePluginClientPath: () => {
+ return '/p'
+ },
+
getSettings: () => {
const path = PluginService.BASE_PLUGIN_API_URL + '/' + npmName + '/public-settings'
// Reuse the route if we're going to and from the same route
shouldReuseRoute (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
- return future.routeConfig === curr.routeConfig
+ return future.routeConfig === curr.routeConfig && future.routeConfig?.data?.reloadOnSameNavigation !== true
}
private gb () {
PluginType,
RegisterClientFormFieldOptions,
RegisterClientHookOptions,
- RegisterClientSettingsScript,
+ RegisterClientRouteOptions,
+ RegisterClientSettingsScriptOptions,
RegisterClientVideoFieldOptions,
RegisteredExternalAuthConfig,
ServerConfigPlugin
type PeertubeHelpersFactory = (pluginInfo: PluginInfo) => RegisterClientHelpers
type OnFormFields = (options: RegisterClientFormFieldOptions, videoFormOptions: RegisterClientVideoFieldOptions) => void
-type OnSettingsScripts = (pluginInfo: PluginInfo, options: RegisterClientSettingsScript) => void
+type OnSettingsScripts = (pluginInfo: PluginInfo, options: RegisterClientSettingsScriptOptions) => void
+type OnClientRoute = (options: RegisterClientRouteOptions) => void
const logger = debug('peertube:plugins')
private readonly peertubeHelpersFactory: PeertubeHelpersFactory
private readonly onFormFields: OnFormFields
private readonly onSettingsScripts: OnSettingsScripts
+ private readonly onClientRoute: OnClientRoute
constructor (options: {
peertubeHelpersFactory: PeertubeHelpersFactory
onFormFields?: OnFormFields
onSettingsScripts?: OnSettingsScripts
+ onClientRoute?: OnClientRoute
}) {
this.peertubeHelpersFactory = options.peertubeHelpersFactory
this.onFormFields = options.onFormFields
this.onSettingsScripts = options.onSettingsScripts
+ this.onClientRoute = options.onClientRoute
}
static getPluginPathPrefix (isTheme: boolean) {
return this.onFormFields(commonOptions, videoFormOptions)
}
- const registerSettingsScript = (options: RegisterClientSettingsScript) => {
+ const registerSettingsScript = (options: RegisterClientSettingsScriptOptions) => {
if (!this.onSettingsScripts) {
throw new Error('Registering settings script is not supported')
}
return this.onSettingsScripts(pluginInfo, options)
}
+ const registerClientRoute = (options: RegisterClientRouteOptions) => {
+ if (!this.onClientRoute) {
+ throw new Error('Registering client route is not supported')
+ }
+
+ return this.onClientRoute(options)
+ }
+
const peertubeHelpers = this.peertubeHelpersFactory(pluginInfo)
console.log('Loading script %s of plugin %s.', clientScript.script, plugin.name)
const absURL = (environment.apiUrl || window.location.origin) + clientScript.script
return dynamicImport(absURL)
- .then((script: ClientScriptModule) => script.register({ registerHook, registerVideoField, registerSettingsScript, peertubeHelpers }))
+ .then((script: ClientScriptModule) => {
+ return script.register({
+ registerHook,
+ registerVideoField,
+ registerSettingsScript,
+ registerClientRoute,
+ peertubeHelpers
+ })
+ })
.then(() => this.sortHooksByPriority())
.catch(err => console.error('Cannot import or register plugin %s.', pluginInfo.plugin.name, err))
}
return {
getBaseStaticRoute: unimplemented,
-
getBaseRouterRoute: unimplemented,
+ getBasePluginClientPath: unimplemented,
getSettings: unimplemented,
import {
RegisterClientFormFieldOptions,
RegisterClientHookOptions,
- RegisterClientSettingsScript,
+ RegisterClientRouteOptions,
+ RegisterClientSettingsScriptOptions,
RegisterClientVideoFieldOptions,
ServerConfig
} from '@shared/models'
registerVideoField: (commonOptions: RegisterClientFormFieldOptions, videoFormOptions: RegisterClientVideoFieldOptions) => void
- registerSettingsScript: (options: RegisterClientSettingsScript) => void
+ registerSettingsScript: (options: RegisterClientSettingsScriptOptions) => void
+
+ registerClientRoute: (options: RegisterClientRouteOptions) => void
peertubeHelpers: RegisterClientHelpers
}
getBaseRouterRoute: () => string
+ getBasePluginClientPath: () => string
+
isLoggedIn: () => boolean
getAuthHeader: () => { 'Authorization': string } | undefined
export * from './plugin-selector-id.type'
export * from './register-client-form-field.model'
export * from './register-client-hook.model'
+export * from './register-client-route.model'
export * from './register-client-settings-script.model'
--- /dev/null
+export interface RegisterClientRouteOptions {
+ route: string
+
+ onMount (options: {
+ rootEl: HTMLElement
+ }): void
+}
import { RegisterServerSettingOptions } from '../server'
-export interface RegisterClientSettingsScript {
+export interface RegisterClientSettingsScriptOptions {
isSettingHidden (options: {
setting: RegisterServerSettingOptions
formValues: { [name: string]: any }