diff options
55 files changed, 543 insertions, 354 deletions
diff --git a/client/src/app/+about/about-instance/about-instance.component.ts b/client/src/app/+about/about-instance/about-instance.component.ts index 16ccae2e2..87beb13da 100644 --- a/client/src/app/+about/about-instance/about-instance.component.ts +++ b/client/src/app/+about/about-instance/about-instance.component.ts | |||
@@ -5,7 +5,8 @@ import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-a | |||
5 | import { InstanceService } from '@app/shared/instance/instance.service' | 5 | import { InstanceService } from '@app/shared/instance/instance.service' |
6 | import { MarkdownService } from '@app/shared/renderer' | 6 | import { MarkdownService } from '@app/shared/renderer' |
7 | import { forkJoin } from 'rxjs' | 7 | import { forkJoin } from 'rxjs' |
8 | import { first } from 'rxjs/operators' | 8 | import { map, switchMap } from 'rxjs/operators' |
9 | import { ServerConfig } from '@shared/models' | ||
9 | 10 | ||
10 | @Component({ | 11 | @Component({ |
11 | selector: 'my-about-instance', | 12 | selector: 'my-about-instance', |
@@ -33,6 +34,8 @@ export class AboutInstanceComponent implements OnInit { | |||
33 | languages: string[] = [] | 34 | languages: string[] = [] |
34 | categories: string[] = [] | 35 | categories: string[] = [] |
35 | 36 | ||
37 | serverConfig: ServerConfig | ||
38 | |||
36 | constructor ( | 39 | constructor ( |
37 | private notifier: Notifier, | 40 | private notifier: Notifier, |
38 | private serverService: ServerService, | 41 | private serverService: ServerService, |
@@ -42,25 +45,35 @@ export class AboutInstanceComponent implements OnInit { | |||
42 | ) {} | 45 | ) {} |
43 | 46 | ||
44 | get instanceName () { | 47 | get instanceName () { |
45 | return this.serverService.getConfig().instance.name | 48 | return this.serverConfig.instance.name |
46 | } | 49 | } |
47 | 50 | ||
48 | get isContactFormEnabled () { | 51 | get isContactFormEnabled () { |
49 | return this.serverService.getConfig().email.enabled && this.serverService.getConfig().contactForm.enabled | 52 | return this.serverConfig.email.enabled && this.serverConfig.contactForm.enabled |
50 | } | 53 | } |
51 | 54 | ||
52 | get isNSFW () { | 55 | get isNSFW () { |
53 | return this.serverService.getConfig().instance.isNSFW | 56 | return this.serverConfig.instance.isNSFW |
54 | } | 57 | } |
55 | 58 | ||
56 | ngOnInit () { | 59 | ngOnInit () { |
57 | forkJoin([ | 60 | this.serverConfig = this.serverService.getTmpConfig() |
58 | this.instanceService.getAbout(), | 61 | this.serverService.getConfig() |
59 | this.serverService.localeObservable.pipe(first()), | 62 | .subscribe(config => this.serverConfig = config) |
60 | this.serverService.videoLanguagesLoaded.pipe(first()), | 63 | |
61 | this.serverService.videoCategoriesLoaded.pipe(first()) | 64 | this.instanceService.getAbout() |
62 | ]).subscribe( | 65 | .pipe( |
63 | async ([ about, translations ]) => { | 66 | switchMap(about => { |
67 | return forkJoin([ | ||
68 | this.instanceService.buildTranslatedLanguages(about), | ||
69 | this.instanceService.buildTranslatedCategories(about) | ||
70 | ]).pipe(map(([ languages, categories ]) => ({ about, languages, categories }))) | ||
71 | }) | ||
72 | ).subscribe( | ||
73 | async ({ about, languages, categories }) => { | ||
74 | this.languages = languages | ||
75 | this.categories = categories | ||
76 | |||
64 | this.shortDescription = about.instance.shortDescription | 77 | this.shortDescription = about.instance.shortDescription |
65 | 78 | ||
66 | this.creationReason = about.instance.creationReason | 79 | this.creationReason = about.instance.creationReason |
@@ -68,9 +81,6 @@ export class AboutInstanceComponent implements OnInit { | |||
68 | this.businessModel = about.instance.businessModel | 81 | this.businessModel = about.instance.businessModel |
69 | 82 | ||
70 | this.html = await this.instanceService.buildHtml(about) | 83 | this.html = await this.instanceService.buildHtml(about) |
71 | |||
72 | this.languages = this.instanceService.buildTranslatedLanguages(about, translations) | ||
73 | this.categories = this.instanceService.buildTranslatedCategories(about, translations) | ||
74 | }, | 84 | }, |
75 | 85 | ||
76 | () => this.notifier.error(this.i18n('Cannot get about information from server')) | 86 | () => this.notifier.error(this.i18n('Cannot get about information from server')) |
diff --git a/client/src/app/+about/about-instance/contact-admin-modal.component.ts b/client/src/app/+about/about-instance/contact-admin-modal.component.ts index 878d49b55..2ed41e741 100644 --- a/client/src/app/+about/about-instance/contact-admin-modal.component.ts +++ b/client/src/app/+about/about-instance/contact-admin-modal.component.ts | |||
@@ -6,6 +6,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | |||
6 | import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' | 6 | import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' |
7 | import { FormReactive, InstanceValidatorsService } from '@app/shared' | 7 | import { FormReactive, InstanceValidatorsService } from '@app/shared' |
8 | import { InstanceService } from '@app/shared/instance/instance.service' | 8 | import { InstanceService } from '@app/shared/instance/instance.service' |
9 | import { ServerConfig } from '@shared/models' | ||
9 | 10 | ||
10 | @Component({ | 11 | @Component({ |
11 | selector: 'my-contact-admin-modal', | 12 | selector: 'my-contact-admin-modal', |
@@ -18,6 +19,7 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit { | |||
18 | error: string | 19 | error: string |
19 | 20 | ||
20 | private openedModal: NgbModalRef | 21 | private openedModal: NgbModalRef |
22 | private serverConfig: ServerConfig | ||
21 | 23 | ||
22 | constructor ( | 24 | constructor ( |
23 | protected formValidatorService: FormValidatorService, | 25 | protected formValidatorService: FormValidatorService, |
@@ -32,10 +34,14 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit { | |||
32 | } | 34 | } |
33 | 35 | ||
34 | get instanceName () { | 36 | get instanceName () { |
35 | return this.serverService.getConfig().instance.name | 37 | return this.serverConfig.instance.name |
36 | } | 38 | } |
37 | 39 | ||
38 | ngOnInit () { | 40 | ngOnInit () { |
41 | this.serverConfig = this.serverService.getTmpConfig() | ||
42 | this.serverService.getConfig() | ||
43 | .subscribe(config => this.serverConfig = config) | ||
44 | |||
39 | this.buildForm({ | 45 | this.buildForm({ |
40 | fromName: this.instanceValidatorsService.FROM_NAME, | 46 | fromName: this.instanceValidatorsService.FROM_NAME, |
41 | fromEmail: this.instanceValidatorsService.FROM_EMAIL, | 47 | fromEmail: this.instanceValidatorsService.FROM_EMAIL, |
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts index 1f6751297..25e06d8a1 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts | |||
@@ -8,7 +8,7 @@ import { I18n } from '@ngx-translate/i18n-polyfill' | |||
8 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' | 8 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' |
9 | import { SelectItem } from 'primeng/api' | 9 | import { SelectItem } from 'primeng/api' |
10 | import { forkJoin } from 'rxjs' | 10 | import { forkJoin } from 'rxjs' |
11 | import { first } from 'rxjs/operators' | 11 | import { ServerConfig } from '@shared/models' |
12 | 12 | ||
13 | @Component({ | 13 | @Component({ |
14 | selector: 'my-edit-custom-config', | 14 | selector: 'my-edit-custom-config', |
@@ -24,6 +24,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { | |||
24 | languageItems: SelectItem[] = [] | 24 | languageItems: SelectItem[] = [] |
25 | categoryItems: SelectItem[] = [] | 25 | categoryItems: SelectItem[] = [] |
26 | 26 | ||
27 | private serverConfig: ServerConfig | ||
28 | |||
27 | constructor ( | 29 | constructor ( |
28 | protected formValidatorService: FormValidatorService, | 30 | protected formValidatorService: FormValidatorService, |
29 | private customConfigValidatorsService: CustomConfigValidatorsService, | 31 | private customConfigValidatorsService: CustomConfigValidatorsService, |
@@ -84,7 +86,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { | |||
84 | } | 86 | } |
85 | 87 | ||
86 | get availableThemes () { | 88 | get availableThemes () { |
87 | return this.serverService.getConfig().theme.registered | 89 | return this.serverConfig.theme.registered |
88 | .map(t => t.name) | 90 | .map(t => t.name) |
89 | } | 91 | } |
90 | 92 | ||
@@ -93,6 +95,10 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { | |||
93 | } | 95 | } |
94 | 96 | ||
95 | ngOnInit () { | 97 | ngOnInit () { |
98 | this.serverConfig = this.serverService.getTmpConfig() | ||
99 | this.serverService.getConfig() | ||
100 | .subscribe(config => this.serverConfig = config) | ||
101 | |||
96 | const formGroupData: { [key in keyof CustomConfig ]: any } = { | 102 | const formGroupData: { [key in keyof CustomConfig ]: any } = { |
97 | instance: { | 103 | instance: { |
98 | name: this.customConfigValidatorsService.INSTANCE_NAME, | 104 | name: this.customConfigValidatorsService.INSTANCE_NAME, |
@@ -218,16 +224,13 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { | |||
218 | 224 | ||
219 | forkJoin([ | 225 | forkJoin([ |
220 | this.configService.getCustomConfig(), | 226 | this.configService.getCustomConfig(), |
221 | this.serverService.videoLanguagesLoaded.pipe(first()), // First so the observable completes | 227 | this.serverService.getVideoLanguages(), |
222 | this.serverService.videoCategoriesLoaded.pipe(first()) | 228 | this.serverService.getVideoCategories() |
223 | ]).subscribe( | 229 | ]).subscribe( |
224 | ([ config ]) => { | 230 | ([ config, languages, categories ]) => { |
225 | this.customConfig = config | 231 | this.customConfig = config |
226 | 232 | ||
227 | const languages = this.serverService.getVideoLanguages() | ||
228 | this.languageItems = languages.map(l => ({ label: l.label, value: l.id })) | 233 | this.languageItems = languages.map(l => ({ label: l.label, value: l.id })) |
229 | |||
230 | const categories = this.serverService.getVideoCategories() | ||
231 | this.categoryItems = categories.map(l => ({ label: l.label, value: l.id })) | 234 | this.categoryItems = categories.map(l => ({ label: l.label, value: l.id })) |
232 | 235 | ||
233 | this.updateForm() | 236 | this.updateForm() |
@@ -249,12 +252,14 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { | |||
249 | 252 | ||
250 | async formValidated () { | 253 | async formValidated () { |
251 | this.configService.updateCustomConfig(this.form.value) | 254 | this.configService.updateCustomConfig(this.form.value) |
255 | .pipe( | ||
256 | ) | ||
252 | .subscribe( | 257 | .subscribe( |
253 | res => { | 258 | res => { |
254 | this.customConfig = res | 259 | this.customConfig = res |
255 | 260 | ||
256 | // Reload general configuration | 261 | // Reload general configuration |
257 | this.serverService.loadConfig() | 262 | this.serverService.resetConfig() |
258 | 263 | ||
259 | this.updateForm() | 264 | this.updateForm() |
260 | 265 | ||
diff --git a/client/src/app/+admin/moderation/moderation.component.ts b/client/src/app/+admin/moderation/moderation.component.ts index 47154af3f..7744deb06 100644 --- a/client/src/app/+admin/moderation/moderation.component.ts +++ b/client/src/app/+admin/moderation/moderation.component.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { Component } from '@angular/core' | 1 | import { Component, OnInit } from '@angular/core' |
2 | import { UserRight } from '../../../../../shared' | 2 | import { UserRight } from '../../../../../shared' |
3 | import { AuthService, ServerService } from '@app/core' | 3 | import { AuthService, ServerService } from '@app/core' |
4 | 4 | ||
@@ -6,14 +6,18 @@ import { AuthService, ServerService } from '@app/core' | |||
6 | templateUrl: './moderation.component.html', | 6 | templateUrl: './moderation.component.html', |
7 | styleUrls: [ './moderation.component.scss' ] | 7 | styleUrls: [ './moderation.component.scss' ] |
8 | }) | 8 | }) |
9 | export class ModerationComponent { | 9 | export class ModerationComponent implements OnInit { |
10 | autoBlacklistVideosEnabled: boolean | 10 | autoBlacklistVideosEnabled = false |
11 | 11 | ||
12 | constructor ( | 12 | constructor ( |
13 | private auth: AuthService, | 13 | private auth: AuthService, |
14 | private serverService: ServerService | 14 | private serverService: ServerService |
15 | ) { | 15 | ) { } |
16 | this.autoBlacklistVideosEnabled = this.serverService.getConfig().autoBlacklist.videos.ofUsers.enabled | 16 | |
17 | ngOnInit (): void { | ||
18 | this.serverService.getConfig() | ||
19 | .subscribe(config => this.autoBlacklistVideosEnabled = config.autoBlacklist.videos.ofUsers.enabled) | ||
20 | |||
17 | } | 21 | } |
18 | 22 | ||
19 | hasVideoAbusesRight () { | 23 | hasVideoAbusesRight () { |
diff --git a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts b/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts index f4bce7c48..5876f658b 100644 --- a/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts +++ b/client/src/app/+admin/moderation/video-blacklist-list/video-blacklist-list.component.ts | |||
@@ -33,11 +33,18 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit { | |||
33 | private i18n: I18n | 33 | private i18n: I18n |
34 | ) { | 34 | ) { |
35 | super() | 35 | super() |
36 | } | ||
36 | 37 | ||
37 | // don't filter if auto-blacklist not enabled as this will be only list | 38 | ngOnInit () { |
38 | if (this.serverService.getConfig().autoBlacklist.videos.ofUsers.enabled) { | 39 | this.serverService.getConfig() |
39 | this.listBlacklistTypeFilter = VideoBlacklistType.MANUAL | 40 | .subscribe(config => { |
40 | } | 41 | // don't filter if auto-blacklist not enabled as this will be only list |
42 | if (config.autoBlacklist.videos.ofUsers.enabled) { | ||
43 | this.listBlacklistTypeFilter = VideoBlacklistType.MANUAL | ||
44 | } | ||
45 | }) | ||
46 | |||
47 | this.initialize() | ||
41 | 48 | ||
42 | this.videoBlacklistActions = [ | 49 | this.videoBlacklistActions = [ |
43 | { | 50 | { |
@@ -47,10 +54,6 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit { | |||
47 | ] | 54 | ] |
48 | } | 55 | } |
49 | 56 | ||
50 | ngOnInit () { | ||
51 | this.initialize() | ||
52 | } | ||
53 | |||
54 | getVideoUrl (videoBlacklist: VideoBlacklist) { | 57 | getVideoUrl (videoBlacklist: VideoBlacklist) { |
55 | return Video.buildClientUrl(videoBlacklist.video.uuid) | 58 | return Video.buildClientUrl(videoBlacklist.video.uuid) |
56 | } | 59 | } |
diff --git a/client/src/app/+admin/users/user-edit/user-create.component.ts b/client/src/app/+admin/users/user-edit/user-create.component.ts index 3b57a49c6..e726ec4d7 100644 --- a/client/src/app/+admin/users/user-edit/user-create.component.ts +++ b/client/src/app/+admin/users/user-edit/user-create.component.ts | |||
@@ -34,6 +34,8 @@ export class UserCreateComponent extends UserEdit implements OnInit { | |||
34 | } | 34 | } |
35 | 35 | ||
36 | ngOnInit () { | 36 | ngOnInit () { |
37 | super.ngOnInit() | ||
38 | |||
37 | const defaultValues = { | 39 | const defaultValues = { |
38 | role: UserRole.USER.toString(), | 40 | role: UserRole.USER.toString(), |
39 | videoQuota: '-1', | 41 | videoQuota: '-1', |
diff --git a/client/src/app/+admin/users/user-edit/user-edit.ts b/client/src/app/+admin/users/user-edit/user-edit.ts index 6625d65d6..02f1dcd42 100644 --- a/client/src/app/+admin/users/user-edit/user-edit.ts +++ b/client/src/app/+admin/users/user-edit/user-edit.ts | |||
@@ -1,21 +1,30 @@ | |||
1 | import { AuthService, ServerService } from '../../../core' | 1 | import { AuthService, ServerService } from '../../../core' |
2 | import { FormReactive } from '../../../shared' | 2 | import { FormReactive } from '../../../shared' |
3 | import { USER_ROLE_LABELS, UserRole, VideoResolution } from '../../../../../../shared' | 3 | import { ServerConfig, USER_ROLE_LABELS, UserRole, VideoResolution } from '../../../../../../shared' |
4 | import { ConfigService } from '@app/+admin/config/shared/config.service' | 4 | import { ConfigService } from '@app/+admin/config/shared/config.service' |
5 | import { UserAdminFlag } from '@shared/models/users/user-flag.model' | 5 | import { UserAdminFlag } from '@shared/models/users/user-flag.model' |
6 | import { OnInit } from '@angular/core' | ||
6 | 7 | ||
7 | export abstract class UserEdit extends FormReactive { | 8 | export abstract class UserEdit extends FormReactive implements OnInit { |
8 | videoQuotaOptions: { value: string, label: string }[] = [] | 9 | videoQuotaOptions: { value: string, label: string }[] = [] |
9 | videoQuotaDailyOptions: { value: string, label: string }[] = [] | 10 | videoQuotaDailyOptions: { value: string, label: string }[] = [] |
10 | username: string | 11 | username: string |
11 | userId: number | 12 | userId: number |
12 | 13 | ||
14 | protected serverConfig: ServerConfig | ||
15 | |||
13 | protected abstract serverService: ServerService | 16 | protected abstract serverService: ServerService |
14 | protected abstract configService: ConfigService | 17 | protected abstract configService: ConfigService |
15 | protected abstract auth: AuthService | 18 | protected abstract auth: AuthService |
16 | abstract isCreation (): boolean | 19 | abstract isCreation (): boolean |
17 | abstract getFormButtonTitle (): string | 20 | abstract getFormButtonTitle (): string |
18 | 21 | ||
22 | ngOnInit (): void { | ||
23 | this.serverConfig = this.serverService.getTmpConfig() | ||
24 | this.serverService.getConfig() | ||
25 | .subscribe(config => this.serverConfig = config) | ||
26 | } | ||
27 | |||
19 | getRoles () { | 28 | getRoles () { |
20 | const authUser = this.auth.getUser() | 29 | const authUser = this.auth.getUser() |
21 | 30 | ||
@@ -32,12 +41,12 @@ export abstract class UserEdit extends FormReactive { | |||
32 | isTranscodingInformationDisplayed () { | 41 | isTranscodingInformationDisplayed () { |
33 | const formVideoQuota = parseInt(this.form.value['videoQuota'], 10) | 42 | const formVideoQuota = parseInt(this.form.value['videoQuota'], 10) |
34 | 43 | ||
35 | return this.serverService.getConfig().transcoding.enabledResolutions.length !== 0 && | 44 | return this.serverConfig.transcoding.enabledResolutions.length !== 0 && |
36 | formVideoQuota > 0 | 45 | formVideoQuota > 0 |
37 | } | 46 | } |
38 | 47 | ||
39 | computeQuotaWithTranscoding () { | 48 | computeQuotaWithTranscoding () { |
40 | const transcodingConfig = this.serverService.getConfig().transcoding | 49 | const transcodingConfig = this.serverConfig.transcoding |
41 | 50 | ||
42 | const resolutions = transcodingConfig.enabledResolutions | 51 | const resolutions = transcodingConfig.enabledResolutions |
43 | const higherResolution = VideoResolution.H_4K | 52 | const higherResolution = VideoResolution.H_4K |
diff --git a/client/src/app/+admin/users/user-edit/user-update.component.ts b/client/src/app/+admin/users/user-edit/user-update.component.ts index c7052a925..d1682a99d 100644 --- a/client/src/app/+admin/users/user-edit/user-update.component.ts +++ b/client/src/app/+admin/users/user-edit/user-update.component.ts | |||
@@ -43,6 +43,8 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy { | |||
43 | } | 43 | } |
44 | 44 | ||
45 | ngOnInit () { | 45 | ngOnInit () { |
46 | super.ngOnInit() | ||
47 | |||
46 | const defaultValues = { videoQuota: '-1', videoQuotaDaily: '-1' } | 48 | const defaultValues = { videoQuota: '-1', videoQuotaDaily: '-1' } |
47 | this.buildForm({ | 49 | this.buildForm({ |
48 | email: this.userValidatorsService.USER_EMAIL, | 50 | email: this.userValidatorsService.USER_EMAIL, |
diff --git a/client/src/app/+admin/users/user-list/user-list.component.ts b/client/src/app/+admin/users/user-list/user-list.component.ts index ab82713b2..1083ba291 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.ts +++ b/client/src/app/+admin/users/user-list/user-list.component.ts | |||
@@ -4,7 +4,7 @@ import { SortMeta } from 'primeng/components/common/sortmeta' | |||
4 | import { ConfirmService, ServerService } from '../../../core' | 4 | import { ConfirmService, ServerService } from '../../../core' |
5 | import { RestPagination, RestTable, UserService } from '../../../shared' | 5 | import { RestPagination, RestTable, UserService } from '../../../shared' |
6 | import { I18n } from '@ngx-translate/i18n-polyfill' | 6 | import { I18n } from '@ngx-translate/i18n-polyfill' |
7 | import { User } from '../../../../../../shared' | 7 | import { ServerConfig, User } from '../../../../../../shared' |
8 | import { UserBanModalComponent } from '@app/shared/moderation' | 8 | import { UserBanModalComponent } from '@app/shared/moderation' |
9 | import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' | 9 | import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' |
10 | 10 | ||
@@ -25,6 +25,8 @@ export class UserListComponent extends RestTable implements OnInit { | |||
25 | selectedUsers: User[] = [] | 25 | selectedUsers: User[] = [] |
26 | bulkUserActions: DropdownAction<User[]>[] = [] | 26 | bulkUserActions: DropdownAction<User[]>[] = [] |
27 | 27 | ||
28 | private serverConfig: ServerConfig | ||
29 | |||
28 | constructor ( | 30 | constructor ( |
29 | private notifier: Notifier, | 31 | private notifier: Notifier, |
30 | private confirmService: ConfirmService, | 32 | private confirmService: ConfirmService, |
@@ -41,10 +43,14 @@ export class UserListComponent extends RestTable implements OnInit { | |||
41 | } | 43 | } |
42 | 44 | ||
43 | get requiresEmailVerification () { | 45 | get requiresEmailVerification () { |
44 | return this.serverService.getConfig().signup.requiresEmailVerification | 46 | return this.serverConfig.signup.requiresEmailVerification |
45 | } | 47 | } |
46 | 48 | ||
47 | ngOnInit () { | 49 | ngOnInit () { |
50 | this.serverConfig = this.serverService.getTmpConfig() | ||
51 | this.serverService.getConfig() | ||
52 | .subscribe(config => this.serverConfig = config) | ||
53 | |||
48 | this.initialize() | 54 | this.initialize() |
49 | 55 | ||
50 | this.bulkUserActions = [ | 56 | this.bulkUserActions = [ |
diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts b/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts index ec7cf935c..9d406805f 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts | |||
@@ -6,6 +6,7 @@ import { FormValidatorService } from '@app/shared/forms/form-validators/form-val | |||
6 | import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service' | 6 | import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service' |
7 | import { User } from '../../../../../../shared' | 7 | import { User } from '../../../../../../shared' |
8 | import { tap } from 'rxjs/operators' | 8 | import { tap } from 'rxjs/operators' |
9 | import { forkJoin } from 'rxjs' | ||
9 | 10 | ||
10 | @Component({ | 11 | @Component({ |
11 | selector: 'my-account-change-email', | 12 | selector: 'my-account-change-email', |
@@ -45,29 +46,29 @@ export class MyAccountChangeEmailComponent extends FormReactive implements OnIni | |||
45 | const password = this.form.value[ 'password' ] | 46 | const password = this.form.value[ 'password' ] |
46 | const email = this.form.value[ 'new-email' ] | 47 | const email = this.form.value[ 'new-email' ] |
47 | 48 | ||
48 | this.userService.changeEmail(password, email) | 49 | forkJoin([ |
49 | .pipe( | 50 | this.serverService.getConfig(), |
50 | tap(() => this.authService.refreshUserInformation()) | 51 | this.userService.changeEmail(password, email) |
51 | ) | 52 | ]).pipe(tap(() => this.authService.refreshUserInformation())) |
52 | .subscribe( | 53 | .subscribe( |
53 | () => { | 54 | ([ config ]) => { |
54 | this.form.reset() | 55 | this.form.reset() |
55 | 56 | ||
56 | if (this.serverService.getConfig().signup.requiresEmailVerification) { | 57 | if (config.signup.requiresEmailVerification) { |
57 | this.success = this.i18n('Please check your emails to verify your new email.') | 58 | this.success = this.i18n('Please check your emails to verify your new email.') |
58 | } else { | 59 | } else { |
59 | this.success = this.i18n('Email updated.') | 60 | this.success = this.i18n('Email updated.') |
60 | } | 61 | } |
61 | }, | 62 | }, |
62 | |||
63 | err => { | ||
64 | if (err.status === 401) { | ||
65 | this.error = this.i18n('You current password is invalid.') | ||
66 | return | ||
67 | } | ||
68 | 63 | ||
69 | this.error = err.message | 64 | err => { |
65 | if (err.status === 401) { | ||
66 | this.error = this.i18n('You current password is invalid.') | ||
67 | return | ||
70 | } | 68 | } |
71 | ) | 69 | |
70 | this.error = err.message | ||
71 | } | ||
72 | ) | ||
72 | } | 73 | } |
73 | } | 74 | } |
diff --git a/client/src/app/+my-account/my-account-settings/my-account-interface/my-account-interface-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-interface/my-account-interface-settings.component.ts index 5ec1c9f8f..441f89f10 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-interface/my-account-interface-settings.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-interface/my-account-interface-settings.component.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { Component, Input, OnInit } from '@angular/core' | 1 | import { Component, Input, OnInit } from '@angular/core' |
2 | import { Notifier, ServerService } from '@app/core' | 2 | import { Notifier, ServerService } from '@app/core' |
3 | import { UserUpdateMe } from '../../../../../../shared' | 3 | import { ServerConfig, UserUpdateMe } from '../../../../../../shared' |
4 | import { AuthService } from '../../../core' | 4 | import { AuthService } from '../../../core' |
5 | import { FormReactive, User, UserService } from '../../../shared' | 5 | import { FormReactive, User, UserService } from '../../../shared' |
6 | import { I18n } from '@ngx-translate/i18n-polyfill' | 6 | import { I18n } from '@ngx-translate/i18n-polyfill' |
@@ -16,6 +16,8 @@ export class MyAccountInterfaceSettingsComponent extends FormReactive implements | |||
16 | @Input() user: User = null | 16 | @Input() user: User = null |
17 | @Input() userInformationLoaded: Subject<any> | 17 | @Input() userInformationLoaded: Subject<any> |
18 | 18 | ||
19 | private serverConfig: ServerConfig | ||
20 | |||
19 | constructor ( | 21 | constructor ( |
20 | protected formValidatorService: FormValidatorService, | 22 | protected formValidatorService: FormValidatorService, |
21 | private authService: AuthService, | 23 | private authService: AuthService, |
@@ -28,11 +30,15 @@ export class MyAccountInterfaceSettingsComponent extends FormReactive implements | |||
28 | } | 30 | } |
29 | 31 | ||
30 | get availableThemes () { | 32 | get availableThemes () { |
31 | return this.serverService.getConfig().theme.registered | 33 | return this.serverConfig.theme.registered |
32 | .map(t => t.name) | 34 | .map(t => t.name) |
33 | } | 35 | } |
34 | 36 | ||
35 | ngOnInit () { | 37 | ngOnInit () { |
38 | this.serverConfig = this.serverService.getTmpConfig() | ||
39 | this.serverService.getConfig() | ||
40 | .subscribe(config => this.serverConfig = config) | ||
41 | |||
36 | this.buildForm({ | 42 | this.buildForm({ |
37 | theme: null | 43 | theme: null |
38 | }) | 44 | }) |
diff --git a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts index 76fabb19d..6ba1a1020 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts | |||
@@ -21,7 +21,7 @@ export class MyAccountNotificationPreferencesComponent implements OnInit { | |||
21 | webNotifications: { [ id in keyof UserNotificationSetting ]: boolean } = {} as any | 21 | webNotifications: { [ id in keyof UserNotificationSetting ]: boolean } = {} as any |
22 | labelNotifications: { [ id in keyof UserNotificationSetting ]: string } = {} as any | 22 | labelNotifications: { [ id in keyof UserNotificationSetting ]: string } = {} as any |
23 | rightNotifications: { [ id in keyof Partial<UserNotificationSetting> ]: UserRight } = {} as any | 23 | rightNotifications: { [ id in keyof Partial<UserNotificationSetting> ]: UserRight } = {} as any |
24 | emailEnabled: boolean | 24 | emailEnabled = false |
25 | 25 | ||
26 | private savePreferences = debounce(this.savePreferencesImpl.bind(this), 500) | 26 | private savePreferences = debounce(this.savePreferencesImpl.bind(this), 500) |
27 | 27 | ||
@@ -31,7 +31,6 @@ export class MyAccountNotificationPreferencesComponent implements OnInit { | |||
31 | private serverService: ServerService, | 31 | private serverService: ServerService, |
32 | private notifier: Notifier | 32 | private notifier: Notifier |
33 | ) { | 33 | ) { |
34 | |||
35 | this.labelNotifications = { | 34 | this.labelNotifications = { |
36 | newVideoFromSubscription: this.i18n('New video from your subscriptions'), | 35 | newVideoFromSubscription: this.i18n('New video from your subscriptions'), |
37 | newCommentOnMyVideo: this.i18n('New comment on your video'), | 36 | newCommentOnMyVideo: this.i18n('New comment on your video'), |
@@ -55,11 +54,14 @@ export class MyAccountNotificationPreferencesComponent implements OnInit { | |||
55 | newInstanceFollower: UserRight.MANAGE_SERVER_FOLLOW, | 54 | newInstanceFollower: UserRight.MANAGE_SERVER_FOLLOW, |
56 | autoInstanceFollowing: UserRight.MANAGE_CONFIGURATION | 55 | autoInstanceFollowing: UserRight.MANAGE_CONFIGURATION |
57 | } | 56 | } |
58 | |||
59 | this.emailEnabled = this.serverService.getConfig().email.enabled | ||
60 | } | 57 | } |
61 | 58 | ||
62 | ngOnInit () { | 59 | ngOnInit () { |
60 | this.serverService.getConfig() | ||
61 | .subscribe(config => { | ||
62 | this.emailEnabled = config.email.enabled | ||
63 | }) | ||
64 | |||
63 | this.userInformationLoaded.subscribe(() => this.loadNotificationSettings()) | 65 | this.userInformationLoaded.subscribe(() => this.loadNotificationSettings()) |
64 | } | 66 | } |
65 | 67 | ||
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts index 99eee23b8..a66159b3f 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts | |||
@@ -41,11 +41,9 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI | |||
41 | }) | 41 | }) |
42 | 42 | ||
43 | forkJoin([ | 43 | forkJoin([ |
44 | this.serverService.videoLanguagesLoaded.pipe(first()), | 44 | this.serverService.getVideoLanguages(), |
45 | this.userInformationLoaded.pipe(first()) | 45 | this.userInformationLoaded.pipe(first()) |
46 | ]).subscribe(() => { | 46 | ]).subscribe(([ languages ]) => { |
47 | const languages = this.serverService.getVideoLanguages() | ||
48 | |||
49 | this.languageItems = [ { label: this.i18n('Unknown language'), value: '_unknown' } ] | 47 | this.languageItems = [ { label: this.i18n('Unknown language'), value: '_unknown' } ] |
50 | this.languageItems = this.languageItems | 48 | this.languageItems = this.languageItems |
51 | .concat(languages.map(l => ({ label: l.label, value: l.id }))) | 49 | .concat(languages.map(l => ({ label: l.label, value: l.id }))) |
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts index 081e956d2..9c948b367 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts | |||
@@ -9,6 +9,7 @@ import { VideoChannel } from '@app/shared/video-channel/video-channel.model' | |||
9 | import { I18n } from '@ngx-translate/i18n-polyfill' | 9 | import { I18n } from '@ngx-translate/i18n-polyfill' |
10 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' | 10 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' |
11 | import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators/video-channel-validators.service' | 11 | import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators/video-channel-validators.service' |
12 | import { ServerConfig } from '@shared/models' | ||
12 | 13 | ||
13 | @Component({ | 14 | @Component({ |
14 | selector: 'my-account-video-channel-update', | 15 | selector: 'my-account-video-channel-update', |
@@ -21,6 +22,7 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE | |||
21 | 22 | ||
22 | private paramsSub: Subscription | 23 | private paramsSub: Subscription |
23 | private oldSupportField: string | 24 | private oldSupportField: string |
25 | private serverConfig: ServerConfig | ||
24 | 26 | ||
25 | constructor ( | 27 | constructor ( |
26 | protected formValidatorService: FormValidatorService, | 28 | protected formValidatorService: FormValidatorService, |
@@ -37,6 +39,10 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE | |||
37 | } | 39 | } |
38 | 40 | ||
39 | ngOnInit () { | 41 | ngOnInit () { |
42 | this.serverConfig = this.serverService.getTmpConfig() | ||
43 | this.serverService.getConfig() | ||
44 | .subscribe(config => this.serverConfig = config) | ||
45 | |||
40 | this.buildForm({ | 46 | this.buildForm({ |
41 | 'display-name': this.videoChannelValidatorsService.VIDEO_CHANNEL_DISPLAY_NAME, | 47 | 'display-name': this.videoChannelValidatorsService.VIDEO_CHANNEL_DISPLAY_NAME, |
42 | description: this.videoChannelValidatorsService.VIDEO_CHANNEL_DESCRIPTION, | 48 | description: this.videoChannelValidatorsService.VIDEO_CHANNEL_DESCRIPTION, |
@@ -109,11 +115,11 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE | |||
109 | } | 115 | } |
110 | 116 | ||
111 | get maxAvatarSize () { | 117 | get maxAvatarSize () { |
112 | return this.serverService.getConfig().avatar.file.size.max | 118 | return this.serverConfig.avatar.file.size.max |
113 | } | 119 | } |
114 | 120 | ||
115 | get avatarExtensions () { | 121 | get avatarExtensions () { |
116 | return this.serverService.getConfig().avatar.file.extensions.join(',') | 122 | return this.serverConfig.avatar.file.extensions.join(',') |
117 | } | 123 | } |
118 | 124 | ||
119 | isCreation () { | 125 | isCreation () { |
diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-create.component.ts b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-create.component.ts index 8aed8b513..e47e5f980 100644 --- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-create.component.ts +++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-create.component.ts | |||
@@ -47,15 +47,14 @@ export class MyAccountVideoPlaylistCreateComponent extends MyAccountVideoPlaylis | |||
47 | populateAsyncUserVideoChannels(this.authService, this.userVideoChannels) | 47 | populateAsyncUserVideoChannels(this.authService, this.userVideoChannels) |
48 | .catch(err => console.error('Cannot populate user video channels.', err)) | 48 | .catch(err => console.error('Cannot populate user video channels.', err)) |
49 | 49 | ||
50 | this.serverService.videoPlaylistPrivaciesLoaded.subscribe( | 50 | this.serverService.getVideoPlaylistPrivacies() |
51 | () => { | 51 | .subscribe(videoPlaylistPrivacies => { |
52 | this.videoPlaylistPrivacies = this.serverService.getVideoPlaylistPrivacies() | 52 | this.videoPlaylistPrivacies = videoPlaylistPrivacies |
53 | 53 | ||
54 | this.form.patchValue({ | 54 | this.form.patchValue({ |
55 | privacy: VideoPlaylistPrivacy.PRIVATE | 55 | privacy: VideoPlaylistPrivacy.PRIVATE |
56 | }) | ||
56 | }) | 57 | }) |
57 | } | ||
58 | ) | ||
59 | } | 58 | } |
60 | 59 | ||
61 | formValidated () { | 60 | formValidated () { |
diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-update.component.ts b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-update.component.ts index 917ad7258..2f85cdd96 100644 --- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-update.component.ts +++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-update.component.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { Component, OnDestroy, OnInit } from '@angular/core' | 1 | import { Component, OnDestroy, OnInit } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | 2 | import { ActivatedRoute, Router } from '@angular/router' |
3 | import { AuthService, Notifier, ServerService } from '@app/core' | 3 | import { AuthService, Notifier, ServerService } from '@app/core' |
4 | import { Subscription } from 'rxjs' | 4 | import { forkJoin, Subscription } from 'rxjs' |
5 | import { I18n } from '@ngx-translate/i18n-polyfill' | 5 | import { I18n } from '@ngx-translate/i18n-polyfill' |
6 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' | 6 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' |
7 | import { MyAccountVideoPlaylistEdit } from '@app/+my-account/my-account-video-playlists/my-account-video-playlist-edit' | 7 | import { MyAccountVideoPlaylistEdit } from '@app/+my-account/my-account-video-playlists/my-account-video-playlist-edit' |
@@ -56,13 +56,17 @@ export class MyAccountVideoPlaylistUpdateComponent extends MyAccountVideoPlaylis | |||
56 | this.paramsSub = this.route.params | 56 | this.paramsSub = this.route.params |
57 | .pipe( | 57 | .pipe( |
58 | map(routeParams => routeParams['videoPlaylistId']), | 58 | map(routeParams => routeParams['videoPlaylistId']), |
59 | switchMap(videoPlaylistId => this.videoPlaylistService.getVideoPlaylist(videoPlaylistId)), | 59 | switchMap(videoPlaylistId => { |
60 | delayWhen(() => this.serverService.videoPlaylistPrivaciesLoaded) | 60 | return forkJoin([ |
61 | this.videoPlaylistService.getVideoPlaylist(videoPlaylistId), | ||
62 | this.serverService.getVideoPlaylistPrivacies() | ||
63 | ]) | ||
64 | }) | ||
61 | ) | 65 | ) |
62 | .subscribe( | 66 | .subscribe( |
63 | videoPlaylistToUpdate => { | 67 | ([ videoPlaylistToUpdate, videoPlaylistPrivacies]) => { |
64 | this.videoPlaylistPrivacies = this.serverService.getVideoPlaylistPrivacies() | ||
65 | this.videoPlaylistToUpdate = videoPlaylistToUpdate | 68 | this.videoPlaylistToUpdate = videoPlaylistToUpdate |
69 | this.videoPlaylistPrivacies = videoPlaylistPrivacies | ||
66 | 70 | ||
67 | this.hydrateFormFromPlaylist() | 71 | this.hydrateFormFromPlaylist() |
68 | }, | 72 | }, |
diff --git a/client/src/app/+my-account/my-account.component.ts b/client/src/app/+my-account/my-account.component.ts index d98d06f8e..05dcf522d 100644 --- a/client/src/app/+my-account/my-account.component.ts +++ b/client/src/app/+my-account/my-account.component.ts | |||
@@ -1,20 +1,28 @@ | |||
1 | import { Component } from '@angular/core' | 1 | import { Component, OnInit } from '@angular/core' |
2 | import { ServerService } from '@app/core' | 2 | import { ServerService } from '@app/core' |
3 | import { I18n } from '@ngx-translate/i18n-polyfill' | 3 | import { I18n } from '@ngx-translate/i18n-polyfill' |
4 | import { TopMenuDropdownParam } from '@app/shared/menu/top-menu-dropdown.component' | 4 | import { TopMenuDropdownParam } from '@app/shared/menu/top-menu-dropdown.component' |
5 | import { ServerConfig } from '@shared/models' | ||
5 | 6 | ||
6 | @Component({ | 7 | @Component({ |
7 | selector: 'my-my-account', | 8 | selector: 'my-my-account', |
8 | templateUrl: './my-account.component.html', | 9 | templateUrl: './my-account.component.html', |
9 | styleUrls: [ './my-account.component.scss' ] | 10 | styleUrls: [ './my-account.component.scss' ] |
10 | }) | 11 | }) |
11 | export class MyAccountComponent { | 12 | export class MyAccountComponent implements OnInit { |
12 | menuEntries: TopMenuDropdownParam[] = [] | 13 | menuEntries: TopMenuDropdownParam[] = [] |
13 | 14 | ||
15 | private serverConfig: ServerConfig | ||
16 | |||
14 | constructor ( | 17 | constructor ( |
15 | private serverService: ServerService, | 18 | private serverService: ServerService, |
16 | private i18n: I18n | 19 | private i18n: I18n |
17 | ) { | 20 | ) { } |
21 | |||
22 | ngOnInit (): void { | ||
23 | this.serverConfig = this.serverService.getTmpConfig() | ||
24 | this.serverService.getConfig() | ||
25 | .subscribe(config => this.serverConfig = config) | ||
18 | 26 | ||
19 | const libraryEntries: TopMenuDropdownParam = { | 27 | const libraryEntries: TopMenuDropdownParam = { |
20 | label: this.i18n('My library'), | 28 | label: this.i18n('My library'), |
@@ -91,7 +99,7 @@ export class MyAccountComponent { | |||
91 | } | 99 | } |
92 | 100 | ||
93 | isVideoImportEnabled () { | 101 | isVideoImportEnabled () { |
94 | const importConfig = this.serverService.getConfig().import.videos | 102 | const importConfig = this.serverConfig.import.videos |
95 | 103 | ||
96 | return importConfig.http.enabled || importConfig.torrent.enabled | 104 | return importConfig.http.enabled || importConfig.torrent.enabled |
97 | } | 105 | } |
diff --git a/client/src/app/+my-account/shared/actor-avatar-info.component.ts b/client/src/app/+my-account/shared/actor-avatar-info.component.ts index 0289a66c3..101dfa556 100644 --- a/client/src/app/+my-account/shared/actor-avatar-info.component.ts +++ b/client/src/app/+my-account/shared/actor-avatar-info.component.ts | |||
@@ -1,26 +1,35 @@ | |||
1 | import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core' | 1 | import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' |
2 | import { ServerService } from '../../core/server' | 2 | import { ServerService } from '../../core/server' |
3 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' | 3 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' |
4 | import { Account } from '@app/shared/account/account.model' | 4 | import { Account } from '@app/shared/account/account.model' |
5 | import { Notifier } from '@app/core' | 5 | import { Notifier } from '@app/core' |
6 | import { ServerConfig } from '@shared/models' | ||
6 | 7 | ||
7 | @Component({ | 8 | @Component({ |
8 | selector: 'my-actor-avatar-info', | 9 | selector: 'my-actor-avatar-info', |
9 | templateUrl: './actor-avatar-info.component.html', | 10 | templateUrl: './actor-avatar-info.component.html', |
10 | styleUrls: [ './actor-avatar-info.component.scss' ] | 11 | styleUrls: [ './actor-avatar-info.component.scss' ] |
11 | }) | 12 | }) |
12 | export class ActorAvatarInfoComponent { | 13 | export class ActorAvatarInfoComponent implements OnInit { |
13 | @ViewChild('avatarfileInput', { static: false }) avatarfileInput: ElementRef<HTMLInputElement> | 14 | @ViewChild('avatarfileInput', { static: false }) avatarfileInput: ElementRef<HTMLInputElement> |
14 | 15 | ||
15 | @Input() actor: VideoChannel | Account | 16 | @Input() actor: VideoChannel | Account |
16 | 17 | ||
17 | @Output() avatarChange = new EventEmitter<FormData>() | 18 | @Output() avatarChange = new EventEmitter<FormData>() |
18 | 19 | ||
20 | private serverConfig: ServerConfig | ||
21 | |||
19 | constructor ( | 22 | constructor ( |
20 | private serverService: ServerService, | 23 | private serverService: ServerService, |
21 | private notifier: Notifier | 24 | private notifier: Notifier |
22 | ) {} | 25 | ) {} |
23 | 26 | ||
27 | ngOnInit (): void { | ||
28 | this.serverConfig = this.serverService.getTmpConfig() | ||
29 | this.serverService.getConfig() | ||
30 | .subscribe(config => this.serverConfig = config) | ||
31 | } | ||
32 | |||
24 | onAvatarChange () { | 33 | onAvatarChange () { |
25 | const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ] | 34 | const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ] |
26 | if (avatarfile.size > this.maxAvatarSize) { | 35 | if (avatarfile.size > this.maxAvatarSize) { |
@@ -35,10 +44,10 @@ export class ActorAvatarInfoComponent { | |||
35 | } | 44 | } |
36 | 45 | ||
37 | get maxAvatarSize () { | 46 | get maxAvatarSize () { |
38 | return this.serverService.getConfig().avatar.file.size.max | 47 | return this.serverConfig.avatar.file.size.max |
39 | } | 48 | } |
40 | 49 | ||
41 | get avatarExtensions () { | 50 | get avatarExtensions () { |
42 | return this.serverService.getConfig().avatar.file.extensions.join(',') | 51 | return this.serverConfig.avatar.file.extensions.join(',') |
43 | } | 52 | } |
44 | } | 53 | } |
diff --git a/client/src/app/+signup/+register/register-routing.module.ts b/client/src/app/+signup/+register/register-routing.module.ts index e3a5001dc..f47e80755 100644 --- a/client/src/app/+signup/+register/register-routing.module.ts +++ b/client/src/app/+signup/+register/register-routing.module.ts | |||
@@ -16,7 +16,7 @@ const registerRoutes: Routes = [ | |||
16 | } | 16 | } |
17 | }, | 17 | }, |
18 | resolve: { | 18 | resolve: { |
19 | serverConfigLoaded: ServerConfigResolver | 19 | serverConfig: ServerConfigResolver |
20 | } | 20 | } |
21 | } | 21 | } |
22 | ] | 22 | ] |
diff --git a/client/src/app/+signup/+register/register.component.ts b/client/src/app/+signup/+register/register.component.ts index acec56f04..ae944ec15 100644 --- a/client/src/app/+signup/+register/register.component.ts +++ b/client/src/app/+signup/+register/register.component.ts | |||
@@ -4,10 +4,11 @@ import { UserService, UserValidatorsService } from '@app/shared' | |||
4 | import { I18n } from '@ngx-translate/i18n-polyfill' | 4 | import { I18n } from '@ngx-translate/i18n-polyfill' |
5 | import { UserRegister } from '@shared/models/users/user-register.model' | 5 | import { UserRegister } from '@shared/models/users/user-register.model' |
6 | import { FormGroup } from '@angular/forms' | 6 | import { FormGroup } from '@angular/forms' |
7 | import { About } from '@shared/models/server' | 7 | import { About, ServerConfig } from '@shared/models/server' |
8 | import { InstanceService } from '@app/shared/instance/instance.service' | 8 | import { InstanceService } from '@app/shared/instance/instance.service' |
9 | import { HooksService } from '@app/core/plugins/hooks.service' | 9 | import { HooksService } from '@app/core/plugins/hooks.service' |
10 | import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap' | 10 | import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap' |
11 | import { ActivatedRoute } from '@angular/router' | ||
11 | 12 | ||
12 | @Component({ | 13 | @Component({ |
13 | selector: 'my-register', | 14 | selector: 'my-register', |
@@ -34,7 +35,10 @@ export class RegisterComponent implements OnInit { | |||
34 | formStepUser: FormGroup | 35 | formStepUser: FormGroup |
35 | formStepChannel: FormGroup | 36 | formStepChannel: FormGroup |
36 | 37 | ||
38 | private serverConfig: ServerConfig | ||
39 | |||
37 | constructor ( | 40 | constructor ( |
41 | private route: ActivatedRoute, | ||
38 | private authService: AuthService, | 42 | private authService: AuthService, |
39 | private userValidatorsService: UserValidatorsService, | 43 | private userValidatorsService: UserValidatorsService, |
40 | private notifier: Notifier, | 44 | private notifier: Notifier, |
@@ -48,10 +52,12 @@ export class RegisterComponent implements OnInit { | |||
48 | } | 52 | } |
49 | 53 | ||
50 | get requiresEmailVerification () { | 54 | get requiresEmailVerification () { |
51 | return this.serverService.getConfig().signup.requiresEmailVerification | 55 | return this.serverConfig.signup.requiresEmailVerification |
52 | } | 56 | } |
53 | 57 | ||
54 | ngOnInit (): void { | 58 | ngOnInit (): void { |
59 | this.serverConfig = this.route.snapshot.data.serverConfig | ||
60 | |||
55 | this.instanceService.getAbout() | 61 | this.instanceService.getAbout() |
56 | .subscribe( | 62 | .subscribe( |
57 | async about => { | 63 | async about => { |
diff --git a/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts b/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts index cfd471fa4..3bd604b66 100644 --- a/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts +++ b/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts | |||
@@ -5,6 +5,7 @@ import { ServerService } from '@app/core/server' | |||
5 | import { FormReactive, UserService } from '@app/shared' | 5 | import { FormReactive, UserService } from '@app/shared' |
6 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' | 6 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' |
7 | import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service' | 7 | import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service' |
8 | import { ServerConfig } from '@shared/models' | ||
8 | 9 | ||
9 | @Component({ | 10 | @Component({ |
10 | selector: 'my-verify-account-ask-send-email', | 11 | selector: 'my-verify-account-ask-send-email', |
@@ -13,6 +14,7 @@ import { UserValidatorsService } from '@app/shared/forms/form-validators/user-va | |||
13 | }) | 14 | }) |
14 | 15 | ||
15 | export class VerifyAccountAskSendEmailComponent extends FormReactive implements OnInit { | 16 | export class VerifyAccountAskSendEmailComponent extends FormReactive implements OnInit { |
17 | private serverConfig: ServerConfig | ||
16 | 18 | ||
17 | constructor ( | 19 | constructor ( |
18 | protected formValidatorService: FormValidatorService, | 20 | protected formValidatorService: FormValidatorService, |
@@ -27,10 +29,14 @@ export class VerifyAccountAskSendEmailComponent extends FormReactive implements | |||
27 | } | 29 | } |
28 | 30 | ||
29 | get requiresEmailVerification () { | 31 | get requiresEmailVerification () { |
30 | return this.serverService.getConfig().signup.requiresEmailVerification | 32 | return this.serverConfig.signup.requiresEmailVerification |
31 | } | 33 | } |
32 | 34 | ||
33 | ngOnInit () { | 35 | ngOnInit () { |
36 | this.serverConfig = this.serverService.getTmpConfig() | ||
37 | this.serverService.getConfig() | ||
38 | .subscribe(config => this.serverConfig = config) | ||
39 | |||
34 | this.buildForm({ | 40 | this.buildForm({ |
35 | 'verify-email-email': this.userValidatorsService.USER_EMAIL | 41 | 'verify-email-email': this.userValidatorsService.USER_EMAIL |
36 | }) | 42 | }) |
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index 351620c59..883f36514 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts | |||
@@ -15,7 +15,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | |||
15 | import { POP_STATE_MODAL_DISMISS } from '@app/shared/misc/constants' | 15 | import { POP_STATE_MODAL_DISMISS } from '@app/shared/misc/constants' |
16 | import { WelcomeModalComponent } from '@app/modal/welcome-modal.component' | 16 | import { WelcomeModalComponent } from '@app/modal/welcome-modal.component' |
17 | import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component' | 17 | import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component' |
18 | import { UserRole } from '@shared/models' | 18 | import { ServerConfig, UserRole } from '@shared/models' |
19 | import { User } from '@app/shared' | 19 | import { User } from '@app/shared' |
20 | import { InstanceService } from '@app/shared/instance/instance.service' | 20 | import { InstanceService } from '@app/shared/instance/instance.service' |
21 | 21 | ||
@@ -33,6 +33,8 @@ export class AppComponent implements OnInit { | |||
33 | 33 | ||
34 | customCSS: SafeHtml | 34 | customCSS: SafeHtml |
35 | 35 | ||
36 | private serverConfig: ServerConfig | ||
37 | |||
36 | constructor ( | 38 | constructor ( |
37 | private i18n: I18n, | 39 | private i18n: I18n, |
38 | private viewportScroller: ViewportScroller, | 40 | private viewportScroller: ViewportScroller, |
@@ -52,7 +54,7 @@ export class AppComponent implements OnInit { | |||
52 | ) { } | 54 | ) { } |
53 | 55 | ||
54 | get instanceName () { | 56 | get instanceName () { |
55 | return this.serverService.getConfig().instance.name | 57 | return this.serverConfig.instance.name |
56 | } | 58 | } |
57 | 59 | ||
58 | get defaultRoute () { | 60 | get defaultRoute () { |
@@ -62,6 +64,10 @@ export class AppComponent implements OnInit { | |||
62 | ngOnInit () { | 64 | ngOnInit () { |
63 | document.getElementById('incompatible-browser').className += ' browser-ok' | 65 | document.getElementById('incompatible-browser').className += ' browser-ok' |
64 | 66 | ||
67 | this.serverConfig = this.serverService.getTmpConfig() | ||
68 | this.serverService.getConfig() | ||
69 | .subscribe(config => this.serverConfig = config) | ||
70 | |||
65 | this.loadPlugins() | 71 | this.loadPlugins() |
66 | this.themeService.initialize() | 72 | this.themeService.initialize() |
67 | 73 | ||
@@ -72,14 +78,6 @@ export class AppComponent implements OnInit { | |||
72 | this.authService.refreshUserInformation() | 78 | this.authService.refreshUserInformation() |
73 | } | 79 | } |
74 | 80 | ||
75 | // Load custom data from server | ||
76 | this.serverService.loadConfig() | ||
77 | this.serverService.loadVideoCategories() | ||
78 | this.serverService.loadVideoLanguages() | ||
79 | this.serverService.loadVideoLicences() | ||
80 | this.serverService.loadVideoPrivacies() | ||
81 | this.serverService.loadVideoPlaylistPrivacies() | ||
82 | |||
83 | // Do not display menu on small screens | 81 | // Do not display menu on small screens |
84 | if (this.screenService.isInSmallView()) { | 82 | if (this.screenService.isInSmallView()) { |
85 | this.isMenuDisplayed = false | 83 | this.isMenuDisplayed = false |
@@ -187,10 +185,8 @@ export class AppComponent implements OnInit { | |||
187 | 185 | ||
188 | private injectJS () { | 186 | private injectJS () { |
189 | // Inject JS | 187 | // Inject JS |
190 | this.serverService.configLoaded | 188 | this.serverService.getConfig() |
191 | .subscribe(() => { | 189 | .subscribe(config => { |
192 | const config = this.serverService.getConfig() | ||
193 | |||
194 | if (config.instance.customizations.javascript) { | 190 | if (config.instance.customizations.javascript) { |
195 | try { | 191 | try { |
196 | // tslint:disable:no-eval | 192 | // tslint:disable:no-eval |
@@ -204,17 +200,14 @@ export class AppComponent implements OnInit { | |||
204 | 200 | ||
205 | private injectCSS () { | 201 | private injectCSS () { |
206 | // Inject CSS if modified (admin config settings) | 202 | // Inject CSS if modified (admin config settings) |
207 | this.serverService.configLoaded | 203 | this.serverService.configReloaded |
208 | .pipe(skip(1)) // We only want to subscribe to reloads, because the CSS is already injected by the server | ||
209 | .subscribe(() => { | 204 | .subscribe(() => { |
210 | const headStyle = document.querySelector('style.custom-css-style') | 205 | const headStyle = document.querySelector('style.custom-css-style') |
211 | if (headStyle) headStyle.parentNode.removeChild(headStyle) | 206 | if (headStyle) headStyle.parentNode.removeChild(headStyle) |
212 | 207 | ||
213 | const config = this.serverService.getConfig() | ||
214 | |||
215 | // We test customCSS if the admin removed the css | 208 | // We test customCSS if the admin removed the css |
216 | if (this.customCSS || config.instance.customizations.css) { | 209 | if (this.customCSS || this.serverConfig.instance.customizations.css) { |
217 | const styleTag = '<style>' + config.instance.customizations.css + '</style>' | 210 | const styleTag = '<style>' + this.serverConfig.instance.customizations.css + '</style>' |
218 | this.customCSS = this.domSanitizer.bypassSecurityTrustHtml(styleTag) | 211 | this.customCSS = this.domSanitizer.bypassSecurityTrustHtml(styleTag) |
219 | } | 212 | } |
220 | }) | 213 | }) |
@@ -227,25 +220,22 @@ export class AppComponent implements OnInit { | |||
227 | } | 220 | } |
228 | 221 | ||
229 | private async openModalsIfNeeded () { | 222 | private async openModalsIfNeeded () { |
230 | this.serverService.configLoaded | 223 | this.authService.userInformationLoaded |
231 | .pipe( | 224 | .pipe( |
232 | first(), | ||
233 | switchMap(() => this.authService.userInformationLoaded), | ||
234 | map(() => this.authService.getUser()), | 225 | map(() => this.authService.getUser()), |
235 | filter(user => user.role === UserRole.ADMINISTRATOR) | 226 | filter(user => user.role === UserRole.ADMINISTRATOR) |
236 | ).subscribe(user => setTimeout(() => this.openAdminModals(user))) // setTimeout because of ngIf in template | 227 | ).subscribe(user => setTimeout(() => this._openAdminModalsIfNeeded(user))) // setTimeout because of ngIf in template |
237 | } | 228 | } |
238 | 229 | ||
239 | private async openAdminModals (user: User) { | 230 | private async _openAdminModalsIfNeeded (user: User) { |
240 | if (user.noWelcomeModal !== true) return this.welcomeModal.show() | 231 | if (user.noWelcomeModal !== true) return this.welcomeModal.show() |
241 | 232 | ||
242 | const config = this.serverService.getConfig() | 233 | if (user.noInstanceConfigWarningModal === true || !this.serverConfig.signup.allowed) return |
243 | if (user.noInstanceConfigWarningModal === true || !config.signup.allowed) return | ||
244 | 234 | ||
245 | this.instanceService.getAbout() | 235 | this.instanceService.getAbout() |
246 | .subscribe(about => { | 236 | .subscribe(about => { |
247 | if ( | 237 | if ( |
248 | config.instance.name.toLowerCase() === 'peertube' || | 238 | this.serverConfig.instance.name.toLowerCase() === 'peertube' || |
249 | !about.instance.terms || | 239 | !about.instance.terms || |
250 | !about.instance.administrator || | 240 | !about.instance.administrator || |
251 | !about.instance.maintenanceLifetime | 241 | !about.instance.maintenanceLifetime |
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts index 38b7328e2..dda705811 100644 --- a/client/src/app/app.module.ts +++ b/client/src/app/app.module.ts | |||
@@ -25,10 +25,10 @@ export function metaFactory (serverService: ServerService): MetaLoader { | |||
25 | return new MetaStaticLoader({ | 25 | return new MetaStaticLoader({ |
26 | pageTitlePositioning: PageTitlePositioning.PrependPageTitle, | 26 | pageTitlePositioning: PageTitlePositioning.PrependPageTitle, |
27 | pageTitleSeparator: ' - ', | 27 | pageTitleSeparator: ' - ', |
28 | get applicationName () { return serverService.getConfig().instance.name }, | 28 | get applicationName () { return serverService.getTmpConfig().instance.name }, |
29 | defaults: { | 29 | defaults: { |
30 | get title () { return serverService.getConfig().instance.name }, | 30 | get title () { return serverService.getTmpConfig().instance.name }, |
31 | get description () { return serverService.getConfig().instance.shortDescription } | 31 | get description () { return serverService.getTmpConfig().instance.shortDescription } |
32 | } | 32 | } |
33 | }) | 33 | }) |
34 | } | 34 | } |
diff --git a/client/src/app/core/plugins/plugin.service.ts b/client/src/app/core/plugins/plugin.service.ts index e24468da5..da5114048 100644 --- a/client/src/app/core/plugins/plugin.service.ts +++ b/client/src/app/core/plugins/plugin.service.ts | |||
@@ -70,9 +70,9 @@ export class PluginService implements ClientHook { | |||
70 | } | 70 | } |
71 | 71 | ||
72 | initializePlugins () { | 72 | initializePlugins () { |
73 | this.server.configLoaded | 73 | this.server.getConfig() |
74 | .subscribe(() => { | 74 | .subscribe(config => { |
75 | this.plugins = this.server.getConfig().plugin.registered | 75 | this.plugins = config.plugin.registered |
76 | 76 | ||
77 | this.buildScopeStruct() | 77 | this.buildScopeStruct() |
78 | 78 | ||
diff --git a/client/src/app/core/routing/redirect.service.ts b/client/src/app/core/routing/redirect.service.ts index 43b89f08d..3982cf36f 100644 --- a/client/src/app/core/routing/redirect.service.ts +++ b/client/src/app/core/routing/redirect.service.ts | |||
@@ -16,15 +16,15 @@ export class RedirectService { | |||
16 | private serverService: ServerService | 16 | private serverService: ServerService |
17 | ) { | 17 | ) { |
18 | // The config is first loaded from the cache so try to get the default route | 18 | // The config is first loaded from the cache so try to get the default route |
19 | const config = this.serverService.getConfig() | 19 | const tmpConfig = this.serverService.getTmpConfig() |
20 | if (config && config.instance && config.instance.defaultClientRoute) { | 20 | if (tmpConfig && tmpConfig.instance && tmpConfig.instance.defaultClientRoute) { |
21 | RedirectService.DEFAULT_ROUTE = config.instance.defaultClientRoute | 21 | RedirectService.DEFAULT_ROUTE = tmpConfig.instance.defaultClientRoute |
22 | } | 22 | } |
23 | 23 | ||
24 | // Load default route | 24 | // Load default route |
25 | this.serverService.configLoaded | 25 | this.serverService.getConfig() |
26 | .subscribe(() => { | 26 | .subscribe(config => { |
27 | const defaultRouteConfig = this.serverService.getConfig().instance.defaultClientRoute | 27 | const defaultRouteConfig = config.instance.defaultClientRoute |
28 | 28 | ||
29 | if (defaultRouteConfig) { | 29 | if (defaultRouteConfig) { |
30 | RedirectService.DEFAULT_ROUTE = defaultRouteConfig | 30 | RedirectService.DEFAULT_ROUTE = defaultRouteConfig |
diff --git a/client/src/app/core/routing/server-config-resolver.service.ts b/client/src/app/core/routing/server-config-resolver.service.ts index ec7d6428f..3b7ed99bf 100644 --- a/client/src/app/core/routing/server-config-resolver.service.ts +++ b/client/src/app/core/routing/server-config-resolver.service.ts | |||
@@ -1,17 +1,13 @@ | |||
1 | import { Injectable } from '@angular/core' | 1 | import { Injectable } from '@angular/core' |
2 | import { Resolve } from '@angular/router' | 2 | import { Resolve } from '@angular/router' |
3 | import { ServerService } from '@app/core/server' | 3 | import { ServerService } from '@app/core/server' |
4 | import { ServerConfig } from '@shared/models' | ||
4 | 5 | ||
5 | @Injectable() | 6 | @Injectable() |
6 | export class ServerConfigResolver implements Resolve<boolean> { | 7 | export class ServerConfigResolver implements Resolve<ServerConfig> { |
7 | constructor ( | 8 | constructor (private server: ServerService) {} |
8 | private server: ServerService | ||
9 | ) {} | ||
10 | 9 | ||
11 | resolve () { | 10 | resolve () { |
12 | // FIXME: directly returning this.server.configLoaded does not seem to work | 11 | return this.server.getConfig() |
13 | return new Promise<boolean>(res => { | ||
14 | return this.server.configLoaded.subscribe(() => res(true)) | ||
15 | }) | ||
16 | } | 12 | } |
17 | } | 13 | } |
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index fdcc51cc5..ec904bf57 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts | |||
@@ -1,34 +1,36 @@ | |||
1 | import { map, shareReplay, switchMap, tap } from 'rxjs/operators' | 1 | import { first, map, share, shareReplay, switchMap, tap } from 'rxjs/operators' |
2 | import { HttpClient } from '@angular/common/http' | 2 | import { HttpClient } from '@angular/common/http' |
3 | import { Inject, Injectable, LOCALE_ID } from '@angular/core' | 3 | import { Inject, Injectable, LOCALE_ID } from '@angular/core' |
4 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage' | 4 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage' |
5 | import { Observable, of, ReplaySubject } from 'rxjs' | 5 | import { Observable, of, Subject } from 'rxjs' |
6 | import { getCompleteLocale, ServerConfig } from '../../../../../shared' | 6 | import { getCompleteLocale, ServerConfig } from '../../../../../shared' |
7 | import { environment } from '../../../environments/environment' | 7 | import { environment } from '../../../environments/environment' |
8 | import { VideoConstant, VideoPrivacy } from '../../../../../shared/models/videos' | 8 | import { VideoConstant } from '../../../../../shared/models/videos' |
9 | import { isDefaultLocale, peertubeTranslate } from '../../../../../shared/models/i18n' | 9 | import { isDefaultLocale, peertubeTranslate } from '../../../../../shared/models/i18n' |
10 | import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils' | 10 | import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils' |
11 | import { sortBy } from '@app/shared/misc/utils' | 11 | import { sortBy } from '@app/shared/misc/utils' |
12 | import { VideoPlaylistPrivacy } from '@shared/models/videos/playlist/video-playlist-privacy.model' | ||
13 | import { cloneDeep } from 'lodash-es' | ||
14 | 12 | ||
15 | @Injectable() | 13 | @Injectable() |
16 | export class ServerService { | 14 | export class ServerService { |
17 | private static BASE_SERVER_URL = environment.apiUrl + '/api/v1/server/' | ||
18 | private static BASE_CONFIG_URL = environment.apiUrl + '/api/v1/config/' | 15 | private static BASE_CONFIG_URL = environment.apiUrl + '/api/v1/config/' |
19 | private static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/' | 16 | private static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/' |
20 | private static BASE_VIDEO_PLAYLIST_URL = environment.apiUrl + '/api/v1/video-playlists/' | 17 | private static BASE_VIDEO_PLAYLIST_URL = environment.apiUrl + '/api/v1/video-playlists/' |
21 | private static BASE_LOCALE_URL = environment.apiUrl + '/client/locales/' | 18 | private static BASE_LOCALE_URL = environment.apiUrl + '/client/locales/' |
22 | private static CONFIG_LOCAL_STORAGE_KEY = 'server-config' | 19 | private static CONFIG_LOCAL_STORAGE_KEY = 'server-config' |
23 | 20 | ||
24 | configLoaded = new ReplaySubject<boolean>(1) | 21 | configReloaded = new Subject<void>() |
25 | videoPrivaciesLoaded = new ReplaySubject<boolean>(1) | ||
26 | videoPlaylistPrivaciesLoaded = new ReplaySubject<boolean>(1) | ||
27 | videoCategoriesLoaded = new ReplaySubject<boolean>(1) | ||
28 | videoLicencesLoaded = new ReplaySubject<boolean>(1) | ||
29 | videoLanguagesLoaded = new ReplaySubject<boolean>(1) | ||
30 | localeObservable: Observable<any> | ||
31 | 22 | ||
23 | private localeObservable: Observable<any> | ||
24 | private videoLicensesObservable: Observable<VideoConstant<number>[]> | ||
25 | private videoCategoriesObservable: Observable<VideoConstant<number>[]> | ||
26 | private videoPrivaciesObservable: Observable<VideoConstant<number>[]> | ||
27 | private videoPlaylistPrivaciesObservable: Observable<VideoConstant<number>[]> | ||
28 | private videoLanguagesObservable: Observable<VideoConstant<string>[]> | ||
29 | private configObservable: Observable<ServerConfig> | ||
30 | |||
31 | private configReset = false | ||
32 | |||
33 | private configLoaded = false | ||
32 | private config: ServerConfig = { | 34 | private config: ServerConfig = { |
33 | instance: { | 35 | instance: { |
34 | name: 'PeerTube', | 36 | name: 'PeerTube', |
@@ -121,132 +123,141 @@ export class ServerService { | |||
121 | enabled: true | 123 | enabled: true |
122 | } | 124 | } |
123 | } | 125 | } |
124 | private videoCategories: Array<VideoConstant<number>> = [] | ||
125 | private videoLicences: Array<VideoConstant<number>> = [] | ||
126 | private videoLanguages: Array<VideoConstant<string>> = [] | ||
127 | private videoPrivacies: Array<VideoConstant<VideoPrivacy>> = [] | ||
128 | private videoPlaylistPrivacies: Array<VideoConstant<VideoPlaylistPrivacy>> = [] | ||
129 | 126 | ||
130 | constructor ( | 127 | constructor ( |
131 | private http: HttpClient, | 128 | private http: HttpClient, |
132 | @Inject(LOCALE_ID) private localeId: string | 129 | @Inject(LOCALE_ID) private localeId: string |
133 | ) { | 130 | ) { |
134 | this.loadServerLocale() | ||
135 | this.loadConfigLocally() | 131 | this.loadConfigLocally() |
136 | } | 132 | } |
137 | 133 | ||
138 | loadConfig () { | 134 | getServerVersionAndCommit () { |
139 | this.http.get<ServerConfig>(ServerService.BASE_CONFIG_URL) | 135 | const serverVersion = this.config.serverVersion |
140 | .pipe(tap(this.saveConfigLocally)) | 136 | const commit = this.config.serverCommit || '' |
141 | .subscribe(data => { | ||
142 | this.config = data | ||
143 | 137 | ||
144 | this.configLoaded.next(true) | 138 | let result = serverVersion |
145 | }) | 139 | if (commit) result += '...' + commit |
146 | } | ||
147 | 140 | ||
148 | loadVideoCategories () { | 141 | return result |
149 | return this.loadAttributeEnum(ServerService.BASE_VIDEO_URL, 'categories', this.videoCategories, this.videoCategoriesLoaded, true) | ||
150 | } | 142 | } |
151 | 143 | ||
152 | loadVideoLicences () { | 144 | resetConfig () { |
153 | return this.loadAttributeEnum(ServerService.BASE_VIDEO_URL, 'licences', this.videoLicences, this.videoLicencesLoaded) | 145 | this.configLoaded = false |
146 | this.configReset = true | ||
154 | } | 147 | } |
155 | 148 | ||
156 | loadVideoLanguages () { | 149 | getConfig () { |
157 | return this.loadAttributeEnum(ServerService.BASE_VIDEO_URL, 'languages', this.videoLanguages, this.videoLanguagesLoaded, true) | 150 | if (this.configLoaded) return of(this.config) |
158 | } | ||
159 | 151 | ||
160 | loadVideoPrivacies () { | 152 | if (!this.configObservable) { |
161 | return this.loadAttributeEnum(ServerService.BASE_VIDEO_URL, 'privacies', this.videoPrivacies, this.videoPrivaciesLoaded) | 153 | this.configObservable = this.http.get<ServerConfig>(ServerService.BASE_CONFIG_URL) |
162 | } | 154 | .pipe( |
155 | tap(this.saveConfigLocally), | ||
156 | tap(() => this.configLoaded = true), | ||
157 | tap(() => { | ||
158 | if (this.configReset) { | ||
159 | this.configReloaded.next() | ||
160 | this.configReset = false | ||
161 | } | ||
162 | }), | ||
163 | share() | ||
164 | ) | ||
165 | } | ||
163 | 166 | ||
164 | loadVideoPlaylistPrivacies () { | 167 | return this.configObservable |
165 | return this.loadAttributeEnum( | ||
166 | ServerService.BASE_VIDEO_PLAYLIST_URL, | ||
167 | 'privacies', | ||
168 | this.videoPlaylistPrivacies, | ||
169 | this.videoPlaylistPrivaciesLoaded | ||
170 | ) | ||
171 | } | 168 | } |
172 | 169 | ||
173 | getConfig () { | 170 | getTmpConfig () { |
174 | return cloneDeep(this.config) | 171 | return this.config |
175 | } | ||
176 | |||
177 | getServerVersionAndCommit () { | ||
178 | const serverVersion = this.config.serverVersion | ||
179 | const commit = this.config.serverCommit || '' | ||
180 | |||
181 | let result = `v${serverVersion}` | ||
182 | if (commit) result += '...' + commit | ||
183 | |||
184 | return result | ||
185 | } | 172 | } |
186 | 173 | ||
187 | getVideoCategories () { | 174 | getVideoCategories () { |
188 | return cloneDeep(this.videoCategories) | 175 | if (!this.videoCategoriesObservable) { |
176 | this.videoCategoriesObservable = this.loadAttributeEnum<number>(ServerService.BASE_VIDEO_URL, 'categories', true) | ||
177 | } | ||
178 | |||
179 | return this.videoCategoriesObservable.pipe(first()) | ||
189 | } | 180 | } |
190 | 181 | ||
191 | getVideoLicences () { | 182 | getVideoLicences () { |
192 | return cloneDeep(this.videoLicences) | 183 | if (!this.videoLicensesObservable) { |
184 | this.videoLicensesObservable = this.loadAttributeEnum<number>(ServerService.BASE_VIDEO_URL, 'licences') | ||
185 | } | ||
186 | |||
187 | return this.videoLicensesObservable.pipe(first()) | ||
193 | } | 188 | } |
194 | 189 | ||
195 | getVideoLanguages () { | 190 | getVideoLanguages () { |
196 | return cloneDeep(this.videoLanguages) | 191 | if (!this.videoLanguagesObservable) { |
192 | this.videoLanguagesObservable = this.loadAttributeEnum<string>(ServerService.BASE_VIDEO_URL, 'languages', true) | ||
193 | } | ||
194 | |||
195 | return this.videoLanguagesObservable.pipe(first()) | ||
197 | } | 196 | } |
198 | 197 | ||
199 | getVideoPrivacies () { | 198 | getVideoPrivacies () { |
200 | return cloneDeep(this.videoPrivacies) | 199 | if (!this.videoPrivaciesObservable) { |
200 | this.videoPrivaciesObservable = this.loadAttributeEnum<number>(ServerService.BASE_VIDEO_URL, 'privacies') | ||
201 | } | ||
202 | |||
203 | return this.videoPrivaciesObservable.pipe(first()) | ||
201 | } | 204 | } |
202 | 205 | ||
203 | getVideoPlaylistPrivacies () { | 206 | getVideoPlaylistPrivacies () { |
204 | return cloneDeep(this.videoPlaylistPrivacies) | 207 | if (!this.videoPlaylistPrivaciesObservable) { |
208 | this.videoPlaylistPrivaciesObservable = this.loadAttributeEnum<number>(ServerService.BASE_VIDEO_PLAYLIST_URL, 'privacies') | ||
209 | } | ||
210 | |||
211 | return this.videoPlaylistPrivaciesObservable.pipe(first()) | ||
212 | } | ||
213 | |||
214 | getServerLocale () { | ||
215 | if (!this.localeObservable) { | ||
216 | const completeLocale = isOnDevLocale() ? getDevLocale() : getCompleteLocale(this.localeId) | ||
217 | |||
218 | // Default locale, nothing to translate | ||
219 | if (isDefaultLocale(completeLocale)) { | ||
220 | this.localeObservable = of({}).pipe(shareReplay()) | ||
221 | } else { | ||
222 | this.localeObservable = this.http | ||
223 | .get(ServerService.BASE_LOCALE_URL + completeLocale + '/server.json') | ||
224 | .pipe(shareReplay()) | ||
225 | } | ||
226 | } | ||
227 | |||
228 | return this.localeObservable.pipe(first()) | ||
205 | } | 229 | } |
206 | 230 | ||
207 | private loadAttributeEnum ( | 231 | private loadAttributeEnum <T extends string | number> ( |
208 | baseUrl: string, | 232 | baseUrl: string, |
209 | attributeName: 'categories' | 'licences' | 'languages' | 'privacies', | 233 | attributeName: 'categories' | 'licences' | 'languages' | 'privacies', |
210 | hashToPopulate: VideoConstant<string | number>[], | ||
211 | notifier: ReplaySubject<boolean>, | ||
212 | sort = false | 234 | sort = false |
213 | ) { | 235 | ) { |
214 | this.localeObservable | 236 | return this.getServerLocale() |
215 | .pipe( | 237 | .pipe( |
216 | switchMap(translations => { | 238 | switchMap(translations => { |
217 | return this.http.get<{ [id: string]: string }>(baseUrl + attributeName) | 239 | return this.http.get<{ [ id: string ]: string }>(baseUrl + attributeName) |
218 | .pipe(map(data => ({ data, translations }))) | 240 | .pipe(map(data => ({ data, translations }))) |
219 | }) | 241 | }), |
220 | ) | 242 | map(({ data, translations }) => { |
221 | .subscribe(({ data, translations }) => { | 243 | const hashToPopulate: VideoConstant<T>[] = [] |
222 | Object.keys(data) | ||
223 | .forEach(dataKey => { | ||
224 | const label = data[ dataKey ] | ||
225 | |||
226 | hashToPopulate.push({ | ||
227 | id: attributeName === 'languages' ? dataKey : parseInt(dataKey, 10), | ||
228 | label: peertubeTranslate(label, translations) | ||
229 | }) | ||
230 | }) | ||
231 | |||
232 | if (sort === true) sortBy(hashToPopulate, 'label') | ||
233 | |||
234 | notifier.next(true) | ||
235 | }) | ||
236 | } | ||
237 | 244 | ||
238 | private loadServerLocale () { | 245 | Object.keys(data) |
239 | const completeLocale = isOnDevLocale() ? getDevLocale() : getCompleteLocale(this.localeId) | 246 | .forEach(dataKey => { |
247 | const label = data[ dataKey ] | ||
240 | 248 | ||
241 | // Default locale, nothing to translate | 249 | hashToPopulate.push({ |
242 | if (isDefaultLocale(completeLocale)) { | 250 | id: (attributeName === 'languages' ? dataKey : parseInt(dataKey, 10)) as T, |
243 | this.localeObservable = of({}).pipe(shareReplay()) | 251 | label: peertubeTranslate(label, translations) |
244 | return | 252 | }) |
245 | } | 253 | }) |
254 | |||
255 | if (sort === true) sortBy(hashToPopulate, 'label') | ||
246 | 256 | ||
247 | this.localeObservable = this.http | 257 | return hashToPopulate |
248 | .get(ServerService.BASE_LOCALE_URL + completeLocale + '/server.json') | 258 | }), |
249 | .pipe(shareReplay()) | 259 | shareReplay() |
260 | ) | ||
250 | } | 261 | } |
251 | 262 | ||
252 | private saveConfigLocally (config: ServerConfig) { | 263 | private saveConfigLocally (config: ServerConfig) { |
diff --git a/client/src/app/core/theme/theme.service.ts b/client/src/app/core/theme/theme.service.ts index 3eebc1acc..2c5873cb3 100644 --- a/client/src/app/core/theme/theme.service.ts +++ b/client/src/app/core/theme/theme.service.ts | |||
@@ -3,7 +3,7 @@ import { AuthService } from '@app/core/auth' | |||
3 | import { ServerService } from '@app/core/server' | 3 | import { ServerService } from '@app/core/server' |
4 | import { environment } from '../../../environments/environment' | 4 | import { environment } from '../../../environments/environment' |
5 | import { PluginService } from '@app/core/plugins/plugin.service' | 5 | import { PluginService } from '@app/core/plugins/plugin.service' |
6 | import { ServerConfigTheme } from '@shared/models' | 6 | import { ServerConfig, ServerConfigTheme } from '@shared/models' |
7 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage' | 7 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage' |
8 | import { first } from 'rxjs/operators' | 8 | import { first } from 'rxjs/operators' |
9 | 9 | ||
@@ -20,6 +20,8 @@ export class ThemeService { | |||
20 | private themeFromLocalStorage: ServerConfigTheme | 20 | private themeFromLocalStorage: ServerConfigTheme |
21 | private themeDOMLinksFromLocalStorage: HTMLLinkElement[] = [] | 21 | private themeDOMLinksFromLocalStorage: HTMLLinkElement[] = [] |
22 | 22 | ||
23 | private serverConfig: ServerConfig | ||
24 | |||
23 | constructor ( | 25 | constructor ( |
24 | private auth: AuthService, | 26 | private auth: AuthService, |
25 | private pluginService: PluginService, | 27 | private pluginService: PluginService, |
@@ -30,9 +32,12 @@ export class ThemeService { | |||
30 | // Try to load from local storage first, so we don't have to wait network requests | 32 | // Try to load from local storage first, so we don't have to wait network requests |
31 | this.loadAndSetFromLocalStorage() | 33 | this.loadAndSetFromLocalStorage() |
32 | 34 | ||
33 | this.server.configLoaded | 35 | this.serverConfig = this.server.getTmpConfig() |
34 | .subscribe(() => { | 36 | this.server.getConfig() |
35 | const themes = this.server.getConfig().theme.registered | 37 | .subscribe(config => { |
38 | this.serverConfig = config | ||
39 | |||
40 | const themes = this.serverConfig.theme.registered | ||
36 | 41 | ||
37 | this.removeThemeFromLocalStorageIfNeeded(themes) | 42 | this.removeThemeFromLocalStorageIfNeeded(themes) |
38 | this.injectThemes(themes) | 43 | this.injectThemes(themes) |
@@ -77,7 +82,7 @@ export class ThemeService { | |||
77 | if (theme !== 'instance-default') return theme | 82 | if (theme !== 'instance-default') return theme |
78 | } | 83 | } |
79 | 84 | ||
80 | return this.server.getConfig().theme.default | 85 | return this.serverConfig.theme.default |
81 | } | 86 | } |
82 | 87 | ||
83 | private loadTheme (name: string) { | 88 | private loadTheme (name: string) { |
diff --git a/client/src/app/login/login-routing.module.ts b/client/src/app/login/login-routing.module.ts index 5a41f4e7e..22f59b4d9 100644 --- a/client/src/app/login/login-routing.module.ts +++ b/client/src/app/login/login-routing.module.ts | |||
@@ -15,7 +15,7 @@ const loginRoutes: Routes = [ | |||
15 | } | 15 | } |
16 | }, | 16 | }, |
17 | resolve: { | 17 | resolve: { |
18 | serverConfigLoaded: ServerConfigResolver | 18 | serverConfig: ServerConfigResolver |
19 | } | 19 | } |
20 | } | 20 | } |
21 | ] | 21 | ] |
diff --git a/client/src/app/login/login.component.ts b/client/src/app/login/login.component.ts index 911b9982f..cf923492a 100644 --- a/client/src/app/login/login.component.ts +++ b/client/src/app/login/login.component.ts | |||
@@ -7,7 +7,8 @@ import { I18n } from '@ngx-translate/i18n-polyfill' | |||
7 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' | 7 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' |
8 | import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-validators.service' | 8 | import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-validators.service' |
9 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' | 9 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' |
10 | import { Router } from '@angular/router' | 10 | import { ActivatedRoute, Router } from '@angular/router' |
11 | import { ServerConfig } from '@shared/models' | ||
11 | 12 | ||
12 | @Component({ | 13 | @Component({ |
13 | selector: 'my-login', | 14 | selector: 'my-login', |
@@ -23,10 +24,12 @@ export class LoginComponent extends FormReactive implements OnInit { | |||
23 | forgotPasswordEmail = '' | 24 | forgotPasswordEmail = '' |
24 | 25 | ||
25 | private openedForgotPasswordModal: NgbModalRef | 26 | private openedForgotPasswordModal: NgbModalRef |
27 | private serverConfig: ServerConfig | ||
26 | 28 | ||
27 | constructor ( | 29 | constructor ( |
28 | public router: Router, | ||
29 | protected formValidatorService: FormValidatorService, | 30 | protected formValidatorService: FormValidatorService, |
31 | private router: Router, | ||
32 | private route: ActivatedRoute, | ||
30 | private modalService: NgbModal, | 33 | private modalService: NgbModal, |
31 | private loginValidatorsService: LoginValidatorsService, | 34 | private loginValidatorsService: LoginValidatorsService, |
32 | private authService: AuthService, | 35 | private authService: AuthService, |
@@ -40,14 +43,16 @@ export class LoginComponent extends FormReactive implements OnInit { | |||
40 | } | 43 | } |
41 | 44 | ||
42 | get signupAllowed () { | 45 | get signupAllowed () { |
43 | return this.serverService.getConfig().signup.allowed === true | 46 | return this.serverConfig.signup.allowed === true |
44 | } | 47 | } |
45 | 48 | ||
46 | isEmailDisabled () { | 49 | isEmailDisabled () { |
47 | return this.serverService.getConfig().email.enabled === false | 50 | return this.serverConfig.email.enabled === false |
48 | } | 51 | } |
49 | 52 | ||
50 | ngOnInit () { | 53 | ngOnInit () { |
54 | this.serverConfig = this.route.snapshot.data.serverConfig | ||
55 | |||
51 | this.buildForm({ | 56 | this.buildForm({ |
52 | username: this.loginValidatorsService.LOGIN_USERNAME, | 57 | username: this.loginValidatorsService.LOGIN_USERNAME, |
53 | password: this.loginValidatorsService.LOGIN_PASSWORD | 58 | password: this.loginValidatorsService.LOGIN_PASSWORD |
diff --git a/client/src/app/menu/menu.component.ts b/client/src/app/menu/menu.component.ts index c7c31577a..2d522b521 100644 --- a/client/src/app/menu/menu.component.ts +++ b/client/src/app/menu/menu.component.ts | |||
@@ -4,6 +4,7 @@ import { AuthService, AuthStatus, RedirectService, ServerService, ThemeService } | |||
4 | import { User } from '../shared/users/user.model' | 4 | import { User } from '../shared/users/user.model' |
5 | import { LanguageChooserComponent } from '@app/menu/language-chooser.component' | 5 | import { LanguageChooserComponent } from '@app/menu/language-chooser.component' |
6 | import { HotkeysService } from 'angular2-hotkeys' | 6 | import { HotkeysService } from 'angular2-hotkeys' |
7 | import { ServerConfig } from '@shared/models' | ||
7 | 8 | ||
8 | @Component({ | 9 | @Component({ |
9 | selector: 'my-menu', | 10 | selector: 'my-menu', |
@@ -18,6 +19,7 @@ export class MenuComponent implements OnInit { | |||
18 | userHasAdminAccess = false | 19 | userHasAdminAccess = false |
19 | helpVisible = false | 20 | helpVisible = false |
20 | 21 | ||
22 | private serverConfig: ServerConfig | ||
21 | private routesPerRight: { [ role in UserRight ]?: string } = { | 23 | private routesPerRight: { [ role in UserRight ]?: string } = { |
22 | [UserRight.MANAGE_USERS]: '/admin/users', | 24 | [UserRight.MANAGE_USERS]: '/admin/users', |
23 | [UserRight.MANAGE_SERVER_FOLLOW]: '/admin/friends', | 25 | [UserRight.MANAGE_SERVER_FOLLOW]: '/admin/friends', |
@@ -36,6 +38,10 @@ export class MenuComponent implements OnInit { | |||
36 | ) {} | 38 | ) {} |
37 | 39 | ||
38 | ngOnInit () { | 40 | ngOnInit () { |
41 | this.serverConfig = this.serverService.getTmpConfig() | ||
42 | this.serverService.getConfig() | ||
43 | .subscribe(config => this.serverConfig = config) | ||
44 | |||
39 | this.isLoggedIn = this.authService.isLoggedIn() | 45 | this.isLoggedIn = this.authService.isLoggedIn() |
40 | if (this.isLoggedIn === true) this.user = this.authService.getUser() | 46 | if (this.isLoggedIn === true) this.user = this.authService.getUser() |
41 | this.computeIsUserHasAdminAccess() | 47 | this.computeIsUserHasAdminAccess() |
@@ -64,8 +70,8 @@ export class MenuComponent implements OnInit { | |||
64 | } | 70 | } |
65 | 71 | ||
66 | isRegistrationAllowed () { | 72 | isRegistrationAllowed () { |
67 | return this.serverService.getConfig().signup.allowed && | 73 | return this.serverConfig.signup.allowed && |
68 | this.serverService.getConfig().signup.allowedForCurrentIP | 74 | this.serverConfig.signup.allowedForCurrentIP |
69 | } | 75 | } |
70 | 76 | ||
71 | getFirstAdminRightAvailable () { | 77 | getFirstAdminRightAvailable () { |
diff --git a/client/src/app/search/search-filters.component.ts b/client/src/app/search/search-filters.component.ts index 57131fcac..344a260df 100644 --- a/client/src/app/search/search-filters.component.ts +++ b/client/src/app/search/search-filters.component.ts | |||
@@ -1,10 +1,10 @@ | |||
1 | import { Component, EventEmitter, Input, OnInit, Output, SimpleChanges } from '@angular/core' | 1 | import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' |
2 | import { ValidatorFn } from '@angular/forms' | 2 | import { ValidatorFn } from '@angular/forms' |
3 | import { VideoValidatorsService } from '@app/shared' | 3 | import { VideoValidatorsService } from '@app/shared' |
4 | import { ServerService } from '@app/core' | 4 | import { ServerService } from '@app/core' |
5 | import { I18n } from '@ngx-translate/i18n-polyfill' | 5 | import { I18n } from '@ngx-translate/i18n-polyfill' |
6 | import { AdvancedSearch } from '@app/search/advanced-search.model' | 6 | import { AdvancedSearch } from '@app/search/advanced-search.model' |
7 | import { VideoConstant } from '../../../../shared' | 7 | import { ServerConfig, VideoConstant } from '../../../../shared' |
8 | 8 | ||
9 | @Component({ | 9 | @Component({ |
10 | selector: 'my-search-filters', | 10 | selector: 'my-search-filters', |
@@ -33,6 +33,8 @@ export class SearchFiltersComponent implements OnInit { | |||
33 | originallyPublishedStartYear: string | 33 | originallyPublishedStartYear: string |
34 | originallyPublishedEndYear: string | 34 | originallyPublishedEndYear: string |
35 | 35 | ||
36 | private serverConfig: ServerConfig | ||
37 | |||
36 | constructor ( | 38 | constructor ( |
37 | private i18n: I18n, | 39 | private i18n: I18n, |
38 | private videoValidatorsService: VideoValidatorsService, | 40 | private videoValidatorsService: VideoValidatorsService, |
@@ -99,9 +101,13 @@ export class SearchFiltersComponent implements OnInit { | |||
99 | } | 101 | } |
100 | 102 | ||
101 | ngOnInit () { | 103 | ngOnInit () { |
102 | this.serverService.videoCategoriesLoaded.subscribe(() => this.videoCategories = this.serverService.getVideoCategories()) | 104 | this.serverConfig = this.serverService.getTmpConfig() |
103 | this.serverService.videoLicencesLoaded.subscribe(() => this.videoLicences = this.serverService.getVideoLicences()) | 105 | this.serverService.getConfig() |
104 | this.serverService.videoLanguagesLoaded.subscribe(() => this.videoLanguages = this.serverService.getVideoLanguages()) | 106 | .subscribe(config => this.serverConfig = config) |
107 | |||
108 | this.serverService.getVideoCategories().subscribe(categories => this.videoCategories = categories) | ||
109 | this.serverService.getVideoLicences().subscribe(licences => this.videoLicences = licences) | ||
110 | this.serverService.getVideoLanguages().subscribe(languages => this.videoLanguages = languages) | ||
105 | 111 | ||
106 | this.loadFromDurationRange() | 112 | this.loadFromDurationRange() |
107 | this.loadFromPublishedRange() | 113 | this.loadFromPublishedRange() |
diff --git a/client/src/app/shared/images/preview-upload.component.ts b/client/src/app/shared/images/preview-upload.component.ts index 44b78866e..f56f5b1f8 100644 --- a/client/src/app/shared/images/preview-upload.component.ts +++ b/client/src/app/shared/images/preview-upload.component.ts | |||
@@ -2,6 +2,7 @@ import { Component, forwardRef, Input, OnInit } from '@angular/core' | |||
2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' | 2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' |
3 | import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser' | 3 | import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser' |
4 | import { ServerService } from '@app/core' | 4 | import { ServerService } from '@app/core' |
5 | import { ServerConfig } from '@shared/models' | ||
5 | 6 | ||
6 | @Component({ | 7 | @Component({ |
7 | selector: 'my-preview-upload', | 8 | selector: 'my-preview-upload', |
@@ -24,6 +25,7 @@ export class PreviewUploadComponent implements OnInit, ControlValueAccessor { | |||
24 | imageSrc: SafeResourceUrl | 25 | imageSrc: SafeResourceUrl |
25 | allowedExtensionsMessage = '' | 26 | allowedExtensionsMessage = '' |
26 | 27 | ||
28 | private serverConfig: ServerConfig | ||
27 | private file: File | 29 | private file: File |
28 | 30 | ||
29 | constructor ( | 31 | constructor ( |
@@ -32,14 +34,18 @@ export class PreviewUploadComponent implements OnInit, ControlValueAccessor { | |||
32 | ) {} | 34 | ) {} |
33 | 35 | ||
34 | get videoImageExtensions () { | 36 | get videoImageExtensions () { |
35 | return this.serverService.getConfig().video.image.extensions | 37 | return this.serverConfig.video.image.extensions |
36 | } | 38 | } |
37 | 39 | ||
38 | get maxVideoImageSize () { | 40 | get maxVideoImageSize () { |
39 | return this.serverService.getConfig().video.image.size.max | 41 | return this.serverConfig.video.image.size.max |
40 | } | 42 | } |
41 | 43 | ||
42 | ngOnInit () { | 44 | ngOnInit () { |
45 | this.serverConfig = this.serverService.getTmpConfig() | ||
46 | this.serverService.getConfig() | ||
47 | .subscribe(config => this.serverConfig = config) | ||
48 | |||
43 | this.allowedExtensionsMessage = this.videoImageExtensions.join(', ') | 49 | this.allowedExtensionsMessage = this.videoImageExtensions.join(', ') |
44 | } | 50 | } |
45 | 51 | ||
diff --git a/client/src/app/shared/instance/instance-features-table.component.html b/client/src/app/shared/instance/instance-features-table.component.html index f880a886f..fd8b3354f 100644 --- a/client/src/app/shared/instance/instance-features-table.component.html +++ b/client/src/app/shared/instance/instance-features-table.component.html | |||
@@ -1,6 +1,6 @@ | |||
1 | <div class="feature-table"> | 1 | <div class="feature-table"> |
2 | 2 | ||
3 | <table class="table" *ngIf="config"> | 3 | <table class="table" *ngIf="serverConfig"> |
4 | <tr> | 4 | <tr> |
5 | <td i18n class="label">PeerTube version</td> | 5 | <td i18n class="label">PeerTube version</td> |
6 | 6 | ||
@@ -19,7 +19,7 @@ | |||
19 | <tr> | 19 | <tr> |
20 | <td i18n class="label">User registration allowed</td> | 20 | <td i18n class="label">User registration allowed</td> |
21 | <td> | 21 | <td> |
22 | <my-feature-boolean [value]="config.signup.allowed"></my-feature-boolean> | 22 | <my-feature-boolean [value]="serverConfig.signup.allowed"></my-feature-boolean> |
23 | </td> | 23 | </td> |
24 | </tr> | 24 | </tr> |
25 | 25 | ||
@@ -30,15 +30,15 @@ | |||
30 | <tr> | 30 | <tr> |
31 | <td i18n class="sub-label">Transcoding in multiple resolutions</td> | 31 | <td i18n class="sub-label">Transcoding in multiple resolutions</td> |
32 | <td> | 32 | <td> |
33 | <my-feature-boolean [value]="config.transcoding.enabledResolutions.length !== 0"></my-feature-boolean> | 33 | <my-feature-boolean [value]="serverConfig.transcoding.enabledResolutions.length !== 0"></my-feature-boolean> |
34 | </td> | 34 | </td> |
35 | </tr> | 35 | </tr> |
36 | 36 | ||
37 | <tr> | 37 | <tr> |
38 | <td i18n class="sub-label">Video uploads</td> | 38 | <td i18n class="sub-label">Video uploads</td> |
39 | <td> | 39 | <td> |
40 | <span *ngIf="config.autoBlacklist.videos.ofUsers.enabled">Requires manual validation by moderators</span> | 40 | <span *ngIf="serverConfig.autoBlacklist.videos.ofUsers.enabled">Requires manual validation by moderators</span> |
41 | <span *ngIf="!config.autoBlacklist.videos.ofUsers.enabled">Automatically published</span> | 41 | <span *ngIf="!serverConfig.autoBlacklist.videos.ofUsers.enabled">Automatically published</span> |
42 | </td> | 42 | </td> |
43 | </tr> | 43 | </tr> |
44 | 44 | ||
@@ -69,14 +69,14 @@ | |||
69 | <tr> | 69 | <tr> |
70 | <td i18n class="sub-label">HTTP import (YouTube, Vimeo, direct URL...)</td> | 70 | <td i18n class="sub-label">HTTP import (YouTube, Vimeo, direct URL...)</td> |
71 | <td> | 71 | <td> |
72 | <my-feature-boolean [value]="config.import.videos.http.enabled"></my-feature-boolean> | 72 | <my-feature-boolean [value]="serverConfig.import.videos.http.enabled"></my-feature-boolean> |
73 | </td> | 73 | </td> |
74 | </tr> | 74 | </tr> |
75 | 75 | ||
76 | <tr> | 76 | <tr> |
77 | <td i18n class="sub-label">Torrent import</td> | 77 | <td i18n class="sub-label">Torrent import</td> |
78 | <td> | 78 | <td> |
79 | <my-feature-boolean [value]="config.import.videos.torrent.enabled"></my-feature-boolean> | 79 | <my-feature-boolean [value]="serverConfig.import.videos.torrent.enabled"></my-feature-boolean> |
80 | </td> | 80 | </td> |
81 | </tr> | 81 | </tr> |
82 | 82 | ||
@@ -88,7 +88,7 @@ | |||
88 | <tr> | 88 | <tr> |
89 | <td i18n class="sub-label">P2P enabled</td> | 89 | <td i18n class="sub-label">P2P enabled</td> |
90 | <td> | 90 | <td> |
91 | <my-feature-boolean [value]="config.tracker.enabled"></my-feature-boolean> | 91 | <my-feature-boolean [value]="serverConfig.tracker.enabled"></my-feature-boolean> |
92 | </td> | 92 | </td> |
93 | </tr> | 93 | </tr> |
94 | </table> | 94 | </table> |
diff --git a/client/src/app/shared/instance/instance-features-table.component.ts b/client/src/app/shared/instance/instance-features-table.component.ts index 1661f1efe..8fd15ebad 100644 --- a/client/src/app/shared/instance/instance-features-table.component.ts +++ b/client/src/app/shared/instance/instance-features-table.component.ts | |||
@@ -10,7 +10,7 @@ import { ServerConfig } from '@shared/models' | |||
10 | }) | 10 | }) |
11 | export class InstanceFeaturesTableComponent implements OnInit { | 11 | export class InstanceFeaturesTableComponent implements OnInit { |
12 | quotaHelpIndication = '' | 12 | quotaHelpIndication = '' |
13 | config: ServerConfig | 13 | serverConfig: ServerConfig |
14 | 14 | ||
15 | constructor ( | 15 | constructor ( |
16 | private i18n: I18n, | 16 | private i18n: I18n, |
@@ -19,29 +19,34 @@ export class InstanceFeaturesTableComponent implements OnInit { | |||
19 | } | 19 | } |
20 | 20 | ||
21 | get initialUserVideoQuota () { | 21 | get initialUserVideoQuota () { |
22 | return this.serverService.getConfig().user.videoQuota | 22 | return this.serverConfig.user.videoQuota |
23 | } | 23 | } |
24 | 24 | ||
25 | get dailyUserVideoQuota () { | 25 | get dailyUserVideoQuota () { |
26 | return Math.min(this.initialUserVideoQuota, this.serverService.getConfig().user.videoQuotaDaily) | 26 | return Math.min(this.initialUserVideoQuota, this.serverConfig.user.videoQuotaDaily) |
27 | } | 27 | } |
28 | 28 | ||
29 | ngOnInit () { | 29 | ngOnInit () { |
30 | this.serverService.configLoaded | 30 | this.serverConfig = this.serverService.getTmpConfig() |
31 | .subscribe(() => { | 31 | this.serverService.getConfig() |
32 | this.config = this.serverService.getConfig() | 32 | .subscribe(config => { |
33 | this.serverConfig = config | ||
33 | this.buildQuotaHelpIndication() | 34 | this.buildQuotaHelpIndication() |
34 | }) | 35 | }) |
35 | } | 36 | } |
36 | 37 | ||
37 | buildNSFWLabel () { | 38 | buildNSFWLabel () { |
38 | const policy = this.serverService.getConfig().instance.defaultNSFWPolicy | 39 | const policy = this.serverConfig.instance.defaultNSFWPolicy |
39 | 40 | ||
40 | if (policy === 'do_not_list') return this.i18n('Hidden') | 41 | if (policy === 'do_not_list') return this.i18n('Hidden') |
41 | if (policy === 'blur') return this.i18n('Blurred with confirmation request') | 42 | if (policy === 'blur') return this.i18n('Blurred with confirmation request') |
42 | if (policy === 'display') return this.i18n('Displayed') | 43 | if (policy === 'display') return this.i18n('Displayed') |
43 | } | 44 | } |
44 | 45 | ||
46 | getServerVersionAndCommit () { | ||
47 | return this.serverService.getServerVersionAndCommit() | ||
48 | } | ||
49 | |||
45 | private getApproximateTime (seconds: number) { | 50 | private getApproximateTime (seconds: number) { |
46 | const hours = Math.floor(seconds / 3600) | 51 | const hours = Math.floor(seconds / 3600) |
47 | let pluralSuffix = '' | 52 | let pluralSuffix = '' |
@@ -53,10 +58,6 @@ export class InstanceFeaturesTableComponent implements OnInit { | |||
53 | return this.i18n('~ {{minutes}} {minutes, plural, =1 {minute} other {minutes}}', { minutes }) | 58 | return this.i18n('~ {{minutes}} {minutes, plural, =1 {minute} other {minutes}}', { minutes }) |
54 | } | 59 | } |
55 | 60 | ||
56 | getServerVersionAndCommit () { | ||
57 | return this.serverService.getServerVersionAndCommit() | ||
58 | } | ||
59 | |||
60 | private buildQuotaHelpIndication () { | 61 | private buildQuotaHelpIndication () { |
61 | if (this.initialUserVideoQuota === -1) return | 62 | if (this.initialUserVideoQuota === -1) return |
62 | 63 | ||
diff --git a/client/src/app/shared/instance/instance.service.ts b/client/src/app/shared/instance/instance.service.ts index 44b413fa4..8b26063fb 100644 --- a/client/src/app/shared/instance/instance.service.ts +++ b/client/src/app/shared/instance/instance.service.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { catchError } from 'rxjs/operators' | 1 | import { catchError, map } from 'rxjs/operators' |
2 | import { HttpClient } from '@angular/common/http' | 2 | import { HttpClient } from '@angular/common/http' |
3 | import { Injectable } from '@angular/core' | 3 | import { Injectable } from '@angular/core' |
4 | import { environment } from '../../../environments/environment' | 4 | import { environment } from '../../../environments/environment' |
@@ -7,6 +7,7 @@ import { About } from '../../../../../shared/models/server' | |||
7 | import { MarkdownService } from '@app/shared/renderer' | 7 | import { MarkdownService } from '@app/shared/renderer' |
8 | import { peertubeTranslate } from '@shared/models' | 8 | import { peertubeTranslate } from '@shared/models' |
9 | import { ServerService } from '@app/core' | 9 | import { ServerService } from '@app/core' |
10 | import { forkJoin } from 'rxjs' | ||
10 | 11 | ||
11 | @Injectable() | 12 | @Injectable() |
12 | export class InstanceService { | 13 | export class InstanceService { |
@@ -57,25 +58,35 @@ export class InstanceService { | |||
57 | return html | 58 | return html |
58 | } | 59 | } |
59 | 60 | ||
60 | buildTranslatedLanguages (about: About, translations: any) { | 61 | buildTranslatedLanguages (about: About) { |
61 | const languagesArray = this.serverService.getVideoLanguages() | 62 | return forkJoin([ |
63 | this.serverService.getVideoLanguages(), | ||
64 | this.serverService.getServerLocale() | ||
65 | ]).pipe( | ||
66 | map(([ languagesArray, translations ]) => { | ||
67 | return about.instance.languages | ||
68 | .map(l => { | ||
69 | const languageObj = languagesArray.find(la => la.id === l) | ||
62 | 70 | ||
63 | return about.instance.languages | 71 | return peertubeTranslate(languageObj.label, translations) |
64 | .map(l => { | 72 | }) |
65 | const languageObj = languagesArray.find(la => la.id === l) | 73 | }) |
66 | 74 | ) | |
67 | return peertubeTranslate(languageObj.label, translations) | ||
68 | }) | ||
69 | } | 75 | } |
70 | 76 | ||
71 | buildTranslatedCategories (about: About, translations: any) { | 77 | buildTranslatedCategories (about: About) { |
72 | const categoriesArray = this.serverService.getVideoCategories() | 78 | return forkJoin([ |
73 | 79 | this.serverService.getVideoCategories(), | |
74 | return about.instance.categories | 80 | this.serverService.getServerLocale() |
75 | .map(c => { | 81 | ]).pipe( |
76 | const categoryObj = categoriesArray.find(ca => ca.id === c) | 82 | map(([ categoriesArray, translations ]) => { |
83 | return about.instance.categories | ||
84 | .map(c => { | ||
85 | const categoryObj = categoriesArray.find(ca => ca.id === c) | ||
77 | 86 | ||
78 | return peertubeTranslate(categoryObj.label, translations) | 87 | return peertubeTranslate(categoryObj.label, translations) |
79 | }) | 88 | }) |
89 | }) | ||
90 | ) | ||
80 | } | 91 | } |
81 | } | 92 | } |
diff --git a/client/src/app/shared/moderation/user-moderation-dropdown.component.ts b/client/src/app/shared/moderation/user-moderation-dropdown.component.ts index e9d4c1437..d82dc3d94 100644 --- a/client/src/app/shared/moderation/user-moderation-dropdown.component.ts +++ b/client/src/app/shared/moderation/user-moderation-dropdown.component.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core' | 1 | import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild } from '@angular/core' |
2 | import { I18n } from '@ngx-translate/i18n-polyfill' | 2 | import { I18n } from '@ngx-translate/i18n-polyfill' |
3 | import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' | 3 | import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' |
4 | import { UserBanModalComponent } from '@app/shared/moderation/user-ban-modal.component' | 4 | import { UserBanModalComponent } from '@app/shared/moderation/user-ban-modal.component' |
@@ -7,12 +7,13 @@ import { AuthService, ConfirmService, Notifier, ServerService } from '@app/core' | |||
7 | import { User, UserRight } from '../../../../../shared/models/users' | 7 | import { User, UserRight } from '../../../../../shared/models/users' |
8 | import { Account } from '@app/shared/account/account.model' | 8 | import { Account } from '@app/shared/account/account.model' |
9 | import { BlocklistService } from '@app/shared/blocklist' | 9 | import { BlocklistService } from '@app/shared/blocklist' |
10 | import { ServerConfig } from '@shared/models' | ||
10 | 11 | ||
11 | @Component({ | 12 | @Component({ |
12 | selector: 'my-user-moderation-dropdown', | 13 | selector: 'my-user-moderation-dropdown', |
13 | templateUrl: './user-moderation-dropdown.component.html' | 14 | templateUrl: './user-moderation-dropdown.component.html' |
14 | }) | 15 | }) |
15 | export class UserModerationDropdownComponent implements OnChanges { | 16 | export class UserModerationDropdownComponent implements OnInit, OnChanges { |
16 | @ViewChild('userBanModal', { static: false }) userBanModal: UserBanModalComponent | 17 | @ViewChild('userBanModal', { static: false }) userBanModal: UserBanModalComponent |
17 | 18 | ||
18 | @Input() user: User | 19 | @Input() user: User |
@@ -26,6 +27,8 @@ export class UserModerationDropdownComponent implements OnChanges { | |||
26 | 27 | ||
27 | userActions: DropdownAction<{ user: User, account: Account }>[][] = [] | 28 | userActions: DropdownAction<{ user: User, account: Account }>[][] = [] |
28 | 29 | ||
30 | private serverConfig: ServerConfig | ||
31 | |||
29 | constructor ( | 32 | constructor ( |
30 | private authService: AuthService, | 33 | private authService: AuthService, |
31 | private notifier: Notifier, | 34 | private notifier: Notifier, |
@@ -38,7 +41,13 @@ export class UserModerationDropdownComponent implements OnChanges { | |||
38 | ) { } | 41 | ) { } |
39 | 42 | ||
40 | get requiresEmailVerification () { | 43 | get requiresEmailVerification () { |
41 | return this.serverService.getConfig().signup.requiresEmailVerification | 44 | return this.serverConfig.signup.requiresEmailVerification |
45 | } | ||
46 | |||
47 | ngOnInit (): void { | ||
48 | this.serverConfig = this.serverService.getTmpConfig() | ||
49 | this.serverService.getConfig() | ||
50 | .subscribe(config => this.serverConfig = config) | ||
42 | } | 51 | } |
43 | 52 | ||
44 | ngOnChanges () { | 53 | ngOnChanges () { |
diff --git a/client/src/app/shared/overview/overview.service.ts b/client/src/app/shared/overview/overview.service.ts index bd4068925..79cb781f7 100644 --- a/client/src/app/shared/overview/overview.service.ts +++ b/client/src/app/shared/overview/overview.service.ts | |||
@@ -60,7 +60,7 @@ export class OverviewService { | |||
60 | .pipe( | 60 | .pipe( |
61 | // Translate categories | 61 | // Translate categories |
62 | switchMap(() => { | 62 | switchMap(() => { |
63 | return this.serverService.localeObservable | 63 | return this.serverService.getServerLocale() |
64 | .pipe( | 64 | .pipe( |
65 | tap(translations => { | 65 | tap(translations => { |
66 | for (const c of videosOverviewResult.categories) { | 66 | for (const c of videosOverviewResult.categories) { |
diff --git a/client/src/app/shared/video-caption/video-caption.service.ts b/client/src/app/shared/video-caption/video-caption.service.ts index 977f6253a..6bfe67435 100644 --- a/client/src/app/shared/video-caption/video-caption.service.ts +++ b/client/src/app/shared/video-caption/video-caption.service.ts | |||
@@ -22,7 +22,7 @@ export class VideoCaptionService { | |||
22 | return this.authHttp.get<ResultList<VideoCaption>>(VideoService.BASE_VIDEO_URL + videoId + '/captions') | 22 | return this.authHttp.get<ResultList<VideoCaption>>(VideoService.BASE_VIDEO_URL + videoId + '/captions') |
23 | .pipe( | 23 | .pipe( |
24 | switchMap(captionsResult => { | 24 | switchMap(captionsResult => { |
25 | return this.serverService.localeObservable | 25 | return this.serverService.getServerLocale() |
26 | .pipe(map(translations => ({ captionsResult, translations }))) | 26 | .pipe(map(translations => ({ captionsResult, translations }))) |
27 | }), | 27 | }), |
28 | map(({ captionsResult, translations }) => { | 28 | map(({ captionsResult, translations }) => { |
diff --git a/client/src/app/shared/video-import/video-import.service.ts b/client/src/app/shared/video-import/video-import.service.ts index 7ae13154d..3e3fb7dfb 100644 --- a/client/src/app/shared/video-import/video-import.service.ts +++ b/client/src/app/shared/video-import/video-import.service.ts | |||
@@ -91,7 +91,7 @@ export class VideoImportService { | |||
91 | } | 91 | } |
92 | 92 | ||
93 | private extractVideoImports (result: ResultList<VideoImport>): Observable<ResultList<VideoImport>> { | 93 | private extractVideoImports (result: ResultList<VideoImport>): Observable<ResultList<VideoImport>> { |
94 | return this.serverService.localeObservable | 94 | return this.serverService.getServerLocale() |
95 | .pipe( | 95 | .pipe( |
96 | map(translations => { | 96 | map(translations => { |
97 | result.data.forEach(d => | 97 | result.data.forEach(d => |
diff --git a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.ts b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.ts index a8e5a4885..cd592eab0 100644 --- a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.ts +++ b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewChild } from '@angular/core' | 1 | import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' |
2 | import { Video } from '@app/shared/video/video.model' | 2 | import { Video } from '@app/shared/video/video.model' |
3 | import { VideoPlaylistElementType, VideoPlaylistElementUpdate } from '@shared/models' | 3 | import { ServerConfig, VideoPlaylistElementType, VideoPlaylistElementUpdate } from '@shared/models' |
4 | import { AuthService, ConfirmService, Notifier, ServerService } from '@app/core' | 4 | import { AuthService, ConfirmService, Notifier, ServerService } from '@app/core' |
5 | import { ActivatedRoute } from '@angular/router' | 5 | import { ActivatedRoute } from '@angular/router' |
6 | import { I18n } from '@ngx-translate/i18n-polyfill' | 6 | import { I18n } from '@ngx-translate/i18n-polyfill' |
@@ -17,7 +17,7 @@ import { VideoPlaylistElement } from '@app/shared/video-playlist/video-playlist- | |||
17 | templateUrl: './video-playlist-element-miniature.component.html', | 17 | templateUrl: './video-playlist-element-miniature.component.html', |
18 | changeDetection: ChangeDetectionStrategy.OnPush | 18 | changeDetection: ChangeDetectionStrategy.OnPush |
19 | }) | 19 | }) |
20 | export class VideoPlaylistElementMiniatureComponent { | 20 | export class VideoPlaylistElementMiniatureComponent implements OnInit { |
21 | @ViewChild('moreDropdown', { static: false }) moreDropdown: NgbDropdown | 21 | @ViewChild('moreDropdown', { static: false }) moreDropdown: NgbDropdown |
22 | 22 | ||
23 | @Input() playlist: VideoPlaylist | 23 | @Input() playlist: VideoPlaylist |
@@ -39,6 +39,8 @@ export class VideoPlaylistElementMiniatureComponent { | |||
39 | stopTimestamp: number | 39 | stopTimestamp: number |
40 | } = {} as any | 40 | } = {} as any |
41 | 41 | ||
42 | private serverConfig: ServerConfig | ||
43 | |||
42 | constructor ( | 44 | constructor ( |
43 | private authService: AuthService, | 45 | private authService: AuthService, |
44 | private serverService: ServerService, | 46 | private serverService: ServerService, |
@@ -51,6 +53,15 @@ export class VideoPlaylistElementMiniatureComponent { | |||
51 | private cdr: ChangeDetectorRef | 53 | private cdr: ChangeDetectorRef |
52 | ) {} | 54 | ) {} |
53 | 55 | ||
56 | ngOnInit (): void { | ||
57 | this.serverConfig = this.serverService.getTmpConfig() | ||
58 | this.serverService.getConfig() | ||
59 | .subscribe(config => { | ||
60 | this.serverConfig = config | ||
61 | this.cdr.detectChanges() | ||
62 | }) | ||
63 | } | ||
64 | |||
54 | isUnavailable (e: VideoPlaylistElement) { | 65 | isUnavailable (e: VideoPlaylistElement) { |
55 | return e.type === VideoPlaylistElementType.UNAVAILABLE | 66 | return e.type === VideoPlaylistElementType.UNAVAILABLE |
56 | } | 67 | } |
@@ -80,7 +91,7 @@ export class VideoPlaylistElementMiniatureComponent { | |||
80 | } | 91 | } |
81 | 92 | ||
82 | isVideoBlur (video: Video) { | 93 | isVideoBlur (video: Video) { |
83 | return video.isVideoNSFWForUser(this.authService.getUser(), this.serverService.getConfig()) | 94 | return video.isVideoNSFWForUser(this.authService.getUser(), this.serverConfig) |
84 | } | 95 | } |
85 | 96 | ||
86 | removeFromPlaylist (playlistElement: VideoPlaylistElement) { | 97 | removeFromPlaylist (playlistElement: VideoPlaylistElement) { |
diff --git a/client/src/app/shared/video-playlist/video-playlist.service.ts b/client/src/app/shared/video-playlist/video-playlist.service.ts index 42791af86..2945b4959 100644 --- a/client/src/app/shared/video-playlist/video-playlist.service.ts +++ b/client/src/app/shared/video-playlist/video-playlist.service.ts | |||
@@ -173,7 +173,7 @@ export class VideoPlaylistService { | |||
173 | } | 173 | } |
174 | 174 | ||
175 | extractPlaylists (result: ResultList<VideoPlaylistServerModel>) { | 175 | extractPlaylists (result: ResultList<VideoPlaylistServerModel>) { |
176 | return this.serverService.localeObservable | 176 | return this.serverService.getServerLocale() |
177 | .pipe( | 177 | .pipe( |
178 | map(translations => { | 178 | map(translations => { |
179 | const playlistsJSON = result.data | 179 | const playlistsJSON = result.data |
@@ -190,12 +190,12 @@ export class VideoPlaylistService { | |||
190 | } | 190 | } |
191 | 191 | ||
192 | extractPlaylist (playlist: VideoPlaylistServerModel) { | 192 | extractPlaylist (playlist: VideoPlaylistServerModel) { |
193 | return this.serverService.localeObservable | 193 | return this.serverService.getServerLocale() |
194 | .pipe(map(translations => new VideoPlaylist(playlist, translations))) | 194 | .pipe(map(translations => new VideoPlaylist(playlist, translations))) |
195 | } | 195 | } |
196 | 196 | ||
197 | extractVideoPlaylistElements (result: ResultList<ServerVideoPlaylistElement>) { | 197 | extractVideoPlaylistElements (result: ResultList<ServerVideoPlaylistElement>) { |
198 | return this.serverService.localeObservable | 198 | return this.serverService.getServerLocale() |
199 | .pipe( | 199 | .pipe( |
200 | map(translations => { | 200 | map(translations => { |
201 | const elementsJson = result.data | 201 | const elementsJson = result.data |
diff --git a/client/src/app/shared/video/abstract-video-list.ts b/client/src/app/shared/video/abstract-video-list.ts index 2926b179b..faeea27d9 100644 --- a/client/src/app/shared/video/abstract-video-list.ts +++ b/client/src/app/shared/video/abstract-video-list.ts | |||
@@ -13,7 +13,7 @@ import { Notifier, ServerService } from '@app/core' | |||
13 | import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' | 13 | import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' |
14 | import { I18n } from '@ngx-translate/i18n-polyfill' | 14 | import { I18n } from '@ngx-translate/i18n-polyfill' |
15 | import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date' | 15 | import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date' |
16 | import { ResultList } from '@shared/models' | 16 | import { ResultList, ServerConfig } from '@shared/models' |
17 | 17 | ||
18 | enum GroupDate { | 18 | enum GroupDate { |
19 | UNKNOWN = 0, | 19 | UNKNOWN = 0, |
@@ -61,6 +61,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
61 | 61 | ||
62 | onDataSubject = new Subject<any[]>() | 62 | onDataSubject = new Subject<any[]>() |
63 | 63 | ||
64 | protected serverConfig: ServerConfig | ||
65 | |||
64 | protected abstract notifier: Notifier | 66 | protected abstract notifier: Notifier |
65 | protected abstract authService: AuthService | 67 | protected abstract authService: AuthService |
66 | protected abstract route: ActivatedRoute | 68 | protected abstract route: ActivatedRoute |
@@ -85,6 +87,10 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
85 | } | 87 | } |
86 | 88 | ||
87 | ngOnInit () { | 89 | ngOnInit () { |
90 | this.serverConfig = this.serverService.getTmpConfig() | ||
91 | this.serverService.getConfig() | ||
92 | .subscribe(config => this.serverConfig = config) | ||
93 | |||
88 | this.groupedDateLabels = { | 94 | this.groupedDateLabels = { |
89 | [GroupDate.UNKNOWN]: null, | 95 | [GroupDate.UNKNOWN]: null, |
90 | [GroupDate.TODAY]: this.i18n('Today'), | 96 | [GroupDate.TODAY]: this.i18n('Today'), |
@@ -251,7 +257,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
251 | } | 257 | } |
252 | 258 | ||
253 | let path = this.router.url | 259 | let path = this.router.url |
254 | if (!path || path === '/') path = this.serverService.getConfig().instance.defaultClientRoute | 260 | if (!path || path === '/') path = this.serverConfig.instance.defaultClientRoute |
255 | 261 | ||
256 | this.router.navigate([ path ], { queryParams, replaceUrl: true, queryParamsHandling: 'merge' }) | 262 | this.router.navigate([ path ], { queryParams, replaceUrl: true, queryParamsHandling: 'merge' }) |
257 | } | 263 | } |
diff --git a/client/src/app/shared/video/video-miniature.component.ts b/client/src/app/shared/video/video-miniature.component.ts index d5c7dfd9b..9fffc7ddb 100644 --- a/client/src/app/shared/video/video-miniature.component.ts +++ b/client/src/app/shared/video/video-miniature.component.ts | |||
@@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, LOCALE | |||
2 | import { User } from '../users' | 2 | import { User } from '../users' |
3 | import { Video } from './video.model' | 3 | import { Video } from './video.model' |
4 | import { ServerService } from '@app/core' | 4 | import { ServerService } from '@app/core' |
5 | import { VideoPrivacy, VideoState } from '../../../../../shared' | 5 | import { ServerConfig, VideoPrivacy, VideoState } from '../../../../../shared' |
6 | import { I18n } from '@ngx-translate/i18n-polyfill' | 6 | import { I18n } from '@ngx-translate/i18n-polyfill' |
7 | import { VideoActionsDisplayType } from '@app/shared/video/video-actions-dropdown.component' | 7 | import { VideoActionsDisplayType } from '@app/shared/video/video-actions-dropdown.component' |
8 | import { ScreenService } from '@app/shared/misc/screen.service' | 8 | import { ScreenService } from '@app/shared/misc/screen.service' |
@@ -55,6 +55,7 @@ export class VideoMiniatureComponent implements OnInit { | |||
55 | report: true | 55 | report: true |
56 | } | 56 | } |
57 | showActions = false | 57 | showActions = false |
58 | serverConfig: ServerConfig | ||
58 | 59 | ||
59 | private ownerDisplayTypeChosen: 'account' | 'videoChannel' | 60 | private ownerDisplayTypeChosen: 'account' | 'videoChannel' |
60 | 61 | ||
@@ -66,10 +67,14 @@ export class VideoMiniatureComponent implements OnInit { | |||
66 | ) { } | 67 | ) { } |
67 | 68 | ||
68 | get isVideoBlur () { | 69 | get isVideoBlur () { |
69 | return this.video.isVideoNSFWForUser(this.user, this.serverService.getConfig()) | 70 | return this.video.isVideoNSFWForUser(this.user, this.serverConfig) |
70 | } | 71 | } |
71 | 72 | ||
72 | ngOnInit () { | 73 | ngOnInit () { |
74 | this.serverConfig = this.serverService.getTmpConfig() | ||
75 | this.serverService.getConfig() | ||
76 | .subscribe(config => this.serverConfig = config) | ||
77 | |||
73 | this.setUpBy() | 78 | this.setUpBy() |
74 | 79 | ||
75 | // We rely on mouseenter to lazy load actions | 80 | // We rely on mouseenter to lazy load actions |
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts index b0fa55966..9adf46495 100644 --- a/client/src/app/shared/video/video.service.ts +++ b/client/src/app/shared/video/video.service.ts | |||
@@ -64,7 +64,7 @@ export class VideoService implements VideosProvider { | |||
64 | } | 64 | } |
65 | 65 | ||
66 | getVideo (options: { videoId: string }): Observable<VideoDetails> { | 66 | getVideo (options: { videoId: string }): Observable<VideoDetails> { |
67 | return this.serverService.localeObservable | 67 | return this.serverService.getServerLocale() |
68 | .pipe( | 68 | .pipe( |
69 | switchMap(translations => { | 69 | switchMap(translations => { |
70 | return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + options.videoId) | 70 | return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + options.videoId) |
@@ -315,7 +315,7 @@ export class VideoService implements VideosProvider { | |||
315 | } | 315 | } |
316 | 316 | ||
317 | extractVideos (result: ResultList<VideoServerModel>) { | 317 | extractVideos (result: ResultList<VideoServerModel>) { |
318 | return this.serverService.localeObservable | 318 | return this.serverService.getServerLocale() |
319 | .pipe( | 319 | .pipe( |
320 | map(translations => { | 320 | map(translations => { |
321 | const videosJson = result.data | 321 | const videosJson = result.data |
diff --git a/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.ts b/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.ts index 86c6e03e7..1a9bf5171 100644 --- a/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.ts +++ b/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.ts | |||
@@ -5,7 +5,7 @@ import { VideoCaptionsValidatorsService } from '@app/shared/forms/form-validator | |||
5 | import { ServerService } from '@app/core' | 5 | import { ServerService } from '@app/core' |
6 | import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model' | 6 | import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model' |
7 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' | 7 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' |
8 | import { VideoConstant } from '../../../../../../shared' | 8 | import { ServerConfig, VideoConstant } from '../../../../../../shared' |
9 | 9 | ||
10 | @Component({ | 10 | @Component({ |
11 | selector: 'my-video-caption-add-modal', | 11 | selector: 'my-video-caption-add-modal', |
@@ -15,6 +15,7 @@ import { VideoConstant } from '../../../../../../shared' | |||
15 | 15 | ||
16 | export class VideoCaptionAddModalComponent extends FormReactive implements OnInit { | 16 | export class VideoCaptionAddModalComponent extends FormReactive implements OnInit { |
17 | @Input() existingCaptions: string[] | 17 | @Input() existingCaptions: string[] |
18 | @Input() serverConfig: ServerConfig | ||
18 | 19 | ||
19 | @Output() captionAdded = new EventEmitter<VideoCaptionEdit>() | 20 | @Output() captionAdded = new EventEmitter<VideoCaptionEdit>() |
20 | 21 | ||
@@ -35,15 +36,16 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni | |||
35 | } | 36 | } |
36 | 37 | ||
37 | get videoCaptionExtensions () { | 38 | get videoCaptionExtensions () { |
38 | return this.serverService.getConfig().videoCaption.file.extensions | 39 | return this.serverConfig.videoCaption.file.extensions |
39 | } | 40 | } |
40 | 41 | ||
41 | get videoCaptionMaxSize () { | 42 | get videoCaptionMaxSize () { |
42 | return this.serverService.getConfig().videoCaption.file.size.max | 43 | return this.serverConfig.videoCaption.file.size.max |
43 | } | 44 | } |
44 | 45 | ||
45 | ngOnInit () { | 46 | ngOnInit () { |
46 | this.videoCaptionLanguages = this.serverService.getVideoLanguages() | 47 | this.serverService.getVideoLanguages() |
48 | .subscribe(languages => this.videoCaptionLanguages = languages) | ||
47 | 49 | ||
48 | this.buildForm({ | 50 | this.buildForm({ |
49 | language: this.videoCaptionsValidatorsService.VIDEO_CAPTION_LANGUAGE, | 51 | language: this.videoCaptionsValidatorsService.VIDEO_CAPTION_LANGUAGE, |
diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.html b/client/src/app/videos/+video-edit/shared/video-edit.component.html index e2a222037..e40649d95 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.html +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.html | |||
@@ -269,5 +269,5 @@ | |||
269 | </div> | 269 | </div> |
270 | 270 | ||
271 | <my-video-caption-add-modal | 271 | <my-video-caption-add-modal |
272 | #videoCaptionAddModal [existingCaptions]="existingCaptions" (captionAdded)="onCaptionAdded($event)" | 272 | #videoCaptionAddModal [existingCaptions]="existingCaptions" [serverConfig]="serverConfig" (captionAdded)="onCaptionAdded($event)" |
273 | ></my-video-caption-add-modal> | 273 | ></my-video-caption-add-modal> |
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 d0d5e2a2b..982e071ad 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 | |||
@@ -12,7 +12,7 @@ import { VideoCaptionService } from '@app/shared/video-caption' | |||
12 | import { VideoCaptionAddModalComponent } from '@app/videos/+video-edit/shared/video-caption-add-modal.component' | 12 | import { VideoCaptionAddModalComponent } from '@app/videos/+video-edit/shared/video-caption-add-modal.component' |
13 | import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model' | 13 | import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model' |
14 | import { removeElementFromArray } from '@app/shared/misc/utils' | 14 | import { removeElementFromArray } from '@app/shared/misc/utils' |
15 | import { VideoConstant, VideoPrivacy } from '../../../../../../shared' | 15 | import { ServerConfig, VideoConstant, VideoPrivacy } from '../../../../../../shared' |
16 | import { VideoService } from '@app/shared/video/video.service' | 16 | import { VideoService } from '@app/shared/video/video.service' |
17 | 17 | ||
18 | @Component({ | 18 | @Component({ |
@@ -51,6 +51,8 @@ export class VideoEditComponent implements OnInit, OnDestroy { | |||
51 | calendarTimezone: string | 51 | calendarTimezone: string |
52 | calendarDateFormat: string | 52 | calendarDateFormat: string |
53 | 53 | ||
54 | serverConfig: ServerConfig | ||
55 | |||
54 | private schedulerInterval: any | 56 | private schedulerInterval: any |
55 | private firstPatchDone = false | 57 | private firstPatchDone = false |
56 | private initialVideoCaptions: string[] = [] | 58 | private initialVideoCaptions: string[] = [] |
@@ -130,12 +132,19 @@ export class VideoEditComponent implements OnInit, OnDestroy { | |||
130 | ngOnInit () { | 132 | ngOnInit () { |
131 | this.updateForm() | 133 | this.updateForm() |
132 | 134 | ||
133 | this.videoCategories = this.serverService.getVideoCategories() | 135 | this.serverService.getVideoCategories() |
134 | this.videoLicences = this.serverService.getVideoLicences() | 136 | .subscribe(res => this.videoCategories = res) |
135 | this.videoLanguages = this.serverService.getVideoLanguages() | 137 | this.serverService.getVideoLicences() |
138 | .subscribe(res => this.videoLicences = res) | ||
139 | this.serverService.getVideoLanguages() | ||
140 | .subscribe(res => this.videoLanguages = res) | ||
141 | |||
142 | this.serverService.getVideoPrivacies() | ||
143 | .subscribe(privacies => this.videoPrivacies = this.videoService.explainedPrivacyLabels(privacies)) | ||
136 | 144 | ||
137 | const privacies = this.serverService.getVideoPrivacies() | 145 | this.serverConfig = this.serverService.getTmpConfig() |
138 | this.videoPrivacies = this.videoService.explainedPrivacyLabels(privacies) | 146 | this.serverService.getConfig() |
147 | .subscribe(config => this.serverConfig = config) | ||
139 | 148 | ||
140 | this.initialVideoCaptions = this.videoCaptions.map(c => c.language.id) | 149 | this.initialVideoCaptions = this.videoCaptions.map(c => c.language.id) |
141 | 150 | ||
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-send.ts b/client/src/app/videos/+video-edit/video-add-components/video-send.ts index 580c123a0..b32f16950 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-send.ts +++ b/client/src/app/videos/+video-edit/video-add-components/video-send.ts | |||
@@ -3,7 +3,7 @@ import { LoadingBarService } from '@ngx-loading-bar/core' | |||
3 | import { AuthService, Notifier, ServerService } from '@app/core' | 3 | import { AuthService, Notifier, ServerService } from '@app/core' |
4 | import { catchError, switchMap, tap } from 'rxjs/operators' | 4 | import { catchError, switchMap, tap } from 'rxjs/operators' |
5 | import { FormReactive } from '@app/shared' | 5 | import { FormReactive } from '@app/shared' |
6 | import { VideoConstant, VideoPrivacy } from '../../../../../../shared' | 6 | import { ServerConfig, VideoConstant, VideoPrivacy } from '../../../../../../shared' |
7 | import { VideoService } from '@app/shared/video/video.service' | 7 | import { VideoService } from '@app/shared/video/video.service' |
8 | import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model' | 8 | import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model' |
9 | import { VideoCaptionService } from '@app/shared/video-caption' | 9 | import { VideoCaptionService } from '@app/shared/video-caption' |
@@ -29,6 +29,7 @@ export abstract class VideoSend extends FormReactive implements OnInit { | |||
29 | protected serverService: ServerService | 29 | protected serverService: ServerService |
30 | protected videoService: VideoService | 30 | protected videoService: VideoService |
31 | protected videoCaptionService: VideoCaptionService | 31 | protected videoCaptionService: VideoCaptionService |
32 | protected serverConfig: ServerConfig | ||
32 | 33 | ||
33 | abstract canDeactivate (): CanComponentDeactivateResult | 34 | abstract canDeactivate (): CanComponentDeactivateResult |
34 | 35 | ||
@@ -38,10 +39,14 @@ export abstract class VideoSend extends FormReactive implements OnInit { | |||
38 | populateAsyncUserVideoChannels(this.authService, this.userVideoChannels) | 39 | populateAsyncUserVideoChannels(this.authService, this.userVideoChannels) |
39 | .then(() => this.firstStepChannelId = this.userVideoChannels[ 0 ].id) | 40 | .then(() => this.firstStepChannelId = this.userVideoChannels[ 0 ].id) |
40 | 41 | ||
41 | this.serverService.videoPrivaciesLoaded | 42 | this.serverConfig = this.serverService.getTmpConfig() |
43 | this.serverService.getConfig() | ||
44 | .subscribe(config => this.serverConfig = config) | ||
45 | |||
46 | this.serverService.getVideoPrivacies() | ||
42 | .subscribe( | 47 | .subscribe( |
43 | () => { | 48 | privacies => { |
44 | this.videoPrivacies = this.serverService.getVideoPrivacies() | 49 | this.videoPrivacies = privacies |
45 | 50 | ||
46 | this.firstStepPrivacyId = this.DEFAULT_VIDEO_PRIVACY | 51 | this.firstStepPrivacyId = this.DEFAULT_VIDEO_PRIVACY |
47 | }) | 52 | }) |
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts index 23b79edd3..28e10e562 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts +++ b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts | |||
@@ -14,6 +14,7 @@ import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard. | |||
14 | import { FormValidatorService, UserService } from '@app/shared' | 14 | import { FormValidatorService, UserService } from '@app/shared' |
15 | import { VideoCaptionService } from '@app/shared/video-caption' | 15 | import { VideoCaptionService } from '@app/shared/video-caption' |
16 | import { scrollToTop } from '@app/shared/misc/utils' | 16 | import { scrollToTop } from '@app/shared/misc/utils' |
17 | import { ServerConfig } from '@shared/models' | ||
17 | 18 | ||
18 | @Component({ | 19 | @Component({ |
19 | selector: 'my-video-upload', | 20 | selector: 'my-video-upload', |
@@ -70,7 +71,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy | |||
70 | } | 71 | } |
71 | 72 | ||
72 | get videoExtensions () { | 73 | get videoExtensions () { |
73 | return this.serverService.getConfig().video.file.extensions.join(',') | 74 | return this.serverConfig.video.file.extensions.join(',') |
74 | } | 75 | } |
75 | 76 | ||
76 | ngOnInit () { | 77 | ngOnInit () { |
@@ -155,7 +156,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy | |||
155 | } | 156 | } |
156 | 157 | ||
157 | const privacy = this.firstStepPrivacyId.toString() | 158 | const privacy = this.firstStepPrivacyId.toString() |
158 | const nsfw = this.serverService.getConfig().instance.isNSFW | 159 | const nsfw = this.serverConfig.instance.isNSFW |
159 | const waitTranscoding = true | 160 | const waitTranscoding = true |
160 | const commentsEnabled = true | 161 | const commentsEnabled = true |
161 | const downloadEnabled = true | 162 | const downloadEnabled = true |
diff --git a/client/src/app/videos/+video-edit/video-add.component.ts b/client/src/app/videos/+video-edit/video-add.component.ts index 911bc884e..401d8a08f 100644 --- a/client/src/app/videos/+video-edit/video-add.component.ts +++ b/client/src/app/videos/+video-edit/video-add.component.ts | |||
@@ -1,28 +1,37 @@ | |||
1 | import { Component, HostListener, ViewChild } from '@angular/core' | 1 | import { Component, HostListener, OnInit, ViewChild } from '@angular/core' |
2 | import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard.service' | 2 | import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard.service' |
3 | import { VideoImportUrlComponent } from '@app/videos/+video-edit/video-add-components/video-import-url.component' | 3 | import { VideoImportUrlComponent } from '@app/videos/+video-edit/video-add-components/video-import-url.component' |
4 | import { VideoUploadComponent } from '@app/videos/+video-edit/video-add-components/video-upload.component' | 4 | import { VideoUploadComponent } from '@app/videos/+video-edit/video-add-components/video-upload.component' |
5 | import { AuthService, ServerService } from '@app/core' | 5 | import { AuthService, ServerService } from '@app/core' |
6 | import { VideoImportTorrentComponent } from '@app/videos/+video-edit/video-add-components/video-import-torrent.component' | 6 | import { VideoImportTorrentComponent } from '@app/videos/+video-edit/video-add-components/video-import-torrent.component' |
7 | import { ServerConfig } from '@shared/models' | ||
7 | 8 | ||
8 | @Component({ | 9 | @Component({ |
9 | selector: 'my-videos-add', | 10 | selector: 'my-videos-add', |
10 | templateUrl: './video-add.component.html', | 11 | templateUrl: './video-add.component.html', |
11 | styleUrls: [ './video-add.component.scss' ] | 12 | styleUrls: [ './video-add.component.scss' ] |
12 | }) | 13 | }) |
13 | export class VideoAddComponent implements CanComponentDeactivate { | 14 | export class VideoAddComponent implements OnInit, CanComponentDeactivate { |
14 | @ViewChild('videoUpload', { static: false }) videoUpload: VideoUploadComponent | 15 | @ViewChild('videoUpload', { static: false }) videoUpload: VideoUploadComponent |
15 | @ViewChild('videoImportUrl', { static: false }) videoImportUrl: VideoImportUrlComponent | 16 | @ViewChild('videoImportUrl', { static: false }) videoImportUrl: VideoImportUrlComponent |
16 | @ViewChild('videoImportTorrent', { static: false }) videoImportTorrent: VideoImportTorrentComponent | 17 | @ViewChild('videoImportTorrent', { static: false }) videoImportTorrent: VideoImportTorrentComponent |
17 | 18 | ||
18 | secondStepType: 'upload' | 'import-url' | 'import-torrent' | 19 | secondStepType: 'upload' | 'import-url' | 'import-torrent' |
19 | videoName: string | 20 | videoName: string |
21 | serverConfig: ServerConfig | ||
20 | 22 | ||
21 | constructor ( | 23 | constructor ( |
22 | private auth: AuthService, | 24 | private auth: AuthService, |
23 | private serverService: ServerService | 25 | private serverService: ServerService |
24 | ) {} | 26 | ) {} |
25 | 27 | ||
28 | ngOnInit () { | ||
29 | this.serverConfig = this.serverService.getTmpConfig() | ||
30 | |||
31 | this.serverService.getConfig() | ||
32 | .subscribe(config => this.serverConfig = config) | ||
33 | } | ||
34 | |||
26 | onFirstStepDone (type: 'upload' | 'import-url' | 'import-torrent', videoName: string) { | 35 | onFirstStepDone (type: 'upload' | 'import-url' | 'import-torrent', videoName: string) { |
27 | this.secondStepType = type | 36 | this.secondStepType = type |
28 | this.videoName = videoName | 37 | this.videoName = videoName |
@@ -52,11 +61,11 @@ export class VideoAddComponent implements CanComponentDeactivate { | |||
52 | } | 61 | } |
53 | 62 | ||
54 | isVideoImportHttpEnabled () { | 63 | isVideoImportHttpEnabled () { |
55 | return this.serverService.getConfig().import.videos.http.enabled | 64 | return this.serverConfig.import.videos.http.enabled |
56 | } | 65 | } |
57 | 66 | ||
58 | isVideoImportTorrentEnabled () { | 67 | isVideoImportTorrentEnabled () { |
59 | return this.serverService.getConfig().import.videos.torrent.enabled | 68 | return this.serverConfig.import.videos.torrent.enabled |
60 | } | 69 | } |
61 | 70 | ||
62 | isInSecondStep () { | 71 | isInSecondStep () { |
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 8cc1e8b58..626d0ca07 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -8,7 +8,7 @@ import { MetaService } from '@ngx-meta/core' | |||
8 | import { AuthUser, Notifier, ServerService } from '@app/core' | 8 | import { AuthUser, Notifier, ServerService } from '@app/core' |
9 | import { forkJoin, Observable, Subscription } from 'rxjs' | 9 | import { forkJoin, Observable, Subscription } from 'rxjs' |
10 | import { Hotkey, HotkeysService } from 'angular2-hotkeys' | 10 | import { Hotkey, HotkeysService } from 'angular2-hotkeys' |
11 | import { UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '../../../../../shared' | 11 | import { ServerConfig, UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '../../../../../shared' |
12 | import { AuthService, ConfirmService } from '../../core' | 12 | import { AuthService, ConfirmService } from '../../core' |
13 | import { RestExtractor, VideoBlacklistService } from '../../shared' | 13 | import { RestExtractor, VideoBlacklistService } from '../../shared' |
14 | import { VideoDetails } from '../../shared/video/video-details.model' | 14 | import { VideoDetails } from '../../shared/video/video-details.model' |
@@ -84,6 +84,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
84 | private queryParamsSub: Subscription | 84 | private queryParamsSub: Subscription |
85 | private configSub: Subscription | 85 | private configSub: Subscription |
86 | 86 | ||
87 | private serverConfig: ServerConfig | ||
88 | |||
87 | constructor ( | 89 | constructor ( |
88 | private elementRef: ElementRef, | 90 | private elementRef: ElementRef, |
89 | private changeDetector: ChangeDetectorRef, | 91 | private changeDetector: ChangeDetectorRef, |
@@ -120,11 +122,15 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
120 | } | 122 | } |
121 | 123 | ||
122 | async ngOnInit () { | 124 | async ngOnInit () { |
123 | this.configSub = this.serverService.configLoaded | 125 | this.serverConfig = this.serverService.getTmpConfig() |
124 | .subscribe(() => { | 126 | |
127 | this.configSub = this.serverService.getConfig() | ||
128 | .subscribe(config => { | ||
129 | this.serverConfig = config | ||
130 | |||
125 | if ( | 131 | if ( |
126 | isWebRTCDisabled() || | 132 | isWebRTCDisabled() || |
127 | this.serverService.getConfig().tracker.enabled === false || | 133 | this.serverConfig.tracker.enabled === false || |
128 | peertubeLocalStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY) === 'true' | 134 | peertubeLocalStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY) === 'true' |
129 | ) { | 135 | ) { |
130 | this.hasAlreadyAcceptedPrivacyConcern = true | 136 | this.hasAlreadyAcceptedPrivacyConcern = true |
@@ -280,7 +286,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
280 | } | 286 | } |
281 | 287 | ||
282 | isVideoBlur (video: Video) { | 288 | isVideoBlur (video: Video) { |
283 | return video.isVideoNSFWForUser(this.user, this.serverService.getConfig()) | 289 | return video.isVideoNSFWForUser(this.user, this.serverConfig) |
284 | } | 290 | } |
285 | 291 | ||
286 | isAutoPlayEnabled () { | 292 | isAutoPlayEnabled () { |
diff --git a/client/src/app/videos/video-list/video-most-liked.component.ts b/client/src/app/videos/video-list/video-most-liked.component.ts index aff8413eb..f94a7da04 100644 --- a/client/src/app/videos/video-list/video-most-liked.component.ts +++ b/client/src/app/videos/video-list/video-most-liked.component.ts | |||
@@ -40,11 +40,8 @@ export class VideoMostLikedComponent extends AbstractVideoList implements OnInit | |||
40 | 40 | ||
41 | this.generateSyndicationList() | 41 | this.generateSyndicationList() |
42 | 42 | ||
43 | this.serverService.configLoaded.subscribe( | 43 | this.titlePage = this.i18n('Most liked videos') |
44 | () => { | 44 | this.titleTooltip = this.i18n('Videos that have the higher number of likes.') |
45 | this.titlePage = this.i18n('Most liked videos') | ||
46 | this.titleTooltip = this.i18n('Videos that have the higher number of likes.') | ||
47 | }) | ||
48 | } | 45 | } |
49 | 46 | ||
50 | getVideosObservable (page: number) { | 47 | getVideosObservable (page: number) { |
diff --git a/client/src/app/videos/video-list/video-trending.component.ts b/client/src/app/videos/video-list/video-trending.component.ts index 19324da63..bc88679fa 100644 --- a/client/src/app/videos/video-list/video-trending.component.ts +++ b/client/src/app/videos/video-list/video-trending.component.ts | |||
@@ -40,9 +40,9 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit, | |||
40 | 40 | ||
41 | this.generateSyndicationList() | 41 | this.generateSyndicationList() |
42 | 42 | ||
43 | this.serverService.configLoaded.subscribe( | 43 | this.serverService.getConfig().subscribe( |
44 | () => { | 44 | config => { |
45 | const trendingDays = this.serverService.getConfig().trending.videos.intervalDays | 45 | const trendingDays = config.trending.videos.intervalDays |
46 | 46 | ||
47 | if (trendingDays === 1) { | 47 | if (trendingDays === 1) { |
48 | this.titlePage = this.i18n('Trending for the last 24 hours') | 48 | this.titlePage = this.i18n('Trending for the last 24 hours') |
diff --git a/scripts/build/index.sh b/scripts/build/index.sh index 12359e68f..31f2733c3 100755 --- a/scripts/build/index.sh +++ b/scripts/build/index.sh | |||
@@ -8,6 +8,6 @@ else | |||
8 | clientCommand="npm run build:client" | 8 | clientCommand="npm run build:client" |
9 | fi | 9 | fi |
10 | 10 | ||
11 | npm run concurrently -- --raw \ | 11 | npm run concurrently -- --raw \w |
12 | "$clientCommand" \ | 12 | "$clientCommand" \ |
13 | "npm run build:server" | 13 | "npm run build:server" |