From 8e08d415f9473b6b72fef698729453e726da16e7 Mon Sep 17 00:00:00 2001
From: Chocobozzz <me@florianbigard.com>
Date: Fri, 4 Jun 2021 11:46:17 +0200
Subject: [PATCH] Load server config on app init

---
 client/src/app/app-routing.module.ts         |   2 +-
 client/src/app/app.module.ts                 |  16 +-
 client/src/app/core/server/server.service.ts | 180 +++----------------
 3 files changed, 34 insertions(+), 164 deletions(-)

diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts
index e35f540be..b04e6a42b 100644
--- a/client/src/app/app-routing.module.ts
+++ b/client/src/app/app-routing.module.ts
@@ -114,7 +114,7 @@ const routes: Routes = [
     path: 'w',
     loadChildren: () => import('@app/+videos/+video-watch/video-watch.module').then(m => m.VideoWatchModule),
     data: {
-      preload: 3000
+      preload: 5000
     }
   },
   {
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts
index 9f46d49a2..8fc054d79 100644
--- a/client/src/app/app.module.ts
+++ b/client/src/app/app.module.ts
@@ -1,13 +1,13 @@
 import 'focus-visible'
 import { environment } from 'src/environments/environment'
 import { APP_BASE_HREF, registerLocaleData } from '@angular/common'
-import { NgModule } from '@angular/core'
+import { APP_INITIALIZER, NgModule } from '@angular/core'
 import { BrowserModule } from '@angular/platform-browser'
 import { ServiceWorkerModule } from '@angular/service-worker'
 import localeOc from '@app/helpers/locales/oc'
 import { AppRoutingModule } from './app-routing.module'
 import { AppComponent } from './app.component'
-import { CoreModule } from './core'
+import { CoreModule, ServerService } from './core'
 import { EmptyComponent } from './empty.component'
 import { HeaderComponent, SearchTypeaheadComponent, SuggestionComponent } from './header'
 import { HighlightPipe } from './header/highlight.pipe'
@@ -26,6 +26,10 @@ import { SharedUserInterfaceSettingsModule } from './shared/shared-user-settings
 
 registerLocaleData(localeOc, 'oc')
 
+export function loadConfigFactory (server: ServerService) {
+  return () => server.loadConfig()
+}
+
 @NgModule({
   bootstrap: [ AppComponent ],
 
@@ -67,7 +71,13 @@ registerLocaleData(localeOc, 'oc')
     {
       provide: APP_BASE_HREF,
       useValue: '/'
-    }
+    },
+    {
+      provide: APP_INITIALIZER,
+      useFactory: loadConfigFactory,
+      deps: [ ServerService ],
+      multi: true
+     }
   ]
 })
 export class AppModule {}
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts
index 6918957f4..251963858 100644
--- a/client/src/app/core/server/server.service.ts
+++ b/client/src/app/core/server/server.service.ts
@@ -4,7 +4,7 @@ import { HttpClient } from '@angular/common/http'
 import { Inject, Injectable, LOCALE_ID } from '@angular/core'
 import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers'
 import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n'
-import { SearchTargetType, ServerConfig, ServerStats, VideoConstant } from '@shared/models'
+import { HTMLServerConfig, SearchTargetType, ServerConfig, ServerStats, VideoConstant } from '@shared/models'
 import { environment } from '../../../environments/environment'
 
 @Injectable()
@@ -28,163 +28,26 @@ export class ServerService {
   private configReset = false
 
   private configLoaded = false
-  private config: ServerConfig = {
-    instance: {
-      name: 'PeerTube',
-      shortDescription: 'PeerTube, a federated (ActivityPub) video streaming platform  ' +
-                        'using P2P (BitTorrent) directly in the web browser with WebTorrent and Angular.',
-      isNSFW: false,
-      defaultNSFWPolicy: 'do_not_list' as 'do_not_list',
-      defaultClientRoute: '',
-      customizations: {
-        javascript: '',
-        css: ''
-      }
-    },
-    plugin: {
-      registered: [],
-      registeredExternalAuths: [],
-      registeredIdAndPassAuths: []
-    },
-    theme: {
-      registered: [],
-      default: 'default'
-    },
-    email: {
-      enabled: false
-    },
-    contactForm: {
-      enabled: false
-    },
-    serverVersion: 'Unknown',
-    signup: {
-      allowed: false,
-      allowedForCurrentIP: false,
-      requiresEmailVerification: false,
-      minimumAge: 16
-    },
-    transcoding: {
-      profile: 'default',
-      availableProfiles: [ 'default' ],
-      enabledResolutions: [],
-      hls: {
-        enabled: false
-      },
-      webtorrent: {
-        enabled: true
-      }
-    },
-    live: {
-      enabled: false,
-      allowReplay: true,
-      maxDuration: null,
-      maxInstanceLives: -1,
-      maxUserLives: -1,
-      transcoding: {
-        enabled: false,
-        profile: 'default',
-        availableProfiles: [ 'default' ],
-        enabledResolutions: []
-      },
-      rtmp: {
-        port: 1935
-      }
-    },
-    avatar: {
-      file: {
-        size: { max: 0 },
-        extensions: []
-      }
-    },
-    banner: {
-      file: {
-        size: { max: 0 },
-        extensions: []
-      }
-    },
-    video: {
-      image: {
-        size: { max: 0 },
-        extensions: []
-      },
-      file: {
-        extensions: []
-      }
-    },
-    videoCaption: {
-      file: {
-        size: { max: 0 },
-        extensions: []
-      }
-    },
-    user: {
-      videoQuota: -1,
-      videoQuotaDaily: -1
-    },
-    import: {
-      videos: {
-        http: {
-          enabled: false
-        },
-        torrent: {
-          enabled: false
-        }
-      }
-    },
-    trending: {
-      videos: {
-        intervalDays: 0,
-        algorithms: {
-          enabled: [ 'best', 'hot', 'most-viewed', 'most-liked' ],
-          default: 'most-viewed'
-        }
-      }
-    },
-    autoBlacklist: {
-      videos: {
-        ofUsers: {
-          enabled: false
-        }
-      }
-    },
-    tracker: {
-      enabled: true
-    },
-    followings: {
-      instance: {
-        autoFollowIndex: {
-          indexUrl: 'https://instances.joinpeertube.org'
-        }
-      }
-    },
-    broadcastMessage: {
-      enabled: false,
-      message: '',
-      level: 'info',
-      dismissable: false
-    },
-    search: {
-      remoteUri: {
-        users: true,
-        anonymous: false
-      },
-      searchIndex: {
-        enabled: false,
-        url: '',
-        disableLocalSearch: false,
-        isDefaultSearch: false
-      }
-    },
-    homepage: {
-      enabled: false
-    }
-  }
+  private config: ServerConfig
+  private htmlConfig: HTMLServerConfig
 
   constructor (
     private http: HttpClient,
     @Inject(LOCALE_ID) private localeId: string
   ) {
-    this.loadConfigLocally()
+  }
+
+  loadConfig () {
+    try {
+      return this.loadConfigLocally()
+    } catch (err) {
+      // Expected in dev mode since we can't inject the config in the HTML
+      if (environment.production !== false) {
+        console.error('Cannot load config locally. Fallback to API.')
+      }
+
+      return this.getConfig()
+    }
   }
 
   getServerVersionAndCommit () {
@@ -343,13 +206,10 @@ export class ServerService {
 
   private loadConfigLocally () {
     const configString = window['PeerTubeServerConfig']
-    if (!configString) return
-
-    try {
-      const parsed = JSON.parse(configString)
-      Object.assign(this.config, parsed)
-    } catch (err) {
-      console.error('Cannot parse config saved in from index.html.', err)
+    if (!configString) {
+      throw new Error('Could not find PeerTubeServerConfig in HTML')
     }
+
+    this.config = JSON.parse(configString)
   }
 }