diff options
Diffstat (limited to 'client/src/app')
13 files changed, 109 insertions, 72 deletions
diff --git a/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts index 1a95980ae..6af224920 100644 --- a/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts +++ b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts | |||
@@ -5,8 +5,7 @@ import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' | |||
5 | import { ComponentPagination, ConfirmService, hasMoreItems, Notifier } from '@app/core' | 5 | import { ComponentPagination, ConfirmService, hasMoreItems, Notifier } from '@app/core' |
6 | import { PluginService } from '@app/core/plugins/plugin.service' | 6 | import { PluginService } from '@app/core/plugins/plugin.service' |
7 | import { compareSemVer } from '@shared/core-utils/miscs/miscs' | 7 | import { compareSemVer } from '@shared/core-utils/miscs/miscs' |
8 | import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model' | 8 | import { PeerTubePlugin, PluginType } from '@shared/models' |
9 | import { PluginType } from '@shared/models/plugins/plugin.type' | ||
10 | 9 | ||
11 | @Component({ | 10 | @Component({ |
12 | selector: 'my-plugin-list-installed', | 11 | selector: 'my-plugin-list-installed', |
diff --git a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts index d2c179aba..0a6e57904 100644 --- a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts +++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts | |||
@@ -4,8 +4,7 @@ import { Component, OnInit } from '@angular/core' | |||
4 | import { ActivatedRoute, Router } from '@angular/router' | 4 | import { ActivatedRoute, Router } from '@angular/router' |
5 | import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' | 5 | import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' |
6 | import { ComponentPagination, ConfirmService, hasMoreItems, Notifier, PluginService } from '@app/core' | 6 | import { ComponentPagination, ConfirmService, hasMoreItems, Notifier, PluginService } from '@app/core' |
7 | import { PeerTubePluginIndex } from '@shared/models/plugins/peertube-plugin-index.model' | 7 | import { PeerTubePluginIndex, PluginType } from '@shared/models' |
8 | import { PluginType } from '@shared/models/plugins/plugin.type' | ||
9 | 8 | ||
10 | @Component({ | 9 | @Component({ |
11 | selector: 'my-plugin-search', | 10 | selector: 'my-plugin-search', |
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 34119f7ab..3d916dbce 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 | |||
@@ -21,8 +21,15 @@ import { | |||
21 | import { FormReactiveValidationMessages, FormValidatorService } from '@app/shared/shared-forms' | 21 | import { FormReactiveValidationMessages, FormValidatorService } from '@app/shared/shared-forms' |
22 | import { InstanceService } from '@app/shared/shared-instance' | 22 | import { InstanceService } from '@app/shared/shared-instance' |
23 | import { VideoCaptionEdit, VideoEdit, VideoService } from '@app/shared/shared-main' | 23 | import { VideoCaptionEdit, VideoEdit, VideoService } from '@app/shared/shared-main' |
24 | import { LiveVideo, ServerConfig, VideoConstant, VideoDetails, VideoPrivacy } from '@shared/models' | 24 | import { |
25 | import { RegisterClientFormFieldOptions, RegisterClientVideoFieldOptions } from '@shared/models/plugins/register-client-form-field.model' | 25 | LiveVideo, |
26 | RegisterClientFormFieldOptions, | ||
27 | RegisterClientVideoFieldOptions, | ||
28 | ServerConfig, | ||
29 | VideoConstant, | ||
30 | VideoDetails, | ||
31 | VideoPrivacy | ||
32 | } from '@shared/models' | ||
26 | import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service' | 33 | import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service' |
27 | import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component' | 34 | import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component' |
28 | import { VideoEditType } from './video-edit.type' | 35 | import { VideoEditType } from './video-edit.type' |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts index 3aae24732..23bd5ef76 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts | |||
@@ -5,7 +5,7 @@ import { scrollToTop } from '@app/helpers' | |||
5 | import { FormValidatorService } from '@app/shared/shared-forms' | 5 | import { FormValidatorService } from '@app/shared/shared-forms' |
6 | import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' | 6 | import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' |
7 | import { LoadingBarService } from '@ngx-loading-bar/core' | 7 | import { LoadingBarService } from '@ngx-loading-bar/core' |
8 | import { VideoPrivacy, VideoUpdate } from '@shared/models' | 8 | import { ServerErrorCode, VideoPrivacy, VideoUpdate } from '@shared/models' |
9 | import { hydrateFormFromVideo } from '../shared/video-edit-utils' | 9 | import { hydrateFormFromVideo } from '../shared/video-edit-utils' |
10 | import { VideoSend } from './video-send' | 10 | import { VideoSend } from './video-send' |
11 | 11 | ||
@@ -113,7 +113,13 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Af | |||
113 | this.loadingBar.useRef().complete() | 113 | this.loadingBar.useRef().complete() |
114 | this.isImportingVideo = false | 114 | this.isImportingVideo = false |
115 | this.firstStepError.emit() | 115 | this.firstStepError.emit() |
116 | this.notifier.error(err.message) | 116 | |
117 | let message = err.message | ||
118 | if (err.body?.code === ServerErrorCode.INCORRECT_FILES_IN_TORRENT) { | ||
119 | message = $localize`Torrents with only 1 file are supported.` | ||
120 | } | ||
121 | |||
122 | this.notifier.error(message) | ||
117 | } | 123 | } |
118 | ) | 124 | ) |
119 | } | 125 | } |
diff --git a/client/src/app/+videos/+video-edit/video-add.component.html b/client/src/app/+videos/+video-edit/video-add.component.html index dc8c2f21d..ac75d9ff8 100644 --- a/client/src/app/+videos/+video-edit/video-add.component.html +++ b/client/src/app/+videos/+video-edit/video-add.component.html | |||
@@ -20,8 +20,8 @@ | |||
20 | <ng-container *ngIf="secondStepType === 'upload'" i18n>Upload {{ videoName }}</ng-container> | 20 | <ng-container *ngIf="secondStepType === 'upload'" i18n>Upload {{ videoName }}</ng-container> |
21 | </div> | 21 | </div> |
22 | 22 | ||
23 | <div ngbNav #nav="ngbNav" class="nav-tabs video-add-nav" [ngClass]="{ 'hide-nav': secondStepType !== undefined }"> | 23 | <div ngbNav #nav="ngbNav" class="nav-tabs video-add-nav" [activeId]="activeNav" (activeIdChange)="onNavChange($event)" [ngClass]="{ 'hide-nav': !!secondStepType }"> |
24 | <ng-container ngbNavItem> | 24 | <ng-container ngbNavItem="upload"> |
25 | <a ngbNavLink> | 25 | <a ngbNavLink> |
26 | <span i18n>Upload a file</span> | 26 | <span i18n>Upload a file</span> |
27 | </a> | 27 | </a> |
@@ -31,7 +31,7 @@ | |||
31 | </ng-template> | 31 | </ng-template> |
32 | </ng-container> | 32 | </ng-container> |
33 | 33 | ||
34 | <ng-container ngbNavItem *ngIf="isVideoImportHttpEnabled()"> | 34 | <ng-container ngbNavItem="import-url" *ngIf="isVideoImportHttpEnabled()"> |
35 | <a ngbNavLink> | 35 | <a ngbNavLink> |
36 | <span i18n>Import with URL</span> | 36 | <span i18n>Import with URL</span> |
37 | </a> | 37 | </a> |
@@ -41,7 +41,7 @@ | |||
41 | </ng-template> | 41 | </ng-template> |
42 | </ng-container> | 42 | </ng-container> |
43 | 43 | ||
44 | <ng-container ngbNavItem *ngIf="isVideoImportTorrentEnabled()"> | 44 | <ng-container ngbNavItem="import-torrent" *ngIf="isVideoImportTorrentEnabled()"> |
45 | <a ngbNavLink> | 45 | <a ngbNavLink> |
46 | <span i18n>Import with torrent</span> | 46 | <span i18n>Import with torrent</span> |
47 | </a> | 47 | </a> |
@@ -51,7 +51,7 @@ | |||
51 | </ng-template> | 51 | </ng-template> |
52 | </ng-container> | 52 | </ng-container> |
53 | 53 | ||
54 | <ng-container ngbNavItem *ngIf="isVideoLiveEnabled()"> | 54 | <ng-container ngbNavItem="go-live" *ngIf="isVideoLiveEnabled()"> |
55 | <a ngbNavLink> | 55 | <a ngbNavLink> |
56 | <span i18n>Go live</span> | 56 | <span i18n>Go live</span> |
57 | </a> | 57 | </a> |
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 441d5a3db..d735c936c 100644 --- a/client/src/app/+videos/+video-edit/video-add.component.ts +++ b/client/src/app/+videos/+video-edit/video-add.component.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { Component, HostListener, OnInit, ViewChild } from '@angular/core' | 1 | import { Component, HostListener, OnInit, ViewChild } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | ||
2 | import { AuthService, AuthUser, CanComponentDeactivate, ServerService } from '@app/core' | 3 | import { AuthService, AuthUser, CanComponentDeactivate, ServerService } from '@app/core' |
3 | import { ServerConfig } from '@shared/models' | 4 | import { ServerConfig } from '@shared/models' |
4 | import { VideoEditType } from './shared/video-edit.type' | 5 | import { VideoEditType } from './shared/video-edit.type' |
@@ -22,11 +23,16 @@ export class VideoAddComponent implements OnInit, CanComponentDeactivate { | |||
22 | 23 | ||
23 | secondStepType: VideoEditType | 24 | secondStepType: VideoEditType |
24 | videoName: string | 25 | videoName: string |
25 | serverConfig: ServerConfig | 26 | |
27 | activeNav: string | ||
28 | |||
29 | private serverConfig: ServerConfig | ||
26 | 30 | ||
27 | constructor ( | 31 | constructor ( |
28 | private auth: AuthService, | 32 | private auth: AuthService, |
29 | private serverService: ServerService | 33 | private serverService: ServerService, |
34 | private route: ActivatedRoute, | ||
35 | private router: Router | ||
30 | ) {} | 36 | ) {} |
31 | 37 | ||
32 | get userInformationLoaded () { | 38 | get userInformationLoaded () { |
@@ -42,6 +48,16 @@ export class VideoAddComponent implements OnInit, CanComponentDeactivate { | |||
42 | .subscribe(config => this.serverConfig = config) | 48 | .subscribe(config => this.serverConfig = config) |
43 | 49 | ||
44 | this.user = this.auth.getUser() | 50 | this.user = this.auth.getUser() |
51 | |||
52 | if (this.route.snapshot.fragment) { | ||
53 | this.onNavChange(this.route.snapshot.fragment) | ||
54 | } | ||
55 | } | ||
56 | |||
57 | onNavChange (newActiveNav: string) { | ||
58 | this.activeNav = newActiveNav | ||
59 | |||
60 | this.router.navigate([], { fragment: this.activeNav }) | ||
45 | } | 61 | } |
46 | 62 | ||
47 | onFirstStepDone (type: VideoEditType, videoName: string) { | 63 | onFirstStepDone (type: VideoEditType, videoName: string) { |
diff --git a/client/src/app/+videos/video-list/trending/video-trending-header.component.ts b/client/src/app/+videos/video-list/trending/video-trending-header.component.ts index 55040f3c9..bbb02a236 100644 --- a/client/src/app/+videos/video-list/trending/video-trending-header.component.ts +++ b/client/src/app/+videos/video-list/trending/video-trending-header.component.ts | |||
@@ -31,7 +31,8 @@ export class VideoTrendingHeaderComponent extends VideoListHeaderComponent imple | |||
31 | private route: ActivatedRoute, | 31 | private route: ActivatedRoute, |
32 | private router: Router, | 32 | private router: Router, |
33 | private auth: AuthService, | 33 | private auth: AuthService, |
34 | private serverService: ServerService | 34 | private serverService: ServerService, |
35 | private redirectService: RedirectService | ||
35 | ) { | 36 | ) { |
36 | super(data) | 37 | super(data) |
37 | 38 | ||
@@ -84,12 +85,7 @@ export class VideoTrendingHeaderComponent extends VideoListHeaderComponent imple | |||
84 | 85 | ||
85 | this.algorithmChangeSub = this.route.queryParams.subscribe( | 86 | this.algorithmChangeSub = this.route.queryParams.subscribe( |
86 | queryParams => { | 87 | queryParams => { |
87 | const algorithm = queryParams['alg'] | 88 | this.data.model = queryParams['alg'] || this.redirectService.getDefaultTrendingAlgorithm() |
88 | if (algorithm) { | ||
89 | this.data.model = algorithm | ||
90 | } else { | ||
91 | this.data.model = RedirectService.DEFAULT_TRENDING_ALGORITHM | ||
92 | } | ||
93 | } | 89 | } |
94 | ) | 90 | ) |
95 | } | 91 | } |
@@ -99,7 +95,7 @@ export class VideoTrendingHeaderComponent extends VideoListHeaderComponent imple | |||
99 | } | 95 | } |
100 | 96 | ||
101 | setSort () { | 97 | setSort () { |
102 | const alg = this.data.model !== RedirectService.DEFAULT_TRENDING_ALGORITHM | 98 | const alg = this.data.model !== this.redirectService.getDefaultTrendingAlgorithm() |
103 | ? this.data.model | 99 | ? this.data.model |
104 | : undefined | 100 | : undefined |
105 | 101 | ||
diff --git a/client/src/app/+videos/video-list/trending/video-trending.component.ts b/client/src/app/+videos/video-list/trending/video-trending.component.ts index e50d6ec3a..ebec672f3 100644 --- a/client/src/app/+videos/video-list/trending/video-trending.component.ts +++ b/client/src/app/+videos/video-list/trending/video-trending.component.ts | |||
@@ -35,11 +35,12 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit, | |||
35 | protected storageService: LocalStorageService, | 35 | protected storageService: LocalStorageService, |
36 | protected cfr: ComponentFactoryResolver, | 36 | protected cfr: ComponentFactoryResolver, |
37 | private videoService: VideoService, | 37 | private videoService: VideoService, |
38 | private redirectService: RedirectService, | ||
38 | private hooks: HooksService | 39 | private hooks: HooksService |
39 | ) { | 40 | ) { |
40 | super() | 41 | super() |
41 | 42 | ||
42 | this.defaultSort = this.parseAlgorithm(RedirectService.DEFAULT_TRENDING_ALGORITHM) | 43 | this.defaultSort = this.parseAlgorithm(this.redirectService.getDefaultTrendingAlgorithm()) |
43 | 44 | ||
44 | this.headerComponentInjector = this.getInjector() | 45 | this.headerComponentInjector = this.getInjector() |
45 | } | 46 | } |
@@ -106,7 +107,7 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit, | |||
106 | } | 107 | } |
107 | 108 | ||
108 | protected loadPageRouteParams (queryParams: Params) { | 109 | protected loadPageRouteParams (queryParams: Params) { |
109 | const algorithm = queryParams['alg'] || RedirectService.DEFAULT_TRENDING_ALGORITHM | 110 | const algorithm = queryParams['alg'] || this.redirectService.getDefaultTrendingAlgorithm() |
110 | 111 | ||
111 | this.sort = this.parseAlgorithm(algorithm) | 112 | this.sort = this.parseAlgorithm(algorithm) |
112 | } | 113 | } |
@@ -115,8 +116,10 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit, | |||
115 | switch (algorithm) { | 116 | switch (algorithm) { |
116 | case 'most-viewed': | 117 | case 'most-viewed': |
117 | return '-trending' | 118 | return '-trending' |
119 | |||
118 | case 'most-liked': | 120 | case 'most-liked': |
119 | return '-likes' | 121 | return '-likes' |
122 | |||
120 | default: | 123 | default: |
121 | return '-' + algorithm as VideoSortField | 124 | return '-' + algorithm as VideoSortField |
122 | } | 125 | } |
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index 66d871b4a..239e275a4 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts | |||
@@ -67,7 +67,7 @@ export class AppComponent implements OnInit, AfterViewInit { | |||
67 | } | 67 | } |
68 | 68 | ||
69 | goToDefaultRoute () { | 69 | goToDefaultRoute () { |
70 | return this.router.navigateByUrl(RedirectService.DEFAULT_ROUTE) | 70 | return this.router.navigateByUrl(this.redirectService.getDefaultRoute()) |
71 | } | 71 | } |
72 | 72 | ||
73 | ngOnInit () { | 73 | ngOnInit () { |
diff --git a/client/src/app/core/routing/redirect.service.ts b/client/src/app/core/routing/redirect.service.ts index 6d26fb504..cf690a4d0 100644 --- a/client/src/app/core/routing/redirect.service.ts +++ b/client/src/app/core/routing/redirect.service.ts | |||
@@ -6,14 +6,14 @@ import { ServerService } from '../server' | |||
6 | export class RedirectService { | 6 | export class RedirectService { |
7 | // Default route could change according to the instance configuration | 7 | // Default route could change according to the instance configuration |
8 | static INIT_DEFAULT_ROUTE = '/videos/trending' | 8 | static INIT_DEFAULT_ROUTE = '/videos/trending' |
9 | static DEFAULT_ROUTE = RedirectService.INIT_DEFAULT_ROUTE | ||
10 | static INIT_DEFAULT_TRENDING_ALGORITHM = 'most-viewed' | 9 | static INIT_DEFAULT_TRENDING_ALGORITHM = 'most-viewed' |
11 | static DEFAULT_TRENDING_ALGORITHM = RedirectService.INIT_DEFAULT_TRENDING_ALGORITHM | ||
12 | 10 | ||
13 | private previousUrl: string | 11 | private previousUrl: string |
14 | private currentUrl: string | 12 | private currentUrl: string |
15 | 13 | ||
16 | private redirectingToHomepage = false | 14 | private redirectingToHomepage = false |
15 | private defaultTrendingAlgorithm = RedirectService.INIT_DEFAULT_TRENDING_ALGORITHM | ||
16 | private defaultRoute = RedirectService.INIT_DEFAULT_ROUTE | ||
17 | 17 | ||
18 | constructor ( | 18 | constructor ( |
19 | private router: Router, | 19 | private router: Router, |
@@ -22,10 +22,10 @@ export class RedirectService { | |||
22 | // The config is first loaded from the cache so try to get the default route | 22 | // The config is first loaded from the cache so try to get the default route |
23 | const tmpConfig = this.serverService.getTmpConfig() | 23 | const tmpConfig = this.serverService.getTmpConfig() |
24 | if (tmpConfig?.instance?.defaultClientRoute) { | 24 | if (tmpConfig?.instance?.defaultClientRoute) { |
25 | RedirectService.DEFAULT_ROUTE = tmpConfig.instance.defaultClientRoute | 25 | this.defaultRoute = tmpConfig.instance.defaultClientRoute |
26 | } | 26 | } |
27 | if (tmpConfig?.trending?.videos?.algorithms?.default) { | 27 | if (tmpConfig?.trending?.videos?.algorithms?.default) { |
28 | RedirectService.DEFAULT_TRENDING_ALGORITHM = tmpConfig.trending.videos.algorithms.default | 28 | this.defaultTrendingAlgorithm = tmpConfig.trending.videos.algorithms.default |
29 | } | 29 | } |
30 | 30 | ||
31 | // Load default route | 31 | // Load default route |
@@ -34,13 +34,8 @@ export class RedirectService { | |||
34 | const defaultRouteConfig = config.instance.defaultClientRoute | 34 | const defaultRouteConfig = config.instance.defaultClientRoute |
35 | const defaultTrendingConfig = config.trending.videos.algorithms.default | 35 | const defaultTrendingConfig = config.trending.videos.algorithms.default |
36 | 36 | ||
37 | if (defaultRouteConfig) { | 37 | if (defaultRouteConfig) this.defaultRoute = defaultRouteConfig |
38 | RedirectService.DEFAULT_ROUTE = defaultRouteConfig | 38 | if (defaultTrendingConfig) this.defaultTrendingAlgorithm = defaultTrendingConfig |
39 | } | ||
40 | |||
41 | if (defaultTrendingConfig) { | ||
42 | RedirectService.DEFAULT_TRENDING_ALGORITHM = defaultTrendingConfig | ||
43 | } | ||
44 | }) | 39 | }) |
45 | 40 | ||
46 | // Track previous url | 41 | // Track previous url |
@@ -53,6 +48,14 @@ export class RedirectService { | |||
53 | }) | 48 | }) |
54 | } | 49 | } |
55 | 50 | ||
51 | getDefaultRoute () { | ||
52 | return this.defaultRoute | ||
53 | } | ||
54 | |||
55 | getDefaultTrendingAlgorithm () { | ||
56 | return this.defaultTrendingAlgorithm | ||
57 | } | ||
58 | |||
56 | redirectToPreviousRoute () { | 59 | redirectToPreviousRoute () { |
57 | const exceptions = [ | 60 | const exceptions = [ |
58 | '/verify-account', | 61 | '/verify-account', |
@@ -72,21 +75,21 @@ export class RedirectService { | |||
72 | 75 | ||
73 | this.redirectingToHomepage = true | 76 | this.redirectingToHomepage = true |
74 | 77 | ||
75 | console.log('Redirecting to %s...', RedirectService.DEFAULT_ROUTE) | 78 | console.log('Redirecting to %s...', this.defaultRoute) |
76 | 79 | ||
77 | this.router.navigateByUrl(RedirectService.DEFAULT_ROUTE, { skipLocationChange }) | 80 | this.router.navigateByUrl(this.defaultRoute, { skipLocationChange }) |
78 | .then(() => this.redirectingToHomepage = false) | 81 | .then(() => this.redirectingToHomepage = false) |
79 | .catch(() => { | 82 | .catch(() => { |
80 | this.redirectingToHomepage = false | 83 | this.redirectingToHomepage = false |
81 | 84 | ||
82 | console.error( | 85 | console.error( |
83 | 'Cannot navigate to %s, resetting default route to %s.', | 86 | 'Cannot navigate to %s, resetting default route to %s.', |
84 | RedirectService.DEFAULT_ROUTE, | 87 | this.defaultRoute, |
85 | RedirectService.INIT_DEFAULT_ROUTE | 88 | RedirectService.INIT_DEFAULT_ROUTE |
86 | ) | 89 | ) |
87 | 90 | ||
88 | RedirectService.DEFAULT_ROUTE = RedirectService.INIT_DEFAULT_ROUTE | 91 | this.defaultRoute = RedirectService.INIT_DEFAULT_ROUTE |
89 | return this.router.navigateByUrl(RedirectService.DEFAULT_ROUTE, { skipLocationChange }) | 92 | return this.router.navigateByUrl(this.defaultRoute, { skipLocationChange }) |
90 | }) | 93 | }) |
91 | 94 | ||
92 | } | 95 | } |
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index 906191ae1..e48786e18 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts | |||
@@ -3,7 +3,6 @@ import { first, map, share, shareReplay, switchMap, tap } from 'rxjs/operators' | |||
3 | import { HttpClient } from '@angular/common/http' | 3 | import { HttpClient } from '@angular/common/http' |
4 | import { Inject, Injectable, LOCALE_ID } from '@angular/core' | 4 | import { Inject, Injectable, LOCALE_ID } from '@angular/core' |
5 | import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers' | 5 | import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers' |
6 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' | ||
7 | import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n' | 6 | import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n' |
8 | import { SearchTargetType, ServerConfig, ServerStats, VideoConstant } from '@shared/models' | 7 | import { SearchTargetType, ServerConfig, ServerStats, VideoConstant } from '@shared/models' |
9 | import { environment } from '../../../environments/environment' | 8 | import { environment } from '../../../environments/environment' |
@@ -16,8 +15,6 @@ export class ServerService { | |||
16 | private static BASE_LOCALE_URL = environment.apiUrl + '/client/locales/' | 15 | private static BASE_LOCALE_URL = environment.apiUrl + '/client/locales/' |
17 | private static BASE_STATS_URL = environment.apiUrl + '/api/v1/server/stats' | 16 | private static BASE_STATS_URL = environment.apiUrl + '/api/v1/server/stats' |
18 | 17 | ||
19 | private static CONFIG_LOCAL_STORAGE_KEY = 'server-config' | ||
20 | |||
21 | configReloaded = new Subject<ServerConfig>() | 18 | configReloaded = new Subject<ServerConfig>() |
22 | 19 | ||
23 | private localeObservable: Observable<any> | 20 | private localeObservable: Observable<any> |
@@ -212,7 +209,6 @@ export class ServerService { | |||
212 | if (!this.configObservable) { | 209 | if (!this.configObservable) { |
213 | this.configObservable = this.http.get<ServerConfig>(ServerService.BASE_CONFIG_URL) | 210 | this.configObservable = this.http.get<ServerConfig>(ServerService.BASE_CONFIG_URL) |
214 | .pipe( | 211 | .pipe( |
215 | tap(config => this.saveConfigLocally(config)), | ||
216 | tap(config => { | 212 | tap(config => { |
217 | this.config = config | 213 | this.config = config |
218 | this.configLoaded = true | 214 | this.configLoaded = true |
@@ -343,20 +339,15 @@ export class ServerService { | |||
343 | ) | 339 | ) |
344 | } | 340 | } |
345 | 341 | ||
346 | private saveConfigLocally (config: ServerConfig) { | ||
347 | peertubeLocalStorage.setItem(ServerService.CONFIG_LOCAL_STORAGE_KEY, JSON.stringify(config)) | ||
348 | } | ||
349 | |||
350 | private loadConfigLocally () { | 342 | private loadConfigLocally () { |
351 | const configString = peertubeLocalStorage.getItem(ServerService.CONFIG_LOCAL_STORAGE_KEY) | 343 | const configString = window['PeerTubeServerConfig'] |
352 | 344 | if (!configString) return | |
353 | if (configString) { | 345 | |
354 | try { | 346 | try { |
355 | const parsed = JSON.parse(configString) | 347 | const parsed = JSON.parse(configString) |
356 | Object.assign(this.config, parsed) | 348 | Object.assign(this.config, parsed) |
357 | } catch (err) { | 349 | } catch (err) { |
358 | console.error('Cannot parse config saved in local storage.', err) | 350 | console.error('Cannot parse config saved in from index.html.', err) |
359 | } | ||
360 | } | 351 | } |
361 | } | 352 | } |
362 | } | 353 | } |
diff --git a/client/src/app/core/theme/theme.service.ts b/client/src/app/core/theme/theme.service.ts index 4c4611d01..e7a5ae17a 100644 --- a/client/src/app/core/theme/theme.service.ts +++ b/client/src/app/core/theme/theme.service.ts | |||
@@ -82,7 +82,19 @@ export class ThemeService { | |||
82 | : this.userService.getAnonymousUser().theme | 82 | : this.userService.getAnonymousUser().theme |
83 | 83 | ||
84 | if (theme !== 'instance-default') return theme | 84 | if (theme !== 'instance-default') return theme |
85 | return this.serverConfig.theme.default | 85 | |
86 | const instanceTheme = this.serverConfig.theme.default | ||
87 | if (instanceTheme !== 'default') return instanceTheme | ||
88 | |||
89 | // Default to dark theme if available and wanted by the user | ||
90 | if ( | ||
91 | this.themes.find(t => t.name === 'dark') && | ||
92 | window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches | ||
93 | ) { | ||
94 | return 'dark' | ||
95 | } | ||
96 | |||
97 | return instanceTheme | ||
86 | } | 98 | } |
87 | 99 | ||
88 | private loadTheme (name: string) { | 100 | private loadTheme (name: string) { |
diff --git a/client/src/app/shared/shared-main/angular/from-now.pipe.ts b/client/src/app/shared/shared-main/angular/from-now.pipe.ts index 5e7832807..d62c1f88e 100644 --- a/client/src/app/shared/shared-main/angular/from-now.pipe.ts +++ b/client/src/app/shared/shared-main/angular/from-now.pipe.ts | |||
@@ -3,32 +3,37 @@ import { Pipe, PipeTransform } from '@angular/core' | |||
3 | // Thanks: https://stackoverflow.com/questions/3177836/how-to-format-time-since-xxx-e-g-4-minutes-ago-similar-to-stack-exchange-site | 3 | // Thanks: https://stackoverflow.com/questions/3177836/how-to-format-time-since-xxx-e-g-4-minutes-ago-similar-to-stack-exchange-site |
4 | @Pipe({ name: 'myFromNow' }) | 4 | @Pipe({ name: 'myFromNow' }) |
5 | export class FromNowPipe implements PipeTransform { | 5 | export class FromNowPipe implements PipeTransform { |
6 | |||
7 | transform (arg: number | Date | string) { | 6 | transform (arg: number | Date | string) { |
8 | const argDate = new Date(arg) | 7 | const argDate = new Date(arg) |
9 | const seconds = Math.floor((Date.now() - argDate.getTime()) / 1000) | 8 | const seconds = Math.floor((Date.now() - argDate.getTime()) / 1000) |
10 | 9 | ||
11 | let interval = Math.round(seconds / 31536000) | 10 | let interval = Math.floor(seconds / 31536000) |
12 | if (interval > 1) return $localize`${interval} years ago` | 11 | if (interval > 1) return $localize`${interval} years ago` |
13 | if (interval === 1) return $localize`${interval} year ago` | 12 | if (interval === 1) return $localize`1 year ago` |
14 | 13 | ||
15 | interval = Math.round(seconds / 2592000) | 14 | interval = Math.floor(seconds / 2419200) |
15 | // 12 months = 360 days, but a year ~ 365 days | ||
16 | // Display "1 year ago" rather than "12 months ago" | ||
17 | if (interval >= 12) return $localize`1 year ago` | ||
16 | if (interval > 1) return $localize`${interval} months ago` | 18 | if (interval > 1) return $localize`${interval} months ago` |
17 | if (interval === 1) return $localize`${interval} month ago` | 19 | if (interval === 1) return $localize`1 month ago` |
18 | 20 | ||
19 | interval = Math.round(seconds / 604800) | 21 | interval = Math.floor(seconds / 604800) |
22 | // 4 weeks ~ 28 days, but our month is 30 days | ||
23 | // Display "1 month ago" rather than "4 weeks ago" | ||
24 | if (interval >= 4) return $localize`1 month ago` | ||
20 | if (interval > 1) return $localize`${interval} weeks ago` | 25 | if (interval > 1) return $localize`${interval} weeks ago` |
21 | if (interval === 1) return $localize`${interval} week ago` | 26 | if (interval === 1) return $localize`1 week ago` |
22 | 27 | ||
23 | interval = Math.round(seconds / 86400) | 28 | interval = Math.floor(seconds / 86400) |
24 | if (interval > 1) return $localize`${interval} days ago` | 29 | if (interval > 1) return $localize`${interval} days ago` |
25 | if (interval === 1) return $localize`${interval} day ago` | 30 | if (interval === 1) return $localize`1 day ago` |
26 | 31 | ||
27 | interval = Math.round(seconds / 3600) | 32 | interval = Math.floor(seconds / 3600) |
28 | if (interval > 1) return $localize`${interval} hours ago` | 33 | if (interval > 1) return $localize`${interval} hours ago` |
29 | if (interval === 1) return $localize`${interval} hour ago` | 34 | if (interval === 1) return $localize`1 hour ago` |
30 | 35 | ||
31 | interval = Math.round(seconds / 60) | 36 | interval = Math.floor(seconds / 60) |
32 | if (interval >= 1) return $localize`${interval} min ago` | 37 | if (interval >= 1) return $localize`${interval} min ago` |
33 | 38 | ||
34 | return $localize`just now` | 39 | return $localize`just now` |