aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app')
-rw-r--r--client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts3
-rw-r--r--client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts3
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-edit.component.ts11
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts10
-rw-r--r--client/src/app/+videos/+video-edit/video-add.component.html10
-rw-r--r--client/src/app/+videos/+video-edit/video-add.component.ts20
-rw-r--r--client/src/app/+videos/video-list/trending/video-trending-header.component.ts12
-rw-r--r--client/src/app/+videos/video-list/trending/video-trending.component.ts7
-rw-r--r--client/src/app/app.component.ts2
-rw-r--r--client/src/app/core/routing/redirect.service.ts35
-rw-r--r--client/src/app/core/server/server.service.ts25
-rw-r--r--client/src/app/core/theme/theme.service.ts14
-rw-r--r--client/src/app/shared/shared-main/angular/from-now.pipe.ts29
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'
5import { ComponentPagination, ConfirmService, hasMoreItems, Notifier } from '@app/core' 5import { ComponentPagination, ConfirmService, hasMoreItems, Notifier } from '@app/core'
6import { PluginService } from '@app/core/plugins/plugin.service' 6import { PluginService } from '@app/core/plugins/plugin.service'
7import { compareSemVer } from '@shared/core-utils/miscs/miscs' 7import { compareSemVer } from '@shared/core-utils/miscs/miscs'
8import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model' 8import { PeerTubePlugin, PluginType } from '@shared/models'
9import { 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'
4import { ActivatedRoute, Router } from '@angular/router' 4import { ActivatedRoute, Router } from '@angular/router'
5import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' 5import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service'
6import { ComponentPagination, ConfirmService, hasMoreItems, Notifier, PluginService } from '@app/core' 6import { ComponentPagination, ConfirmService, hasMoreItems, Notifier, PluginService } from '@app/core'
7import { PeerTubePluginIndex } from '@shared/models/plugins/peertube-plugin-index.model' 7import { PeerTubePluginIndex, PluginType } from '@shared/models'
8import { 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 {
21import { FormReactiveValidationMessages, FormValidatorService } from '@app/shared/shared-forms' 21import { FormReactiveValidationMessages, FormValidatorService } from '@app/shared/shared-forms'
22import { InstanceService } from '@app/shared/shared-instance' 22import { InstanceService } from '@app/shared/shared-instance'
23import { VideoCaptionEdit, VideoEdit, VideoService } from '@app/shared/shared-main' 23import { VideoCaptionEdit, VideoEdit, VideoService } from '@app/shared/shared-main'
24import { LiveVideo, ServerConfig, VideoConstant, VideoDetails, VideoPrivacy } from '@shared/models' 24import {
25import { 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'
26import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service' 33import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service'
27import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component' 34import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component'
28import { VideoEditType } from './video-edit.type' 35import { 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'
5import { FormValidatorService } from '@app/shared/shared-forms' 5import { FormValidatorService } from '@app/shared/shared-forms'
6import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' 6import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main'
7import { LoadingBarService } from '@ngx-loading-bar/core' 7import { LoadingBarService } from '@ngx-loading-bar/core'
8import { VideoPrivacy, VideoUpdate } from '@shared/models' 8import { ServerErrorCode, VideoPrivacy, VideoUpdate } from '@shared/models'
9import { hydrateFormFromVideo } from '../shared/video-edit-utils' 9import { hydrateFormFromVideo } from '../shared/video-edit-utils'
10import { VideoSend } from './video-send' 10import { 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 @@
1import { Component, HostListener, OnInit, ViewChild } from '@angular/core' 1import { Component, HostListener, OnInit, ViewChild } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router'
2import { AuthService, AuthUser, CanComponentDeactivate, ServerService } from '@app/core' 3import { AuthService, AuthUser, CanComponentDeactivate, ServerService } from '@app/core'
3import { ServerConfig } from '@shared/models' 4import { ServerConfig } from '@shared/models'
4import { VideoEditType } from './shared/video-edit.type' 5import { 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'
6export class RedirectService { 6export 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'
3import { HttpClient } from '@angular/common/http' 3import { HttpClient } from '@angular/common/http'
4import { Inject, Injectable, LOCALE_ID } from '@angular/core' 4import { Inject, Injectable, LOCALE_ID } from '@angular/core'
5import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers' 5import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers'
6import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
7import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n' 6import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n'
8import { SearchTargetType, ServerConfig, ServerStats, VideoConstant } from '@shared/models' 7import { SearchTargetType, ServerConfig, ServerStats, VideoConstant } from '@shared/models'
9import { environment } from '../../../environments/environment' 8import { 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' })
5export class FromNowPipe implements PipeTransform { 5export 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`