aboutsummaryrefslogtreecommitdiffhomepage
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/src/app/+my-library/my-library.component.ts1
-rw-r--r--client/src/app/+search/search-filters.component.ts1
-rw-r--r--client/src/app/+search/search.component.ts2
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-edit.component.ts1
-rw-r--r--client/src/app/+videos/+video-watch/video-watch.component.ts1
-rw-r--r--client/src/app/app-routing.module.ts6
-rw-r--r--client/src/app/app.component.ts19
-rw-r--r--client/src/app/app.module.ts17
-rw-r--r--client/src/app/core/core.module.ts8
-rw-r--r--client/src/app/core/plugins/plugin.service.ts26
-rw-r--r--client/src/app/core/routing/homepage-redirect.component.ts30
-rw-r--r--client/src/app/core/routing/index.ts1
-rw-r--r--client/src/app/core/routing/redirect.service.ts1
-rw-r--r--client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts1
-rw-r--r--client/src/root-helpers/plugins.ts5
-rw-r--r--client/src/root-helpers/utils.ts38
16 files changed, 63 insertions, 95 deletions
diff --git a/client/src/app/+my-library/my-library.component.ts b/client/src/app/+my-library/my-library.component.ts
index 939aa84c8..2ee3559a7 100644
--- a/client/src/app/+my-library/my-library.component.ts
+++ b/client/src/app/+my-library/my-library.component.ts
@@ -11,7 +11,6 @@ export class MyLibraryComponent implements OnInit {
11 menuEntries: TopMenuDropdownParam[] = [] 11 menuEntries: TopMenuDropdownParam[] = []
12 user: AuthUser 12 user: AuthUser
13 13
14
15 private serverConfig: HTMLServerConfig 14 private serverConfig: HTMLServerConfig
16 15
17 constructor ( 16 constructor (
diff --git a/client/src/app/+search/search-filters.component.ts b/client/src/app/+search/search-filters.component.ts
index f5f0c87ed..afa523b91 100644
--- a/client/src/app/+search/search-filters.component.ts
+++ b/client/src/app/+search/search-filters.component.ts
@@ -99,7 +99,6 @@ export class SearchFiltersComponent implements OnInit {
99 ngOnInit () { 99 ngOnInit () {
100 this.serverConfig = this.serverService.getHTMLConfig() 100 this.serverConfig = this.serverService.getHTMLConfig()
101 101
102
103 this.serverService.getVideoCategories().subscribe(categories => this.videoCategories = categories) 102 this.serverService.getVideoCategories().subscribe(categories => this.videoCategories = categories)
104 this.serverService.getVideoLicences().subscribe(licences => this.videoLicences = licences) 103 this.serverService.getVideoLicences().subscribe(licences => this.videoLicences = licences)
105 this.serverService.getVideoLanguages().subscribe(languages => this.videoLanguages = languages) 104 this.serverService.getVideoLanguages().subscribe(languages => this.videoLanguages = languages)
diff --git a/client/src/app/+search/search.component.ts b/client/src/app/+search/search.component.ts
index a31096bb2..a4ab7a5b1 100644
--- a/client/src/app/+search/search.component.ts
+++ b/client/src/app/+search/search.component.ts
@@ -287,7 +287,7 @@ export class SearchComponent implements OnInit, OnDestroy {
287 ) 287 )
288 } 288 }
289 289
290 private getDefaultSearchTarget(): SearchTargetType { 290 private getDefaultSearchTarget (): SearchTargetType {
291 const searchIndexConfig = this.serverConfig.search.searchIndex 291 const searchIndexConfig = this.serverConfig.search.searchIndex
292 292
293 if (searchIndexConfig.enabled && (searchIndexConfig.isDefaultSearch || searchIndexConfig.disableLocalSearch)) { 293 if (searchIndexConfig.enabled && (searchIndexConfig.isDefaultSearch || searchIndexConfig.disableLocalSearch)) {
diff --git a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts
index 52801802b..c3299cade 100644
--- a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts
+++ b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts
@@ -194,7 +194,6 @@ export class VideoEditComponent implements OnInit, OnDestroy {
194 } 194 }
195 }) 195 })
196 196
197
198 this.serverConfig = this.serverService.getHTMLConfig() 197 this.serverConfig = this.serverService.getHTMLConfig()
199 198
200 this.initialVideoCaptions = this.videoCaptions.map(c => c.language.id) 199 this.initialVideoCaptions = this.videoCaptions.map(c => c.language.id)
diff --git a/client/src/app/+videos/+video-watch/video-watch.component.ts b/client/src/app/+videos/+video-watch/video-watch.component.ts
index 51d486ea5..3fdbc0184 100644
--- a/client/src/app/+videos/+video-watch/video-watch.component.ts
+++ b/client/src/app/+videos/+video-watch/video-watch.component.ts
@@ -181,7 +181,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
181 this.hasAlreadyAcceptedPrivacyConcern = true 181 this.hasAlreadyAcceptedPrivacyConcern = true
182 } 182 }
183 183
184
185 this.paramsSub = this.route.params.subscribe(routeParams => { 184 this.paramsSub = this.route.params.subscribe(routeParams => {
186 const videoId = routeParams[ 'videoId' ] 185 const videoId = routeParams[ 'videoId' ]
187 if (videoId) this.loadVideo(videoId) 186 if (videoId) this.loadVideo(videoId)
diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts
index b04e6a42b..1f98e9d2e 100644
--- a/client/src/app/app-routing.module.ts
+++ b/client/src/app/app-routing.module.ts
@@ -3,7 +3,7 @@ import { RouteReuseStrategy, RouterModule, Routes, UrlMatchResult, UrlSegment }
3import { CustomReuseStrategy } from '@app/core/routing/custom-reuse-strategy' 3import { CustomReuseStrategy } from '@app/core/routing/custom-reuse-strategy'
4import { MenuGuards } from '@app/core/routing/menu-guard.service' 4import { MenuGuards } from '@app/core/routing/menu-guard.service'
5import { POSSIBLE_LOCALES } from '@shared/core-utils/i18n' 5import { POSSIBLE_LOCALES } from '@shared/core-utils/i18n'
6import { MetaGuard, PreloadSelectedModulesList } from './core' 6import { HomepageRedirectComponent, MetaGuard, PreloadSelectedModulesList } from './core'
7import { EmptyComponent } from './empty.component' 7import { EmptyComponent } from './empty.component'
8import { USER_USERNAME_REGEX_CHARACTERS } from './shared/form-validators/user-validators' 8import { USER_USERNAME_REGEX_CHARACTERS } from './shared/form-validators/user-validators'
9import { ActorRedirectGuard } from './shared/shared-main' 9import { ActorRedirectGuard } from './shared/shared-main'
@@ -156,7 +156,7 @@ const routes: Routes = [
156 156
157 { 157 {
158 path: '', 158 path: '',
159 component: EmptyComponent // Avoid 404, app component will redirect dynamically 159 component: HomepageRedirectComponent
160 } 160 }
161] 161]
162 162
@@ -164,7 +164,7 @@ const routes: Routes = [
164for (const locale of POSSIBLE_LOCALES) { 164for (const locale of POSSIBLE_LOCALES) {
165 routes.push({ 165 routes.push({
166 path: locale, 166 path: locale,
167 component: EmptyComponent 167 component: HomepageRedirectComponent
168 }) 168 })
169} 169}
170 170
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts
index 6884068f6..2056d6669 100644
--- a/client/src/app/app.component.ts
+++ b/client/src/app/app.component.ts
@@ -1,6 +1,5 @@
1import { Hotkey, HotkeysService } from 'angular2-hotkeys' 1import { Hotkey, HotkeysService } from 'angular2-hotkeys'
2import { concat } from 'rxjs' 2import { filter, map, pairwise, switchMap } from 'rxjs/operators'
3import { filter, first, map, pairwise, switchMap } from 'rxjs/operators'
4import { DOCUMENT, PlatformLocation, ViewportScroller } from '@angular/common' 3import { DOCUMENT, PlatformLocation, ViewportScroller } from '@angular/common'
5import { AfterViewInit, Component, Inject, LOCALE_ID, OnInit, ViewChild } from '@angular/core' 4import { AfterViewInit, Component, Inject, LOCALE_ID, OnInit, ViewChild } from '@angular/core'
6import { DomSanitizer, SafeHtml } from '@angular/platform-browser' 5import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
@@ -14,7 +13,7 @@ import { WelcomeModalComponent } from '@app/modal/welcome-modal.component'
14import { NgbConfig, NgbModal } from '@ng-bootstrap/ng-bootstrap' 13import { NgbConfig, NgbModal } from '@ng-bootstrap/ng-bootstrap'
15import { LoadingBarService } from '@ngx-loading-bar/core' 14import { LoadingBarService } from '@ngx-loading-bar/core'
16import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' 15import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
17import { getShortLocale, is18nPath } from '@shared/core-utils/i18n' 16import { getShortLocale } from '@shared/core-utils/i18n'
18import { BroadcastMessageLevel, HTMLServerConfig, ServerConfig, UserRole } from '@shared/models' 17import { BroadcastMessageLevel, HTMLServerConfig, ServerConfig, UserRole } from '@shared/models'
19import { MenuService } from './core/menu/menu.service' 18import { MenuService } from './core/menu/menu.service'
20import { POP_STATE_MODAL_DISMISS } from './helpers' 19import { POP_STATE_MODAL_DISMISS } from './helpers'
@@ -75,7 +74,7 @@ export class AppComponent implements OnInit, AfterViewInit {
75 74
76 this.serverConfig = this.serverService.getHTMLConfig() 75 this.serverConfig = this.serverService.getHTMLConfig()
77 76
78 this.loadPlugins() 77 this.hooks.runAction('action:application.init', 'common')
79 this.themeService.initialize() 78 this.themeService.initialize()
80 79
81 this.authService.loadClientCredentials() 80 this.authService.loadClientCredentials()
@@ -190,12 +189,6 @@ export class AppComponent implements OnInit, AfterViewInit {
190 } 189 }
191 }) 190 })
192 191
193 // Homepage redirection
194 navigationEndEvent.pipe(
195 map(() => window.location.pathname),
196 filter(pathname => !pathname || pathname === '/' || is18nPath(pathname))
197 ).subscribe(() => this.redirectService.redirectToHomepage(true))
198
199 // Plugin hooks 192 // Plugin hooks
200 navigationEndEvent.subscribe(e => { 193 navigationEndEvent.subscribe(e => {
201 this.hooks.runAction('action:router.navigation-end', 'common', { path: e.url }) 194 this.hooks.runAction('action:router.navigation-end', 'common', { path: e.url })
@@ -268,12 +261,6 @@ export class AppComponent implements OnInit, AfterViewInit {
268 } 261 }
269 } 262 }
270 263
271 private async loadPlugins () {
272 this.pluginService.initializePlugins()
273
274 this.hooks.runAction('action:application.init', 'common')
275 }
276
277 private async openModalsIfNeeded () { 264 private async openModalsIfNeeded () {
278 this.authService.userInformationLoaded 265 this.authService.userInformationLoaded
279 .pipe( 266 .pipe(
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts
index ea53818e1..dfdccbe69 100644
--- a/client/src/app/app.module.ts
+++ b/client/src/app/app.module.ts
@@ -1,4 +1,5 @@
1import 'focus-visible' 1import 'focus-visible'
2import { tap } from 'rxjs/operators'
2import { environment } from 'src/environments/environment' 3import { environment } from 'src/environments/environment'
3import { APP_BASE_HREF, registerLocaleData } from '@angular/common' 4import { APP_BASE_HREF, registerLocaleData } from '@angular/common'
4import { APP_INITIALIZER, NgModule } from '@angular/core' 5import { APP_INITIALIZER, NgModule } from '@angular/core'
@@ -7,7 +8,7 @@ import { ServiceWorkerModule } from '@angular/service-worker'
7import localeOc from '@app/helpers/locales/oc' 8import localeOc from '@app/helpers/locales/oc'
8import { AppRoutingModule } from './app-routing.module' 9import { AppRoutingModule } from './app-routing.module'
9import { AppComponent } from './app.component' 10import { AppComponent } from './app.component'
10import { CoreModule, ServerService } from './core' 11import { CoreModule, PluginService, ServerService } from './core'
11import { EmptyComponent } from './empty.component' 12import { EmptyComponent } from './empty.component'
12import { HeaderComponent, SearchTypeaheadComponent, SuggestionComponent } from './header' 13import { HeaderComponent, SearchTypeaheadComponent, SuggestionComponent } from './header'
13import { HighlightPipe } from './header/highlight.pipe' 14import { HighlightPipe } from './header/highlight.pipe'
@@ -26,8 +27,14 @@ import { SharedUserInterfaceSettingsModule } from './shared/shared-user-settings
26 27
27registerLocaleData(localeOc, 'oc') 28registerLocaleData(localeOc, 'oc')
28 29
29export function loadConfigFactory (server: ServerService) { 30export function loadConfigFactory (server: ServerService, pluginService: PluginService) {
30 return () => server.loadHTMLConfig() 31 return () => {
32 const result = server.loadHTMLConfig()
33
34 if (result) return result.pipe(tap(() => pluginService.initializePlugins()))
35
36 return pluginService.initializePlugins()
37 }
31} 38}
32 39
33@NgModule({ 40@NgModule({
@@ -75,9 +82,9 @@ export function loadConfigFactory (server: ServerService) {
75 { 82 {
76 provide: APP_INITIALIZER, 83 provide: APP_INITIALIZER,
77 useFactory: loadConfigFactory, 84 useFactory: loadConfigFactory,
78 deps: [ ServerService ], 85 deps: [ ServerService, PluginService ],
79 multi: true 86 multi: true
80 } 87 }
81 ] 88 ]
82}) 89})
83export class AppModule {} 90export class AppModule {}
diff --git a/client/src/app/core/core.module.ts b/client/src/app/core/core.module.ts
index de3274544..3e2056481 100644
--- a/client/src/app/core/core.module.ts
+++ b/client/src/app/core/core.module.ts
@@ -14,7 +14,7 @@ import { throwIfAlreadyLoaded } from './module-import-guard'
14import { Notifier } from './notification' 14import { Notifier } from './notification'
15import { HtmlRendererService, LinkifierService, MarkdownService } from './renderer' 15import { HtmlRendererService, LinkifierService, MarkdownService } from './renderer'
16import { RestExtractor, RestService } from './rest' 16import { RestExtractor, RestService } from './rest'
17import { LoginGuard, MetaGuard, MetaService, RedirectService, UnloggedGuard, UserRightGuard } from './routing' 17import { HomepageRedirectComponent, LoginGuard, MetaGuard, MetaService, RedirectService, UnloggedGuard, UserRightGuard } from './routing'
18import { CanDeactivateGuard } from './routing/can-deactivate-guard.service' 18import { CanDeactivateGuard } from './routing/can-deactivate-guard.service'
19import { ServerConfigResolver } from './routing/server-config-resolver.service' 19import { ServerConfigResolver } from './routing/server-config-resolver.service'
20import { ScopedTokensService } from './scoped-tokens' 20import { ScopedTokensService } from './scoped-tokens'
@@ -36,13 +36,15 @@ import { LocalStorageService, ScreenService, SessionStorageService } from './wra
36 ], 36 ],
37 37
38 declarations: [ 38 declarations: [
39 CheatSheetComponent 39 CheatSheetComponent,
40 HomepageRedirectComponent
40 ], 41 ],
41 42
42 exports: [ 43 exports: [
43 ToastModule, 44 ToastModule,
44 45
45 CheatSheetComponent 46 CheatSheetComponent,
47 HomepageRedirectComponent
46 ], 48 ],
47 49
48 providers: [ 50 providers: [
diff --git a/client/src/app/core/plugins/plugin.service.ts b/client/src/app/core/plugins/plugin.service.ts
index dff8ad864..ccbfd3e4d 100644
--- a/client/src/app/core/plugins/plugin.service.ts
+++ b/client/src/app/core/plugins/plugin.service.ts
@@ -1,3 +1,4 @@
1import * as debug from 'debug'
1import { Observable, of, ReplaySubject } from 'rxjs' 2import { Observable, of, ReplaySubject } from 'rxjs'
2import { catchError, first, map, shareReplay } from 'rxjs/operators' 3import { catchError, first, map, shareReplay } from 'rxjs/operators'
3import { HttpClient } from '@angular/common/http' 4import { HttpClient } from '@angular/common/http'
@@ -24,7 +25,6 @@ import {
24} from '@shared/models' 25} from '@shared/models'
25import { environment } from '../../../environments/environment' 26import { environment } from '../../../environments/environment'
26import { RegisterClientHelpers } from '../../../types/register-client-option.model' 27import { RegisterClientHelpers } from '../../../types/register-client-option.model'
27import * as debug from 'debug'
28 28
29const logger = debug('peertube:plugins') 29const logger = debug('peertube:plugins')
30 30
@@ -33,8 +33,6 @@ export class PluginService implements ClientHook {
33 private static BASE_PLUGIN_API_URL = environment.apiUrl + '/api/v1/plugins' 33 private static BASE_PLUGIN_API_URL = environment.apiUrl + '/api/v1/plugins'
34 private static BASE_PLUGIN_URL = environment.apiUrl + '/plugins' 34 private static BASE_PLUGIN_URL = environment.apiUrl + '/plugins'
35 35
36 pluginsBuilt = new ReplaySubject<boolean>(1)
37
38 pluginsLoaded: { [ scope in PluginClientScope ]: ReplaySubject<boolean> } = { 36 pluginsLoaded: { [ scope in PluginClientScope ]: ReplaySubject<boolean> } = {
39 common: new ReplaySubject<boolean>(1), 37 common: new ReplaySubject<boolean>(1),
40 'admin-plugin': new ReplaySubject<boolean>(1), 38 'admin-plugin': new ReplaySubject<boolean>(1),
@@ -79,30 +77,18 @@ export class PluginService implements ClientHook {
79 } 77 }
80 78
81 initializePlugins () { 79 initializePlugins () {
82 logger('Building plugin configuration') 80 const config = this.server.getHTMLConfig()
81 this.plugins = config.plugin.registered
83 82
84 this.server.getConfig() 83 this.buildScopeStruct()
85 .subscribe(config => {
86 this.plugins = config.plugin.registered
87 84
88 this.buildScopeStruct() 85 this.ensurePluginsAreLoaded('common')
89
90 this.pluginsBuilt.next(true)
91
92 logger('Plugin configuration built')
93 })
94 } 86 }
95 87
96 initializeCustomModal (customModal: CustomModalComponent) { 88 initializeCustomModal (customModal: CustomModalComponent) {
97 this.customModal = customModal 89 this.customModal = customModal
98 } 90 }
99 91
100 ensurePluginsAreBuilt () {
101 return this.pluginsBuilt.asObservable()
102 .pipe(first(), shareReplay())
103 .toPromise()
104 }
105
106 ensurePluginsAreLoaded (scope: PluginClientScope) { 92 ensurePluginsAreLoaded (scope: PluginClientScope) {
107 this.loadPluginsByScope(scope) 93 this.loadPluginsByScope(scope)
108 94
@@ -156,8 +142,6 @@ export class PluginService implements ClientHook {
156 logger('Loading scope %s', scope) 142 logger('Loading scope %s', scope)
157 143
158 try { 144 try {
159 await this.ensurePluginsAreBuilt()
160
161 if (!isReload) this.loadedScopes.push(scope) 145 if (!isReload) this.loadedScopes.push(scope)
162 146
163 const toLoad = this.scopes[ scope ] 147 const toLoad = this.scopes[ scope ]
diff --git a/client/src/app/core/routing/homepage-redirect.component.ts b/client/src/app/core/routing/homepage-redirect.component.ts
new file mode 100644
index 000000000..9e3848038
--- /dev/null
+++ b/client/src/app/core/routing/homepage-redirect.component.ts
@@ -0,0 +1,30 @@
1import { Component, OnInit } from '@angular/core'
2import { ActivatedRoute } from '@angular/router'
3import { is18nPath } from '@shared/core-utils/i18n/i18n'
4import { RedirectService } from './redirect.service'
5
6/*
7 * We have to use a component instead of an homepage because of a weird issue when using router.navigate in guard
8 *
9 * Since we also want to use the `skipLocationChange` option, we cannot use a guard that returns a UrlTree
10 * See https://github.com/angular/angular/issues/27148
11*/
12
13@Component({
14 template: ''
15})
16export class HomepageRedirectComponent implements OnInit {
17
18 constructor (
19 private route: ActivatedRoute,
20 private redirectService: RedirectService
21 ) { }
22
23 ngOnInit () {
24 const url = this.route.snapshot.url
25
26 if (url.length === 0 || is18nPath('/' + url[0])) {
27 this.redirectService.redirectToHomepage(true)
28 }
29 }
30}
diff --git a/client/src/app/core/routing/index.ts b/client/src/app/core/routing/index.ts
index 4314ea475..d0c688a2f 100644
--- a/client/src/app/core/routing/index.ts
+++ b/client/src/app/core/routing/index.ts
@@ -1,6 +1,7 @@
1export * from './can-deactivate-guard.service' 1export * from './can-deactivate-guard.service'
2export * from './custom-reuse-strategy' 2export * from './custom-reuse-strategy'
3export * from './disable-for-reuse-hook' 3export * from './disable-for-reuse-hook'
4export * from './homepage-redirect.component'
4export * from './login-guard.service' 5export * from './login-guard.service'
5export * from './menu-guard.service' 6export * from './menu-guard.service'
6export * from './meta-guard.service' 7export * from './meta-guard.service'
diff --git a/client/src/app/core/routing/redirect.service.ts b/client/src/app/core/routing/redirect.service.ts
index 198332b00..17d9d1358 100644
--- a/client/src/app/core/routing/redirect.service.ts
+++ b/client/src/app/core/routing/redirect.service.ts
@@ -42,7 +42,6 @@ export class RedirectService {
42 return this.defaultRoute 42 return this.defaultRoute
43 } 43 }
44 44
45
46 getDefaultTrendingAlgorithm () { 45 getDefaultTrendingAlgorithm () {
47 return this.defaultTrendingAlgorithm 46 return this.defaultTrendingAlgorithm
48 } 47 }
diff --git a/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts b/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts
index eec325a61..c3f10c055 100644
--- a/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts
+++ b/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts
@@ -44,7 +44,6 @@ export class ActorBannerEditComponent implements OnInit {
44 this.bannerFormat = $localize`ratio 6/1, recommended size: 1920x317, max size: ${getBytes(this.maxBannerSize)}, extensions: ${this.bannerExtensions}` 44 this.bannerFormat = $localize`ratio 6/1, recommended size: 1920x317, max size: ${getBytes(this.maxBannerSize)}, extensions: ${this.bannerExtensions}`
45 } 45 }
46 46
47
48 onBannerChange (input: HTMLInputElement) { 47 onBannerChange (input: HTMLInputElement) {
49 this.bannerfileInput = new ElementRef(input) 48 this.bannerfileInput = new ElementRef(input)
50 49
diff --git a/client/src/root-helpers/plugins.ts b/client/src/root-helpers/plugins.ts
index 8c1c858b7..10c111a8c 100644
--- a/client/src/root-helpers/plugins.ts
+++ b/client/src/root-helpers/plugins.ts
@@ -11,8 +11,8 @@ import {
11 RegisterClientVideoFieldOptions, 11 RegisterClientVideoFieldOptions,
12 ServerConfigPlugin 12 ServerConfigPlugin
13} from '../../../shared/models' 13} from '../../../shared/models'
14import { environment } from '../environments/environment'
14import { ClientScript as ClientScriptModule } from '../types/client-script.model' 15import { ClientScript as ClientScriptModule } from '../types/client-script.model'
15import { importModule } from './utils'
16 16
17interface HookStructValue extends RegisterClientHookOptions { 17interface HookStructValue extends RegisterClientHookOptions {
18 plugin: ServerConfigPlugin 18 plugin: ServerConfigPlugin
@@ -101,7 +101,8 @@ function loadPlugin (options: {
101 101
102 console.log('Loading script %s of plugin %s.', clientScript.script, plugin.name) 102 console.log('Loading script %s of plugin %s.', clientScript.script, plugin.name)
103 103
104 return importModule(clientScript.script) 104 const absURL = (environment.apiUrl || window.location.origin) + clientScript.script
105 return import(/* webpackIgnore: true */ absURL)
105 .then((script: ClientScriptModule) => script.register({ registerHook, registerVideoField, registerSettingsScript, peertubeHelpers })) 106 .then((script: ClientScriptModule) => script.register({ registerHook, registerVideoField, registerSettingsScript, peertubeHelpers }))
106 .then(() => sortHooksByPriority(hooks)) 107 .then(() => sortHooksByPriority(hooks))
107 .catch(err => console.error('Cannot import or register plugin %s.', pluginInfo.plugin.name, err)) 108 .catch(err => console.error('Cannot import or register plugin %s.', pluginInfo.plugin.name, err))
diff --git a/client/src/root-helpers/utils.ts b/client/src/root-helpers/utils.ts
index 06591b95e..00bd92411 100644
--- a/client/src/root-helpers/utils.ts
+++ b/client/src/root-helpers/utils.ts
@@ -1,5 +1,3 @@
1import { environment } from '../environments/environment'
2
3function objectToUrlEncoded (obj: any) { 1function objectToUrlEncoded (obj: any) {
4 const str: string[] = [] 2 const str: string[] = []
5 for (const key of Object.keys(obj)) { 3 for (const key of Object.keys(obj)) {
@@ -21,41 +19,6 @@ function copyToClipboard (text: string) {
21 document.body.removeChild(el) 19 document.body.removeChild(el)
22} 20}
23 21
24// Thanks: https://github.com/uupaa/dynamic-import-polyfill
25function importModule (path: string) {
26 return new Promise((resolve, reject) => {
27 const vector = '$importModule$' + Math.random().toString(32).slice(2)
28 const script = document.createElement('script')
29
30 const destructor = () => {
31 delete window[ vector ]
32 script.onerror = null
33 script.onload = null
34 script.remove()
35 URL.revokeObjectURL(script.src)
36 script.src = ''
37 }
38
39 script.defer = true
40 script.type = 'module'
41
42 script.onerror = () => {
43 reject(new Error(`Failed to import: ${path}`))
44 destructor()
45 }
46 script.onload = () => {
47 resolve(window[ vector ])
48 destructor()
49 }
50 const absURL = (environment.apiUrl || window.location.origin) + path
51 const loader = `import * as m from "${absURL}"; window.${vector} = m;` // export Module
52 const blob = new Blob([ loader ], { type: 'text/javascript' })
53 script.src = URL.createObjectURL(blob)
54
55 document.head.appendChild(script)
56 })
57}
58
59function wait (ms: number) { 22function wait (ms: number) {
60 return new Promise<void>(res => { 23 return new Promise<void>(res => {
61 setTimeout(() => res(), ms) 24 setTimeout(() => res(), ms)
@@ -64,7 +27,6 @@ function wait (ms: number) {
64 27
65export { 28export {
66 copyToClipboard, 29 copyToClipboard,
67 importModule,
68 objectToUrlEncoded, 30 objectToUrlEncoded,
69 wait 31 wait
70} 32}