aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app')
-rw-r--r--client/src/app/+accounts/account-video-channels/account-video-channels.component.html2
-rw-r--r--client/src/app/+accounts/account-video-channels/account-video-channels.component.ts30
-rw-r--r--client/src/app/+my-account/my-account-history/my-account-history.component.html3
-rw-r--r--client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts2
-rw-r--r--client/src/app/app.component.ts1
-rw-r--r--client/src/app/modal/quick-settings-modal.component.html13
-rw-r--r--client/src/app/modal/quick-settings-modal.component.ts8
-rw-r--r--client/src/app/search/search.component.html2
-rw-r--r--client/src/app/search/search.component.ts13
-rw-r--r--client/src/app/shared/users/user.service.ts51
-rw-r--r--client/src/app/shared/video/abstract-video-list.html2
-rw-r--r--client/src/app/shared/video/abstract-video-list.ts69
-rw-r--r--client/src/app/shared/video/video.service.ts50
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.html8
-rw-r--r--client/src/app/videos/recommendations/recent-videos-recommendation.service.ts58
-rw-r--r--client/src/app/videos/recommendations/recommended-videos.component.html6
-rw-r--r--client/src/app/videos/recommendations/recommended-videos.component.ts26
-rw-r--r--client/src/app/videos/video-list/video-local.component.ts3
-rw-r--r--client/src/app/videos/video-list/video-most-liked.component.ts3
-rw-r--r--client/src/app/videos/video-list/video-overview.component.html6
-rw-r--r--client/src/app/videos/video-list/video-overview.component.ts25
-rw-r--r--client/src/app/videos/video-list/video-recently-added.component.ts3
-rw-r--r--client/src/app/videos/video-list/video-trending.component.ts3
23 files changed, 227 insertions, 160 deletions
diff --git a/client/src/app/+accounts/account-video-channels/account-video-channels.component.html b/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
index 73bac5f1d..5dbb341d2 100644
--- a/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
+++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
@@ -21,7 +21,7 @@
21 21
22 <my-video-miniature 22 <my-video-miniature
23 *ngFor="let video of getVideosOf(videoChannel)" 23 *ngFor="let video of getVideosOf(videoChannel)"
24 [video]="video" [user]="user" [displayVideoActions]="true" 24 [video]="video" [user]="userMiniature" [displayVideoActions]="true"
25 ></my-video-miniature> 25 ></my-video-miniature>
26 </div> 26 </div>
27 27
diff --git a/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts b/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
index 5572064c1..2e5c5aae2 100644
--- a/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
+++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
@@ -1,17 +1,17 @@
1import { from, Subject, Subscription } from 'rxjs'
2import { concatMap, map, switchMap, tap } from 'rxjs/operators'
1import { Component, OnDestroy, OnInit } from '@angular/core' 3import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute } from '@angular/router' 4import { UserService } from '@app/shared'
3import { Account } from '@app/shared/account/account.model' 5import { Account } from '@app/shared/account/account.model'
4import { AccountService } from '@app/shared/account/account.service' 6import { AccountService } from '@app/shared/account/account.service'
5import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' 7import { ScreenService } from '@app/shared/misc/screen.service'
6import { concatMap, map, switchMap, tap } from 'rxjs/operators' 8import { ComponentPagination, hasMoreItems } from '@app/shared/rest/component-pagination.model'
7import { from, Subject, Subscription } from 'rxjs'
8import { VideoChannel } from '@app/shared/video-channel/video-channel.model' 9import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
10import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
11import { VideoSortField } from '@app/shared/video/sort-field.type'
9import { Video } from '@app/shared/video/video.model' 12import { Video } from '@app/shared/video/video.model'
10import { AuthService } from '@app/core'
11import { VideoService } from '@app/shared/video/video.service' 13import { VideoService } from '@app/shared/video/video.service'
12import { VideoSortField } from '@app/shared/video/sort-field.type' 14import { User } from '@shared/models'
13import { ComponentPagination, hasMoreItems } from '@app/shared/rest/component-pagination.model'
14import { ScreenService } from '@app/shared/misc/screen.service'
15 15
16@Component({ 16@Component({
17 selector: 'my-account-video-channels', 17 selector: 'my-account-video-channels',
@@ -38,21 +38,18 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
38 38
39 onChannelDataSubject = new Subject<any>() 39 onChannelDataSubject = new Subject<any>()
40 40
41 userMiniature: User
42
41 private accountSub: Subscription 43 private accountSub: Subscription
42 44
43 constructor ( 45 constructor (
44 private route: ActivatedRoute,
45 private authService: AuthService,
46 private accountService: AccountService, 46 private accountService: AccountService,
47 private videoChannelService: VideoChannelService, 47 private videoChannelService: VideoChannelService,
48 private videoService: VideoService, 48 private videoService: VideoService,
49 private screenService: ScreenService 49 private screenService: ScreenService,
50 private userService: UserService
50 ) { } 51 ) { }
51 52
52 get user () {
53 return this.authService.getUser()
54 }
55
56 ngOnInit () { 53 ngOnInit () {
57 // Parent get the account for us 54 // Parent get the account for us
58 this.accountSub = this.accountService.accountLoaded 55 this.accountSub = this.accountService.accountLoaded
@@ -61,6 +58,9 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
61 58
62 this.loadMoreChannels() 59 this.loadMoreChannels()
63 }) 60 })
61
62 this.userService.getAnonymousOrLoggedUser()
63 .subscribe(user => this.userMiniature = user)
64 } 64 }
65 65
66 ngOnDestroy () { 66 ngOnDestroy () {
diff --git a/client/src/app/+my-account/my-account-history/my-account-history.component.html b/client/src/app/+my-account/my-account-history/my-account-history.component.html
index 6b94d5477..cfa5ca636 100644
--- a/client/src/app/+my-account/my-account-history/my-account-history.component.html
+++ b/client/src/app/+my-account/my-account-history/my-account-history.component.html
@@ -18,6 +18,7 @@
18 <div class="video" *ngFor="let video of videos"> 18 <div class="video" *ngFor="let video of videos">
19 <my-video-miniature 19 <my-video-miniature
20 [video]="video" [displayAsRow]="true" 20 [video]="video" [displayAsRow]="true"
21 (videoRemoved)="removeVideoFromArray(video)" (videoBlocked)="removeVideoFromArray(video)"></my-video-miniature> 21 (videoRemoved)="removeVideoFromArray(video)" (videoBlocked)="removeVideoFromArray(video)"
22 ></my-video-miniature>
22 </div> 23 </div>
23</div> 24</div>
diff --git a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
index 6df47d11c..5749701e8 100644
--- a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
+++ b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
@@ -77,7 +77,7 @@ export class VideoChannelVideosComponent extends AbstractVideoList implements On
77 const newPagination = immutableAssign(this.pagination, { currentPage: page }) 77 const newPagination = immutableAssign(this.pagination, { currentPage: page })
78 78
79 return this.videoService 79 return this.videoService
80 .getVideoChannelVideos(this.videoChannel, newPagination, this.sort) 80 .getVideoChannelVideos(this.videoChannel, newPagination, this.sort, this.nsfwPolicy)
81 .pipe( 81 .pipe(
82 tap(({ total }) => { 82 tap(({ total }) => {
83 this.titlePage = this.i18n(`{total, plural, =1 {Published 1 video} other {Published {{total}} videos}}`, { total }) 83 this.titlePage = this.i18n(`{total, plural, =1 {Published 1 video} other {Published {{total}} videos}}`, { total })
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts
index 5541f5558..c77dc97de 100644
--- a/client/src/app/app.component.ts
+++ b/client/src/app/app.component.ts
@@ -123,7 +123,6 @@ export class AppComponent implements OnInit, AfterViewInit {
123 const scrollEvent = eventsObs.pipe(filter((e: Event): e is Scroll => e instanceof Scroll)) 123 const scrollEvent = eventsObs.pipe(filter((e: Event): e is Scroll => e instanceof Scroll))
124 124
125 scrollEvent.subscribe(e => { 125 scrollEvent.subscribe(e => {
126 console.log(e)
127 if (e.position) { 126 if (e.position) {
128 return this.viewportScroller.scrollToPosition(e.position) 127 return this.viewportScroller.scrollToPosition(e.position)
129 } 128 }
diff --git a/client/src/app/modal/quick-settings-modal.component.html b/client/src/app/modal/quick-settings-modal.component.html
index e2ea51b92..188a51173 100644
--- a/client/src/app/modal/quick-settings-modal.component.html
+++ b/client/src/app/modal/quick-settings-modal.component.html
@@ -3,11 +3,15 @@
3 <h4 i18n class="modal-title">Settings</h4> 3 <h4 i18n class="modal-title">Settings</h4>
4 <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> 4 <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
5 </div> 5 </div>
6 6
7 <div class="modal-body"> 7 <div class="modal-body">
8 <div i18n class="mb-4 quick-settings-title">Display settings</div> 8 <div i18n class="mb-4 quick-settings-title">Display settings</div>
9 9
10 <my-account-video-settings *ngIf="!isUserLoggedIn()" [user]="user" [userInformationLoaded]="userInformationLoaded" [reactiveUpdate]="true" [notifyOnUpdate]="true"> 10 <my-account-video-settings
11 *ngIf="!isUserLoggedIn()"
12 [user]="user" [userInformationLoaded]="userInformationLoaded" [reactiveUpdate]="true" [notifyOnUpdate]="true"
13 >
14
11 <ng-container ngProjectAs="inner-title"> 15 <ng-container ngProjectAs="inner-title">
12 <div i18n class="mb-4 mt-4 quick-settings-title">Video settings</div> 16 <div i18n class="mb-4 mt-4 quick-settings-title">Video settings</div>
13 </ng-container> 17 </ng-container>
@@ -15,6 +19,9 @@
15 19
16 <div i18n class="mb-4 mt-4 quick-settings-title">Interface settings</div> 20 <div i18n class="mb-4 mt-4 quick-settings-title">Interface settings</div>
17 21
18 <my-account-interface-settings *ngIf="!isUserLoggedIn()" [user]="user" [userInformationLoaded]="userInformationLoaded" [reactiveUpdate]="true" [notifyOnUpdate]="true"></my-account-interface-settings> 22 <my-account-interface-settings
23 *ngIf="!isUserLoggedIn()"
24 [user]="user" [userInformationLoaded]="userInformationLoaded" [reactiveUpdate]="true" [notifyOnUpdate]="true"
25 ></my-account-interface-settings>
19 </div> 26 </div>
20</ng-template> 27</ng-template>
diff --git a/client/src/app/modal/quick-settings-modal.component.ts b/client/src/app/modal/quick-settings-modal.component.ts
index 41d6c9f47..155794d1b 100644
--- a/client/src/app/modal/quick-settings-modal.component.ts
+++ b/client/src/app/modal/quick-settings-modal.component.ts
@@ -32,9 +32,11 @@ export class QuickSettingsModalComponent extends FormReactive implements OnInit
32 32
33 ngOnInit () { 33 ngOnInit () {
34 this.user = this.userService.getAnonymousUser() 34 this.user = this.userService.getAnonymousUser()
35 this.localStorageService.watch().subscribe( 35 this.localStorageService.watch()
36 () => this.user = this.userService.getAnonymousUser() 36 .subscribe(
37 ) 37 () => this.user = this.userService.getAnonymousUser()
38 )
39
38 this.userInformationLoaded.next(true) 40 this.userInformationLoaded.next(true)
39 41
40 this.authService.loginChangedSource 42 this.authService.loginChangedSource
diff --git a/client/src/app/search/search.component.html b/client/src/app/search/search.component.html
index 6acdedf92..9bff024ad 100644
--- a/client/src/app/search/search.component.html
+++ b/client/src/app/search/search.component.html
@@ -53,7 +53,7 @@
53 53
54 <div *ngIf="isVideo(result)" class="entry video"> 54 <div *ngIf="isVideo(result)" class="entry video">
55 <my-video-miniature 55 <my-video-miniature
56 [video]="result" [user]="user" [displayAsRow]="true" [displayVideoActions]="!hideActions()" 56 [video]="result" [user]="userMiniature" [displayAsRow]="true" [displayVideoActions]="!hideActions()"
57 [displayOptions]="videoDisplayOptions" [useLazyLoadUrl]="advancedSearch.searchTarget === 'search-index'" 57 [displayOptions]="videoDisplayOptions" [useLazyLoadUrl]="advancedSearch.searchTarget === 'search-index'"
58 (videoBlocked)="removeVideoFromArray(result)" (videoRemoved)="removeVideoFromArray(result)" 58 (videoBlocked)="removeVideoFromArray(result)" (videoRemoved)="removeVideoFromArray(result)"
59 ></my-video-miniature> 59 ></my-video-miniature>
diff --git a/client/src/app/search/search.component.ts b/client/src/app/search/search.component.ts
index eea015c2e..bed5de79e 100644
--- a/client/src/app/search/search.component.ts
+++ b/client/src/app/search/search.component.ts
@@ -5,6 +5,7 @@ import { AuthService, Notifier, ServerService } from '@app/core'
5import { HooksService } from '@app/core/plugins/hooks.service' 5import { HooksService } from '@app/core/plugins/hooks.service'
6import { AdvancedSearch } from '@app/search/advanced-search.model' 6import { AdvancedSearch } from '@app/search/advanced-search.model'
7import { SearchService } from '@app/search/search.service' 7import { SearchService } from '@app/search/search.service'
8import { UserService } from '@app/shared'
8import { immutableAssign } from '@app/shared/misc/utils' 9import { immutableAssign } from '@app/shared/misc/utils'
9import { ComponentPagination } from '@app/shared/rest/component-pagination.model' 10import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
10import { VideoChannel } from '@app/shared/video-channel/video-channel.model' 11import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
@@ -12,7 +13,7 @@ import { MiniatureDisplayOptions } from '@app/shared/video/video-miniature.compo
12import { Video } from '@app/shared/video/video.model' 13import { Video } from '@app/shared/video/video.model'
13import { MetaService } from '@ngx-meta/core' 14import { MetaService } from '@ngx-meta/core'
14import { I18n } from '@ngx-translate/i18n-polyfill' 15import { I18n } from '@ngx-translate/i18n-polyfill'
15import { ServerConfig } from '@shared/models' 16import { ServerConfig, User } from '@shared/models'
16import { SearchTargetType } from '@shared/models/search/search-target-query.model' 17import { SearchTargetType } from '@shared/models/search/search-target-query.model'
17 18
18@Component({ 19@Component({
@@ -46,6 +47,8 @@ export class SearchComponent implements OnInit, OnDestroy {
46 errorMessage: string 47 errorMessage: string
47 serverConfig: ServerConfig 48 serverConfig: ServerConfig
48 49
50 userMiniature: User
51
49 private subActivatedRoute: Subscription 52 private subActivatedRoute: Subscription
50 private isInitialLoad = false // set to false to show the search filters on first arrival 53 private isInitialLoad = false // set to false to show the search filters on first arrival
51 private firstSearch = true 54 private firstSearch = true
@@ -62,14 +65,11 @@ export class SearchComponent implements OnInit, OnDestroy {
62 private notifier: Notifier, 65 private notifier: Notifier,
63 private searchService: SearchService, 66 private searchService: SearchService,
64 private authService: AuthService, 67 private authService: AuthService,
68 private userService: UserService,
65 private hooks: HooksService, 69 private hooks: HooksService,
66 private serverService: ServerService 70 private serverService: ServerService
67 ) { } 71 ) { }
68 72
69 get user () {
70 return this.authService.getUser()
71 }
72
73 ngOnInit () { 73 ngOnInit () {
74 this.serverService.getConfig() 74 this.serverService.getConfig()
75 .subscribe(config => this.serverConfig = config) 75 .subscribe(config => this.serverConfig = config)
@@ -103,6 +103,9 @@ export class SearchComponent implements OnInit, OnDestroy {
103 err => this.notifier.error(err.text) 103 err => this.notifier.error(err.text)
104 ) 104 )
105 105
106 this.userService.getAnonymousOrLoggedUser()
107 .subscribe(user => this.userMiniature = user)
108
106 this.hooks.runAction('action:search.init', 'search') 109 this.hooks.runAction('action:search.init', 'search')
107 } 110 }
108 111
diff --git a/client/src/app/shared/users/user.service.ts b/client/src/app/shared/users/user.service.ts
index 7c1ae5799..de1c8ec94 100644
--- a/client/src/app/shared/users/user.service.ts
+++ b/client/src/app/shared/users/user.service.ts
@@ -1,19 +1,20 @@
1import { from, Observable } from 'rxjs' 1import { has } from 'lodash-es'
2import { catchError, concatMap, map, shareReplay, toArray } from 'rxjs/operators' 2import { BytesPipe } from 'ngx-pipes'
3import { SortMeta } from 'primeng/api'
4import { from, Observable, of } from 'rxjs'
5import { catchError, concatMap, first, map, shareReplay, toArray, throttleTime, filter } from 'rxjs/operators'
3import { HttpClient, HttpParams } from '@angular/common/http' 6import { HttpClient, HttpParams } from '@angular/common/http'
4import { Injectable } from '@angular/core' 7import { Injectable } from '@angular/core'
5import { ResultList, User as UserServerModel, UserCreate, UserRole, UserUpdate, UserUpdateMe, UserVideoQuota } from '../../../../../shared' 8import { AuthService } from '@app/core/auth'
6import { environment } from '../../../environments/environment'
7import { RestExtractor, RestPagination, RestService } from '../rest'
8import { Avatar } from '../../../../../shared/models/avatars/avatar.model'
9import { SortMeta } from 'primeng/api'
10import { BytesPipe } from 'ngx-pipes'
11import { I18n } from '@ngx-translate/i18n-polyfill' 9import { I18n } from '@ngx-translate/i18n-polyfill'
12import { UserRegister } from '@shared/models/users/user-register.model' 10import { UserRegister } from '@shared/models/users/user-register.model'
13import { User } from './user.model'
14import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' 11import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type'
15import { has } from 'lodash-es' 12import { ResultList, User as UserServerModel, UserCreate, UserRole, UserUpdate, UserUpdateMe, UserVideoQuota } from '../../../../../shared'
13import { Avatar } from '../../../../../shared/models/avatars/avatar.model'
14import { environment } from '../../../environments/environment'
16import { LocalStorageService, SessionStorageService } from '../misc/storage.service' 15import { LocalStorageService, SessionStorageService } from '../misc/storage.service'
16import { RestExtractor, RestPagination, RestService } from '../rest'
17import { User } from './user.model'
17 18
18@Injectable() 19@Injectable()
19export class UserService { 20export class UserService {
@@ -25,6 +26,7 @@ export class UserService {
25 26
26 constructor ( 27 constructor (
27 private authHttp: HttpClient, 28 private authHttp: HttpClient,
29 private authService: AuthService,
28 private restExtractor: RestExtractor, 30 private restExtractor: RestExtractor,
29 private restService: RestService, 31 private restService: RestService,
30 private localStorageService: LocalStorageService, 32 private localStorageService: LocalStorageService,
@@ -94,6 +96,21 @@ export class UserService {
94 } 96 }
95 } 97 }
96 98
99 listenAnonymousUpdate () {
100 return this.localStorageService.watch([
101 User.KEYS.NSFW_POLICY,
102 User.KEYS.WEBTORRENT_ENABLED,
103 User.KEYS.AUTO_PLAY_VIDEO,
104 User.KEYS.AUTO_PLAY_VIDEO_PLAYLIST,
105 User.KEYS.THEME,
106 User.KEYS.VIDEO_LANGUAGES
107 ]).pipe(
108 throttleTime(200),
109 filter(() => this.authService.isLoggedIn() !== true),
110 map(() => this.getAnonymousUser())
111 )
112 }
113
97 deleteMe () { 114 deleteMe () {
98 const url = UserService.BASE_USERS_URL + 'me' 115 const url = UserService.BASE_USERS_URL + 'me'
99 116
@@ -241,7 +258,7 @@ export class UserService {
241 } 258 }
242 259
243 getAnonymousUser () { 260 getAnonymousUser () {
244 let videoLanguages 261 let videoLanguages: string[]
245 262
246 try { 263 try {
247 videoLanguages = JSON.parse(this.localStorageService.getItem(User.KEYS.VIDEO_LANGUAGES)) 264 videoLanguages = JSON.parse(this.localStorageService.getItem(User.KEYS.VIDEO_LANGUAGES))
@@ -313,6 +330,18 @@ export class UserService {
313 ) 330 )
314 } 331 }
315 332
333 getAnonymousOrLoggedUser () {
334 if (!this.authService.isLoggedIn()) {
335 return of(this.getAnonymousUser())
336 }
337
338 return this.authService.userInformationLoaded
339 .pipe(
340 first(),
341 map(() => this.authService.getUser())
342 )
343 }
344
316 private formatUser (user: UserServerModel) { 345 private formatUser (user: UserServerModel) {
317 let videoQuota 346 let videoQuota
318 if (user.videoQuota === -1) { 347 if (user.videoQuota === -1) {
diff --git a/client/src/app/shared/video/abstract-video-list.html b/client/src/app/shared/video/abstract-video-list.html
index 548370843..1e919ee72 100644
--- a/client/src/app/shared/video/abstract-video-list.html
+++ b/client/src/app/shared/video/abstract-video-list.html
@@ -38,7 +38,7 @@
38 <div class="video-wrapper"> 38 <div class="video-wrapper">
39 <my-video-miniature 39 <my-video-miniature
40 [fitWidth]="true" 40 [fitWidth]="true"
41 [video]="video" [user]="user" [ownerDisplayType]="ownerDisplayType" 41 [video]="video" [user]="userMiniature" [ownerDisplayType]="ownerDisplayType"
42 [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions" 42 [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions"
43 (videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)" 43 (videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
44 > 44 >
diff --git a/client/src/app/shared/video/abstract-video-list.ts b/client/src/app/shared/video/abstract-video-list.ts
index 76aa683fc..0bc339ff6 100644
--- a/client/src/app/shared/video/abstract-video-list.ts
+++ b/client/src/app/shared/video/abstract-video-list.ts
@@ -1,22 +1,23 @@
1import { debounceTime, first, tap, throttleTime } from 'rxjs/operators' 1import { fromEvent, Observable, of, Subject, Subscription } from 'rxjs'
2import { debounceTime, tap, throttleTime, switchMap } from 'rxjs/operators'
2import { OnDestroy, OnInit } from '@angular/core' 3import { OnDestroy, OnInit } from '@angular/core'
3import { ActivatedRoute, Router } from '@angular/router' 4import { ActivatedRoute, Router } from '@angular/router'
4import { fromEvent, Observable, of, Subject, Subscription } from 'rxjs'
5import { AuthService } from '../../core/auth'
6import { ComponentPaginationLight } from '../rest/component-pagination.model'
7import { VideoSortField } from './sort-field.type'
8import { Video } from './video.model'
9import { ScreenService } from '@app/shared/misc/screen.service'
10import { MiniatureDisplayOptions, OwnerDisplayType } from '@app/shared/video/video-miniature.component'
11import { Syndication } from '@app/shared/video/syndication.model'
12import { Notifier, ServerService } from '@app/core' 5import { Notifier, ServerService } from '@app/core'
13import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' 6import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
7import { GlobalIconName } from '@app/shared/images/global-icon.component'
8import { ScreenService } from '@app/shared/misc/screen.service'
9import { Syndication } from '@app/shared/video/syndication.model'
10import { MiniatureDisplayOptions, OwnerDisplayType } from '@app/shared/video/video-miniature.component'
14import { I18n } from '@ngx-translate/i18n-polyfill' 11import { I18n } from '@ngx-translate/i18n-polyfill'
15import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date' 12import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date'
16import { ServerConfig } from '@shared/models' 13import { ServerConfig } from '@shared/models'
17import { GlobalIconName } from '@app/shared/images/global-icon.component' 14import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type'
18import { UserService, User } from '../users' 15import { AuthService } from '../../core/auth'
19import { LocalStorageService } from '../misc/storage.service' 16import { LocalStorageService } from '../misc/storage.service'
17import { ComponentPaginationLight } from '../rest/component-pagination.model'
18import { User, UserService } from '../users'
19import { VideoSortField } from './sort-field.type'
20import { Video } from './video.model'
20 21
21enum GroupDate { 22enum GroupDate {
22 UNKNOWN = 0, 23 UNKNOWN = 0,
@@ -34,14 +35,15 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
34 } 35 }
35 sort: VideoSortField = '-publishedAt' 36 sort: VideoSortField = '-publishedAt'
36 37
37 categoryOneOf?: number 38 categoryOneOf?: number[]
38 languageOneOf?: string[] 39 languageOneOf?: string[]
40 nsfwPolicy?: NSFWPolicyType
39 defaultSort: VideoSortField = '-publishedAt' 41 defaultSort: VideoSortField = '-publishedAt'
40 42
41 syndicationItems: Syndication[] = [] 43 syndicationItems: Syndication[] = []
42 44
43 loadOnInit = true 45 loadOnInit = true
44 useUserVideoLanguagePreferences = false 46 useUserVideoPreferences = false
45 ownerDisplayType: OwnerDisplayType = 'account' 47 ownerDisplayType: OwnerDisplayType = 'account'
46 displayModerationBlock = false 48 displayModerationBlock = false
47 titleTooltip: string 49 titleTooltip: string
@@ -71,6 +73,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
71 73
72 onDataSubject = new Subject<any[]>() 74 onDataSubject = new Subject<any[]>()
73 75
76 userMiniature: User
77
74 protected serverConfig: ServerConfig 78 protected serverConfig: ServerConfig
75 79
76 protected abstract notifier: Notifier 80 protected abstract notifier: Notifier
@@ -96,10 +100,6 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
96 100
97 abstract generateSyndicationList (): void 101 abstract generateSyndicationList (): void
98 102
99 get user () {
100 return this.authService.getUser()
101 }
102
103 ngOnInit () { 103 ngOnInit () {
104 this.serverConfig = this.serverService.getTmpConfig() 104 this.serverConfig = this.serverService.getTmpConfig()
105 this.serverService.getConfig() 105 this.serverService.getConfig()
@@ -124,21 +124,17 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
124 124
125 this.calcPageSizes() 125 this.calcPageSizes()
126 126
127 const loadUserObservable = this.loadUserVideoLanguagesIfNeeded() 127 const loadUserObservable = this.loadUserAndSettings()
128 128
129 if (this.loadOnInit === true) { 129 if (this.loadOnInit === true) {
130 loadUserObservable.subscribe(() => this.loadMoreVideos()) 130 loadUserObservable.subscribe(() => this.loadMoreVideos())
131 } 131 }
132 132
133 this.storageService.watch([ 133 this.userService.listenAnonymousUpdate()
134 User.KEYS.NSFW_POLICY, 134 .pipe(switchMap(() => this.loadUserAndSettings()))
135 User.KEYS.VIDEO_LANGUAGES 135 .subscribe(() => {
136 ]).pipe(throttleTime(200)).subscribe(
137 () => {
138 this.loadUserVideoLanguagesIfNeeded()
139 if (this.hasDoneFirstQuery) this.reloadVideos() 136 if (this.hasDoneFirstQuery) this.reloadVideos()
140 } 137 })
141 )
142 138
143 // Display avatar in mobile view 139 // Display avatar in mobile view
144 if (this.screenService.isInMobileView()) { 140 if (this.screenService.isInMobileView()) {
@@ -298,20 +294,15 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
298 this.router.navigate([ path ], { queryParams, replaceUrl: true, queryParamsHandling: 'merge' }) 294 this.router.navigate([ path ], { queryParams, replaceUrl: true, queryParamsHandling: 'merge' })
299 } 295 }
300 296
301 private loadUserVideoLanguagesIfNeeded () { 297 private loadUserAndSettings () {
302 if (!this.useUserVideoLanguagePreferences) { 298 return this.userService.getAnonymousOrLoggedUser()
303 return of(true) 299 .pipe(tap(user => {
304 } 300 this.userMiniature = user
305 301
306 if (!this.authService.isLoggedIn()) { 302 if (!this.useUserVideoPreferences) return
307 this.languageOneOf = this.userService.getAnonymousUser().videoLanguages
308 return of(true)
309 }
310 303
311 return this.authService.userInformationLoaded 304 this.languageOneOf = user.videoLanguages
312 .pipe( 305 this.nsfwPolicy = user.nsfwPolicy
313 first(), 306 }))
314 tap(() => this.languageOneOf = this.user.videoLanguages)
315 )
316 } 307 }
317} 308}
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts
index 3aaf14990..d66a1f809 100644
--- a/client/src/app/shared/video/video.service.ts
+++ b/client/src/app/shared/video/video.service.ts
@@ -39,8 +39,9 @@ export interface VideosProvider {
39 videoPagination: ComponentPaginationLight, 39 videoPagination: ComponentPaginationLight,
40 sort: VideoSortField, 40 sort: VideoSortField,
41 filter?: VideoFilter, 41 filter?: VideoFilter,
42 categoryOneOf?: number, 42 categoryOneOf?: number[],
43 languageOneOf?: string[] 43 languageOneOf?: string[]
44 nsfwPolicy: NSFWPolicyType
44 }): Observable<ResultList<Video>> 45 }): Observable<ResultList<Video>>
45} 46}
46 47
@@ -161,13 +162,18 @@ export class VideoService implements VideosProvider {
161 getVideoChannelVideos ( 162 getVideoChannelVideos (
162 videoChannel: VideoChannel, 163 videoChannel: VideoChannel,
163 videoPagination: ComponentPaginationLight, 164 videoPagination: ComponentPaginationLight,
164 sort: VideoSortField 165 sort: VideoSortField,
166 nsfwPolicy?: NSFWPolicyType
165 ): Observable<ResultList<Video>> { 167 ): Observable<ResultList<Video>> {
166 const pagination = this.restService.componentPaginationToRestPagination(videoPagination) 168 const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
167 169
168 let params = new HttpParams() 170 let params = new HttpParams()
169 params = this.restService.addRestGetParams(params, pagination, sort) 171 params = this.restService.addRestGetParams(params, pagination, sort)
170 172
173 if (nsfwPolicy) {
174 params = params.set('nsfw', this.nsfwPolicyToParam(nsfwPolicy))
175 }
176
171 return this.authHttp 177 return this.authHttp
172 .get<ResultList<Video>>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.nameWithHost + '/videos', { params }) 178 .get<ResultList<Video>>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.nameWithHost + '/videos', { params })
173 .pipe( 179 .pipe(
@@ -201,12 +207,12 @@ export class VideoService implements VideosProvider {
201 videoPagination: ComponentPaginationLight, 207 videoPagination: ComponentPaginationLight,
202 sort: VideoSortField, 208 sort: VideoSortField,
203 filter?: VideoFilter, 209 filter?: VideoFilter,
204 categoryOneOf?: number, 210 categoryOneOf?: number[],
205 languageOneOf?: string[], 211 languageOneOf?: string[],
206 skipCount?: boolean, 212 skipCount?: boolean,
207 nsfw?: boolean 213 nsfwPolicy?: NSFWPolicyType
208 }): Observable<ResultList<Video>> { 214 }): Observable<ResultList<Video>> {
209 const { videoPagination, sort, filter, categoryOneOf, languageOneOf, skipCount, nsfw } = parameters 215 const { videoPagination, sort, filter, categoryOneOf, languageOneOf, skipCount, nsfwPolicy } = parameters
210 216
211 const pagination = this.restService.componentPaginationToRestPagination(videoPagination) 217 const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
212 218
@@ -214,16 +220,10 @@ export class VideoService implements VideosProvider {
214 params = this.restService.addRestGetParams(params, pagination, sort) 220 params = this.restService.addRestGetParams(params, pagination, sort)
215 221
216 if (filter) params = params.set('filter', filter) 222 if (filter) params = params.set('filter', filter)
217 if (categoryOneOf) params = params.set('categoryOneOf', categoryOneOf + '')
218 if (skipCount) params = params.set('skipCount', skipCount + '') 223 if (skipCount) params = params.set('skipCount', skipCount + '')
219 224
220 if (nsfw) { 225 if (nsfwPolicy) {
221 params = params.set('nsfw', nsfw + '') 226 params = params.set('nsfw', this.nsfwPolicyToParam(nsfwPolicy))
222 } else {
223 const nsfwPolicy = this.authService.isLoggedIn()
224 ? this.authService.getUser().nsfwPolicy
225 : this.userService.getAnonymousUser().nsfwPolicy
226 if (this.nsfwPolicyToFilter(nsfwPolicy)) params.set('nsfw', 'false')
227 } 227 }
228 228
229 if (languageOneOf) { 229 if (languageOneOf) {
@@ -232,6 +232,12 @@ export class VideoService implements VideosProvider {
232 } 232 }
233 } 233 }
234 234
235 if (categoryOneOf) {
236 for (const c of categoryOneOf) {
237 params = params.append('categoryOneOf[]', c + '')
238 }
239 }
240
235 return this.authHttp 241 return this.authHttp
236 .get<ResultList<Video>>(VideoService.BASE_VIDEO_URL, { params }) 242 .get<ResultList<Video>>(VideoService.BASE_VIDEO_URL, { params })
237 .pipe( 243 .pipe(
@@ -268,12 +274,16 @@ export class VideoService implements VideosProvider {
268 return feeds 274 return feeds
269 } 275 }
270 276
271 getVideoFeedUrls (sort: VideoSortField, filter?: VideoFilter, categoryOneOf?: number) { 277 getVideoFeedUrls (sort: VideoSortField, filter?: VideoFilter, categoryOneOf?: number[]) {
272 let params = this.restService.addRestGetParams(new HttpParams(), undefined, sort) 278 let params = this.restService.addRestGetParams(new HttpParams(), undefined, sort)
273 279
274 if (filter) params = params.set('filter', filter) 280 if (filter) params = params.set('filter', filter)
275 281
276 if (categoryOneOf) params = params.set('categoryOneOf', categoryOneOf + '') 282 if (categoryOneOf) {
283 for (const c of categoryOneOf) {
284 params = params.append('categoryOneOf[]', c + '')
285 }
286 }
277 287
278 return this.buildBaseFeedUrls(params) 288 return this.buildBaseFeedUrls(params)
279 } 289 }
@@ -377,6 +387,12 @@ export class VideoService implements VideosProvider {
377 return base.filter(o => !!privacies.find(p => p.id === o.id)) 387 return base.filter(o => !!privacies.find(p => p.id === o.id))
378 } 388 }
379 389
390 nsfwPolicyToParam (nsfwPolicy: NSFWPolicyType) {
391 return nsfwPolicy === 'do_not_list'
392 ? 'false'
393 : 'both'
394 }
395
380 private setVideoRate (id: number, rateType: UserVideoRateType) { 396 private setVideoRate (id: number, rateType: UserVideoRateType) {
381 const url = VideoService.BASE_VIDEO_URL + id + '/rate' 397 const url = VideoService.BASE_VIDEO_URL + id + '/rate'
382 const body: UserVideoRateUpdate = { 398 const body: UserVideoRateUpdate = {
@@ -390,8 +406,4 @@ export class VideoService implements VideosProvider {
390 catchError(err => this.restExtractor.handleError(err)) 406 catchError(err => this.restExtractor.handleError(err))
391 ) 407 )
392 } 408 }
393
394 private nsfwPolicyToFilter (policy: NSFWPolicyType) {
395 return policy === 'do_not_list'
396 }
397} 409}
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html
index 589aba603..89e696fe9 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.html
+++ b/client/src/app/videos/+video-watch/video-watch.component.html
@@ -248,10 +248,10 @@
248 </div> 248 </div>
249 249
250 <my-recommended-videos 250 <my-recommended-videos
251 [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }" 251 [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }"
252 [user]="user" 252 [user]="user"
253 [playlist]="playlist" 253 [playlist]="playlist"
254 (gotRecommendations)="onRecommendations($event)" 254 (gotRecommendations)="onRecommendations($event)"
255 ></my-recommended-videos> 255 ></my-recommended-videos>
256 </div> 256 </div>
257 257
diff --git a/client/src/app/videos/recommendations/recent-videos-recommendation.service.ts b/client/src/app/videos/recommendations/recent-videos-recommendation.service.ts
index f06c35f9a..0abf938b7 100644
--- a/client/src/app/videos/recommendations/recent-videos-recommendation.service.ts
+++ b/client/src/app/videos/recommendations/recent-videos-recommendation.service.ts
@@ -1,15 +1,15 @@
1import { Injectable, OnInit } from '@angular/core'
2import { RecommendationService } from '@app/videos/recommendations/recommendations.service'
3import { Video } from '@app/shared/video/video.model'
4import { RecommendationInfo } from '@app/shared/video/recommendation-info.model'
5import { VideoService } from '@app/shared/video/video.service'
6import { map, switchMap } from 'rxjs/operators'
7import { Observable, of } from 'rxjs' 1import { Observable, of } from 'rxjs'
8import { SearchService } from '@app/search/search.service' 2import { map, switchMap } from 'rxjs/operators'
9import { AdvancedSearch } from '@app/search/advanced-search.model' 3import { Injectable } from '@angular/core'
10import { ServerService } from '@app/core' 4import { ServerService } from '@app/core'
5import { AdvancedSearch } from '@app/search/advanced-search.model'
6import { SearchService } from '@app/search/search.service'
7import { UserService } from '@app/shared'
8import { RecommendationInfo } from '@app/shared/video/recommendation-info.model'
9import { Video } from '@app/shared/video/video.model'
10import { VideoService } from '@app/shared/video/video.service'
11import { RecommendationService } from '@app/videos/recommendations/recommendations.service'
11import { ServerConfig } from '@shared/models' 12import { ServerConfig } from '@shared/models'
12import { truncate } from 'lodash'
13 13
14/** 14/**
15 * Provides "recommendations" by providing the most recently uploaded videos. 15 * Provides "recommendations" by providing the most recently uploaded videos.
@@ -23,13 +23,14 @@ export class RecentVideosRecommendationService implements RecommendationService
23 constructor ( 23 constructor (
24 private videos: VideoService, 24 private videos: VideoService,
25 private searchService: SearchService, 25 private searchService: SearchService,
26 private userService: UserService,
26 private serverService: ServerService 27 private serverService: ServerService
27 ) { 28 ) {
28 this.config = this.serverService.getTmpConfig() 29 this.config = this.serverService.getTmpConfig()
29 30
30 this.serverService.getConfig() 31 this.serverService.getConfig()
31 .subscribe(config => this.config = config) 32 .subscribe(config => this.config = config)
32 } 33 }
33 34
34 getRecommendations (recommendation: RecommendationInfo): Observable<Video[]> { 35 getRecommendations (recommendation: RecommendationInfo): Observable<Video[]> {
35 return this.fetchPage(1, recommendation) 36 return this.fetchPage(1, recommendation)
@@ -55,20 +56,29 @@ export class RecentVideosRecommendationService implements RecommendationService
55 return defaultSubscription 56 return defaultSubscription
56 } 57 }
57 58
58 const params = { 59 return this.userService.getAnonymousOrLoggedUser()
59 search: '', 60 .pipe(
60 componentPagination: pagination, 61 map(user => {
61 advancedSearch: new AdvancedSearch({ tagsOneOf: recommendation.tags.join(','), sort: '-createdAt', searchTarget: 'local' }) 62 return {
62 } 63 search: '',
63 64 componentPagination: pagination,
64 return this.searchService.searchVideos(params) 65 advancedSearch: new AdvancedSearch({
65 .pipe( 66 tagsOneOf: recommendation.tags.join(','),
66 map(v => v.data), 67 sort: '-createdAt',
67 switchMap(videos => { 68 searchTarget: 'local',
68 if (videos.length <= 1) return defaultSubscription 69 nsfw: user.nsfwPolicy
70 ? this.videos.nsfwPolicyToParam(user.nsfwPolicy)
71 : undefined
72 })
73 }
74 }),
75 switchMap(params => this.searchService.searchVideos(params)),
76 map(v => v.data),
77 switchMap(videos => {
78 if (videos.length <= 1) return defaultSubscription
69 79
70 return of(videos) 80 return of(videos)
71 }) 81 })
72 ) 82 )
73 } 83 }
74} 84}
diff --git a/client/src/app/videos/recommendations/recommended-videos.component.html b/client/src/app/videos/recommendations/recommended-videos.component.html
index 17e19c083..0467cabf5 100644
--- a/client/src/app/videos/recommendations/recommended-videos.component.html
+++ b/client/src/app/videos/recommendations/recommended-videos.component.html
@@ -13,11 +13,11 @@
13 </div> 13 </div>
14 14
15 <ng-container *ngFor="let video of (videos$ | async); let i = index; let length = count"> 15 <ng-container *ngFor="let video of (videos$ | async); let i = index; let length = count">
16 <my-video-miniature 16 <my-video-miniature
17 [displayOptions]="displayOptions" [video]="video" [user]="user" 17 [displayOptions]="displayOptions" [video]="video" [user]="userMiniature"
18 (videoBlocked)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()"> 18 (videoBlocked)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()">
19 </my-video-miniature> 19 </my-video-miniature>
20 20
21 <hr *ngIf="!playlist && i == 0 && length > 1" /> 21 <hr *ngIf="!playlist && i == 0 && length > 1" />
22 </ng-container> 22 </ng-container>
23 </ng-container> 23 </ng-container>
diff --git a/client/src/app/videos/recommendations/recommended-videos.component.ts b/client/src/app/videos/recommendations/recommended-videos.component.ts
index d4a5df19a..a6f3bce3d 100644
--- a/client/src/app/videos/recommendations/recommended-videos.component.ts
+++ b/client/src/app/videos/recommendations/recommended-videos.component.ts
@@ -1,24 +1,23 @@
1import { Component, Input, Output, OnChanges, EventEmitter } from '@angular/core'
2import { Observable } from 'rxjs' 1import { Observable } from 'rxjs'
3import { Video } from '@app/shared/video/video.model' 2import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'
3import { AuthService, Notifier } from '@app/core'
4import { User } from '@app/shared'
5import { SessionStorageService } from '@app/shared/misc/storage.service'
6import { UserService } from '@app/shared/users/user.service'
4import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' 7import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
5import { RecommendationInfo } from '@app/shared/video/recommendation-info.model' 8import { RecommendationInfo } from '@app/shared/video/recommendation-info.model'
9import { MiniatureDisplayOptions } from '@app/shared/video/video-miniature.component'
10import { Video } from '@app/shared/video/video.model'
6import { RecommendedVideosStore } from '@app/videos/recommendations/recommended-videos.store' 11import { RecommendedVideosStore } from '@app/videos/recommendations/recommended-videos.store'
7import { User } from '@app/shared'
8import { AuthService, Notifier } from '@app/core'
9import { UserService } from '@app/shared/users/user.service'
10import { I18n } from '@ngx-translate/i18n-polyfill' 12import { I18n } from '@ngx-translate/i18n-polyfill'
11import { SessionStorageService } from '@app/shared/misc/storage.service'
12import { MiniatureDisplayOptions } from '@app/shared/video/video-miniature.component'
13 13
14@Component({ 14@Component({
15 selector: 'my-recommended-videos', 15 selector: 'my-recommended-videos',
16 templateUrl: './recommended-videos.component.html', 16 templateUrl: './recommended-videos.component.html',
17 styleUrls: [ './recommended-videos.component.scss' ] 17 styleUrls: [ './recommended-videos.component.scss' ]
18}) 18})
19export class RecommendedVideosComponent implements OnChanges { 19export class RecommendedVideosComponent implements OnInit, OnChanges {
20 @Input() inputRecommendation: RecommendationInfo 20 @Input() inputRecommendation: RecommendationInfo
21 @Input() user: User
22 @Input() playlist: VideoPlaylist 21 @Input() playlist: VideoPlaylist
23 @Output() gotRecommendations = new EventEmitter<Video[]>() 22 @Output() gotRecommendations = new EventEmitter<Video[]>()
24 23
@@ -32,6 +31,8 @@ export class RecommendedVideosComponent implements OnChanges {
32 avatar: true 31 avatar: true
33 } 32 }
34 33
34 userMiniature: User
35
35 readonly hasVideos$: Observable<boolean> 36 readonly hasVideos$: Observable<boolean>
36 readonly videos$: Observable<Video[]> 37 readonly videos$: Observable<Video[]>
37 38
@@ -59,7 +60,12 @@ export class RecommendedVideosComponent implements OnChanges {
59 this.autoPlayNextVideoTooltip = this.i18n('When active, the next video is automatically played after the current one.') 60 this.autoPlayNextVideoTooltip = this.i18n('When active, the next video is automatically played after the current one.')
60 } 61 }
61 62
62 public ngOnChanges (): void { 63 ngOnInit () {
64 this.userService.getAnonymousOrLoggedUser()
65 .subscribe(user => this.userMiniature = user)
66 }
67
68 ngOnChanges () {
63 if (this.inputRecommendation) { 69 if (this.inputRecommendation) {
64 this.store.requestNewRecommendations(this.inputRecommendation) 70 this.store.requestNewRecommendations(this.inputRecommendation)
65 } 71 }
diff --git a/client/src/app/videos/video-list/video-local.component.ts b/client/src/app/videos/video-list/video-local.component.ts
index 757b0e498..960523cd7 100644
--- a/client/src/app/videos/video-list/video-local.component.ts
+++ b/client/src/app/videos/video-list/video-local.component.ts
@@ -24,7 +24,7 @@ export class VideoLocalComponent extends AbstractVideoList implements OnInit, On
24 sort = '-publishedAt' as VideoSortField 24 sort = '-publishedAt' as VideoSortField
25 filter: VideoFilter = 'local' 25 filter: VideoFilter = 'local'
26 26
27 useUserVideoLanguagePreferences = true 27 useUserVideoPreferences = true
28 28
29 constructor ( 29 constructor (
30 protected i18n: I18n, 30 protected i18n: I18n,
@@ -67,6 +67,7 @@ export class VideoLocalComponent extends AbstractVideoList implements OnInit, On
67 filter: this.filter, 67 filter: this.filter,
68 categoryOneOf: this.categoryOneOf, 68 categoryOneOf: this.categoryOneOf,
69 languageOneOf: this.languageOneOf, 69 languageOneOf: this.languageOneOf,
70 nsfwPolicy: this.nsfwPolicy,
70 skipCount: true 71 skipCount: true
71 } 72 }
72 73
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 b69fad05f..cc91a2330 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
@@ -21,7 +21,7 @@ export class VideoMostLikedComponent extends AbstractVideoList implements OnInit
21 titlePage: string 21 titlePage: string
22 defaultSort: VideoSortField = '-likes' 22 defaultSort: VideoSortField = '-likes'
23 23
24 useUserVideoLanguagePreferences = true 24 useUserVideoPreferences = true
25 25
26 constructor ( 26 constructor (
27 protected i18n: I18n, 27 protected i18n: I18n,
@@ -55,6 +55,7 @@ export class VideoMostLikedComponent extends AbstractVideoList implements OnInit
55 sort: this.sort, 55 sort: this.sort,
56 categoryOneOf: this.categoryOneOf, 56 categoryOneOf: this.categoryOneOf,
57 languageOneOf: this.languageOneOf, 57 languageOneOf: this.languageOneOf,
58 nsfwPolicy: this.nsfwPolicy,
58 skipCount: true 59 skipCount: true
59 } 60 }
60 61
diff --git a/client/src/app/videos/video-list/video-overview.component.html b/client/src/app/videos/video-list/video-overview.component.html
index 19d03b5c5..6de2fc292 100644
--- a/client/src/app/videos/video-list/video-overview.component.html
+++ b/client/src/app/videos/video-list/video-overview.component.html
@@ -14,7 +14,7 @@
14 </h1> 14 </h1>
15 15
16 <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)"> 16 <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)">
17 <my-video-miniature [video]="video" [fitWidth]="true" [user]="user" [displayVideoActions]="false"> 17 <my-video-miniature [video]="video" [fitWidth]="true" [user]="userMiniature" [displayVideoActions]="false">
18 </my-video-miniature> 18 </my-video-miniature>
19 </div> 19 </div>
20 </div> 20 </div>
@@ -25,7 +25,7 @@
25 </h2> 25 </h2>
26 26
27 <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)"> 27 <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)">
28 <my-video-miniature [video]="video" [fitWidth]="true" [user]="user" [displayVideoActions]="false"> 28 <my-video-miniature [video]="video" [fitWidth]="true" [user]="userMiniature" [displayVideoActions]="false">
29 </my-video-miniature> 29 </my-video-miniature>
30 </div> 30 </div>
31 </div> 31 </div>
@@ -40,7 +40,7 @@
40 </div> 40 </div>
41 41
42 <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)"> 42 <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)">
43 <my-video-miniature [video]="video" [fitWidth]="true" [user]="user" [displayVideoActions]="false"> 43 <my-video-miniature [video]="video" [fitWidth]="true" [user]="userMiniature" [displayVideoActions]="false">
44 </my-video-miniature> 44 </my-video-miniature>
45 </div> 45 </div>
46 </div> 46 </div>
diff --git a/client/src/app/videos/video-list/video-overview.component.ts b/client/src/app/videos/video-list/video-overview.component.ts
index 101073949..8ff8400db 100644
--- a/client/src/app/videos/video-list/video-overview.component.ts
+++ b/client/src/app/videos/video-list/video-overview.component.ts
@@ -1,11 +1,11 @@
1import { Subject } from 'rxjs'
1import { Component, OnInit } from '@angular/core' 2import { Component, OnInit } from '@angular/core'
2import { AuthService, Notifier } from '@app/core' 3import { Notifier } from '@app/core'
3import { I18n } from '@ngx-translate/i18n-polyfill' 4import { User, UserService } from '@app/shared'
4import { VideosOverview } from '@app/shared/overview/videos-overview.model' 5import { ScreenService } from '@app/shared/misc/screen.service'
5import { OverviewService } from '@app/shared/overview' 6import { OverviewService } from '@app/shared/overview'
7import { VideosOverview } from '@app/shared/overview/videos-overview.model'
6import { Video } from '@app/shared/video/video.model' 8import { Video } from '@app/shared/video/video.model'
7import { ScreenService } from '@app/shared/misc/screen.service'
8import { Subject } from 'rxjs'
9 9
10@Component({ 10@Component({
11 selector: 'my-video-overview', 11 selector: 'my-video-overview',
@@ -18,6 +18,8 @@ export class VideoOverviewComponent implements OnInit {
18 overviews: VideosOverview[] = [] 18 overviews: VideosOverview[] = []
19 notResults = false 19 notResults = false
20 20
21 userMiniature: User
22
21 private loaded = false 23 private loaded = false
22 private currentPage = 1 24 private currentPage = 1
23 private maxPage = 20 25 private maxPage = 20
@@ -25,19 +27,20 @@ export class VideoOverviewComponent implements OnInit {
25 private isLoading = false 27 private isLoading = false
26 28
27 constructor ( 29 constructor (
28 private i18n: I18n,
29 private notifier: Notifier, 30 private notifier: Notifier,
30 private authService: AuthService, 31 private userService: UserService,
31 private overviewService: OverviewService, 32 private overviewService: OverviewService,
32 private screenService: ScreenService 33 private screenService: ScreenService
33 ) { } 34 ) { }
34 35
35 get user () {
36 return this.authService.getUser()
37 }
38
39 ngOnInit () { 36 ngOnInit () {
40 this.loadMoreResults() 37 this.loadMoreResults()
38
39 this.userService.getAnonymousOrLoggedUser()
40 .subscribe(user => this.userMiniature = user)
41
42 this.userService.listenAnonymousUpdate()
43 .subscribe(user => this.userMiniature = user)
41 } 44 }
42 45
43 buildVideoChannelBy (object: { videos: Video[] }) { 46 buildVideoChannelBy (object: { videos: Video[] }) {
diff --git a/client/src/app/videos/video-list/video-recently-added.component.ts b/client/src/app/videos/video-list/video-recently-added.component.ts
index c1ddd4fd4..9f57a61e3 100644
--- a/client/src/app/videos/video-list/video-recently-added.component.ts
+++ b/client/src/app/videos/video-list/video-recently-added.component.ts
@@ -22,7 +22,7 @@ export class VideoRecentlyAddedComponent extends AbstractVideoList implements On
22 sort: VideoSortField = '-publishedAt' 22 sort: VideoSortField = '-publishedAt'
23 groupByDate = true 23 groupByDate = true
24 24
25 useUserVideoLanguagePreferences = true 25 useUserVideoPreferences = true
26 26
27 constructor ( 27 constructor (
28 protected i18n: I18n, 28 protected i18n: I18n,
@@ -59,6 +59,7 @@ export class VideoRecentlyAddedComponent extends AbstractVideoList implements On
59 sort: this.sort, 59 sort: this.sort,
60 categoryOneOf: this.categoryOneOf, 60 categoryOneOf: this.categoryOneOf,
61 languageOneOf: this.languageOneOf, 61 languageOneOf: this.languageOneOf,
62 nsfwPolicy: this.nsfwPolicy,
62 skipCount: true 63 skipCount: true
63 } 64 }
64 65
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 fbe052277..62e0f4e69 100644
--- a/client/src/app/videos/video-list/video-trending.component.ts
+++ b/client/src/app/videos/video-list/video-trending.component.ts
@@ -21,7 +21,7 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
21 titlePage: string 21 titlePage: string
22 defaultSort: VideoSortField = '-trending' 22 defaultSort: VideoSortField = '-trending'
23 23
24 useUserVideoLanguagePreferences = true 24 useUserVideoPreferences = true
25 25
26 constructor ( 26 constructor (
27 protected i18n: I18n, 27 protected i18n: I18n,
@@ -72,6 +72,7 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
72 sort: this.sort, 72 sort: this.sort,
73 categoryOneOf: this.categoryOneOf, 73 categoryOneOf: this.categoryOneOf,
74 languageOneOf: this.languageOneOf, 74 languageOneOf: this.languageOneOf,
75 nsfwPolicy: this.nsfwPolicy,
75 skipCount: true 76 skipCount: true
76 } 77 }
77 78