diff options
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 @@ | |||
1 | import { from, Subject, Subscription } from 'rxjs' | ||
2 | import { concatMap, map, switchMap, tap } from 'rxjs/operators' | ||
1 | import { Component, OnDestroy, OnInit } from '@angular/core' | 3 | import { Component, OnDestroy, OnInit } from '@angular/core' |
2 | import { ActivatedRoute } from '@angular/router' | 4 | import { UserService } from '@app/shared' |
3 | import { Account } from '@app/shared/account/account.model' | 5 | import { Account } from '@app/shared/account/account.model' |
4 | import { AccountService } from '@app/shared/account/account.service' | 6 | import { AccountService } from '@app/shared/account/account.service' |
5 | import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' | 7 | import { ScreenService } from '@app/shared/misc/screen.service' |
6 | import { concatMap, map, switchMap, tap } from 'rxjs/operators' | 8 | import { ComponentPagination, hasMoreItems } from '@app/shared/rest/component-pagination.model' |
7 | import { from, Subject, Subscription } from 'rxjs' | ||
8 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' | 9 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' |
10 | import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' | ||
11 | import { VideoSortField } from '@app/shared/video/sort-field.type' | ||
9 | import { Video } from '@app/shared/video/video.model' | 12 | import { Video } from '@app/shared/video/video.model' |
10 | import { AuthService } from '@app/core' | ||
11 | import { VideoService } from '@app/shared/video/video.service' | 13 | import { VideoService } from '@app/shared/video/video.service' |
12 | import { VideoSortField } from '@app/shared/video/sort-field.type' | 14 | import { User } from '@shared/models' |
13 | import { ComponentPagination, hasMoreItems } from '@app/shared/rest/component-pagination.model' | ||
14 | import { 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' | |||
5 | import { HooksService } from '@app/core/plugins/hooks.service' | 5 | import { HooksService } from '@app/core/plugins/hooks.service' |
6 | import { AdvancedSearch } from '@app/search/advanced-search.model' | 6 | import { AdvancedSearch } from '@app/search/advanced-search.model' |
7 | import { SearchService } from '@app/search/search.service' | 7 | import { SearchService } from '@app/search/search.service' |
8 | import { UserService } from '@app/shared' | ||
8 | import { immutableAssign } from '@app/shared/misc/utils' | 9 | import { immutableAssign } from '@app/shared/misc/utils' |
9 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' | 10 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' |
10 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' | 11 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' |
@@ -12,7 +13,7 @@ import { MiniatureDisplayOptions } from '@app/shared/video/video-miniature.compo | |||
12 | import { Video } from '@app/shared/video/video.model' | 13 | import { Video } from '@app/shared/video/video.model' |
13 | import { MetaService } from '@ngx-meta/core' | 14 | import { MetaService } from '@ngx-meta/core' |
14 | import { I18n } from '@ngx-translate/i18n-polyfill' | 15 | import { I18n } from '@ngx-translate/i18n-polyfill' |
15 | import { ServerConfig } from '@shared/models' | 16 | import { ServerConfig, User } from '@shared/models' |
16 | import { SearchTargetType } from '@shared/models/search/search-target-query.model' | 17 | import { 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 @@ | |||
1 | import { from, Observable } from 'rxjs' | 1 | import { has } from 'lodash-es' |
2 | import { catchError, concatMap, map, shareReplay, toArray } from 'rxjs/operators' | 2 | import { BytesPipe } from 'ngx-pipes' |
3 | import { SortMeta } from 'primeng/api' | ||
4 | import { from, Observable, of } from 'rxjs' | ||
5 | import { catchError, concatMap, first, map, shareReplay, toArray, throttleTime, filter } from 'rxjs/operators' | ||
3 | import { HttpClient, HttpParams } from '@angular/common/http' | 6 | import { HttpClient, HttpParams } from '@angular/common/http' |
4 | import { Injectable } from '@angular/core' | 7 | import { Injectable } from '@angular/core' |
5 | import { ResultList, User as UserServerModel, UserCreate, UserRole, UserUpdate, UserUpdateMe, UserVideoQuota } from '../../../../../shared' | 8 | import { AuthService } from '@app/core/auth' |
6 | import { environment } from '../../../environments/environment' | ||
7 | import { RestExtractor, RestPagination, RestService } from '../rest' | ||
8 | import { Avatar } from '../../../../../shared/models/avatars/avatar.model' | ||
9 | import { SortMeta } from 'primeng/api' | ||
10 | import { BytesPipe } from 'ngx-pipes' | ||
11 | import { I18n } from '@ngx-translate/i18n-polyfill' | 9 | import { I18n } from '@ngx-translate/i18n-polyfill' |
12 | import { UserRegister } from '@shared/models/users/user-register.model' | 10 | import { UserRegister } from '@shared/models/users/user-register.model' |
13 | import { User } from './user.model' | ||
14 | import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' | 11 | import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' |
15 | import { has } from 'lodash-es' | 12 | import { ResultList, User as UserServerModel, UserCreate, UserRole, UserUpdate, UserUpdateMe, UserVideoQuota } from '../../../../../shared' |
13 | import { Avatar } from '../../../../../shared/models/avatars/avatar.model' | ||
14 | import { environment } from '../../../environments/environment' | ||
16 | import { LocalStorageService, SessionStorageService } from '../misc/storage.service' | 15 | import { LocalStorageService, SessionStorageService } from '../misc/storage.service' |
16 | import { RestExtractor, RestPagination, RestService } from '../rest' | ||
17 | import { User } from './user.model' | ||
17 | 18 | ||
18 | @Injectable() | 19 | @Injectable() |
19 | export class UserService { | 20 | export 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 @@ | |||
1 | import { debounceTime, first, tap, throttleTime } from 'rxjs/operators' | 1 | import { fromEvent, Observable, of, Subject, Subscription } from 'rxjs' |
2 | import { debounceTime, tap, throttleTime, switchMap } from 'rxjs/operators' | ||
2 | import { OnDestroy, OnInit } from '@angular/core' | 3 | import { OnDestroy, OnInit } from '@angular/core' |
3 | import { ActivatedRoute, Router } from '@angular/router' | 4 | import { ActivatedRoute, Router } from '@angular/router' |
4 | import { fromEvent, Observable, of, Subject, Subscription } from 'rxjs' | ||
5 | import { AuthService } from '../../core/auth' | ||
6 | import { ComponentPaginationLight } from '../rest/component-pagination.model' | ||
7 | import { VideoSortField } from './sort-field.type' | ||
8 | import { Video } from './video.model' | ||
9 | import { ScreenService } from '@app/shared/misc/screen.service' | ||
10 | import { MiniatureDisplayOptions, OwnerDisplayType } from '@app/shared/video/video-miniature.component' | ||
11 | import { Syndication } from '@app/shared/video/syndication.model' | ||
12 | import { Notifier, ServerService } from '@app/core' | 5 | import { Notifier, ServerService } from '@app/core' |
13 | import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' | 6 | import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' |
7 | import { GlobalIconName } from '@app/shared/images/global-icon.component' | ||
8 | import { ScreenService } from '@app/shared/misc/screen.service' | ||
9 | import { Syndication } from '@app/shared/video/syndication.model' | ||
10 | import { MiniatureDisplayOptions, OwnerDisplayType } from '@app/shared/video/video-miniature.component' | ||
14 | import { I18n } from '@ngx-translate/i18n-polyfill' | 11 | import { I18n } from '@ngx-translate/i18n-polyfill' |
15 | import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date' | 12 | import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date' |
16 | import { ServerConfig } from '@shared/models' | 13 | import { ServerConfig } from '@shared/models' |
17 | import { GlobalIconName } from '@app/shared/images/global-icon.component' | 14 | import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' |
18 | import { UserService, User } from '../users' | 15 | import { AuthService } from '../../core/auth' |
19 | import { LocalStorageService } from '../misc/storage.service' | 16 | import { LocalStorageService } from '../misc/storage.service' |
17 | import { ComponentPaginationLight } from '../rest/component-pagination.model' | ||
18 | import { User, UserService } from '../users' | ||
19 | import { VideoSortField } from './sort-field.type' | ||
20 | import { Video } from './video.model' | ||
20 | 21 | ||
21 | enum GroupDate { | 22 | enum 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 @@ | |||
1 | import { Injectable, OnInit } from '@angular/core' | ||
2 | import { RecommendationService } from '@app/videos/recommendations/recommendations.service' | ||
3 | import { Video } from '@app/shared/video/video.model' | ||
4 | import { RecommendationInfo } from '@app/shared/video/recommendation-info.model' | ||
5 | import { VideoService } from '@app/shared/video/video.service' | ||
6 | import { map, switchMap } from 'rxjs/operators' | ||
7 | import { Observable, of } from 'rxjs' | 1 | import { Observable, of } from 'rxjs' |
8 | import { SearchService } from '@app/search/search.service' | 2 | import { map, switchMap } from 'rxjs/operators' |
9 | import { AdvancedSearch } from '@app/search/advanced-search.model' | 3 | import { Injectable } from '@angular/core' |
10 | import { ServerService } from '@app/core' | 4 | import { ServerService } from '@app/core' |
5 | import { AdvancedSearch } from '@app/search/advanced-search.model' | ||
6 | import { SearchService } from '@app/search/search.service' | ||
7 | import { UserService } from '@app/shared' | ||
8 | import { RecommendationInfo } from '@app/shared/video/recommendation-info.model' | ||
9 | import { Video } from '@app/shared/video/video.model' | ||
10 | import { VideoService } from '@app/shared/video/video.service' | ||
11 | import { RecommendationService } from '@app/videos/recommendations/recommendations.service' | ||
11 | import { ServerConfig } from '@shared/models' | 12 | import { ServerConfig } from '@shared/models' |
12 | import { 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 @@ | |||
1 | import { Component, Input, Output, OnChanges, EventEmitter } from '@angular/core' | ||
2 | import { Observable } from 'rxjs' | 1 | import { Observable } from 'rxjs' |
3 | import { Video } from '@app/shared/video/video.model' | 2 | import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core' |
3 | import { AuthService, Notifier } from '@app/core' | ||
4 | import { User } from '@app/shared' | ||
5 | import { SessionStorageService } from '@app/shared/misc/storage.service' | ||
6 | import { UserService } from '@app/shared/users/user.service' | ||
4 | import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' | 7 | import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' |
5 | import { RecommendationInfo } from '@app/shared/video/recommendation-info.model' | 8 | import { RecommendationInfo } from '@app/shared/video/recommendation-info.model' |
9 | import { MiniatureDisplayOptions } from '@app/shared/video/video-miniature.component' | ||
10 | import { Video } from '@app/shared/video/video.model' | ||
6 | import { RecommendedVideosStore } from '@app/videos/recommendations/recommended-videos.store' | 11 | import { RecommendedVideosStore } from '@app/videos/recommendations/recommended-videos.store' |
7 | import { User } from '@app/shared' | ||
8 | import { AuthService, Notifier } from '@app/core' | ||
9 | import { UserService } from '@app/shared/users/user.service' | ||
10 | import { I18n } from '@ngx-translate/i18n-polyfill' | 12 | import { I18n } from '@ngx-translate/i18n-polyfill' |
11 | import { SessionStorageService } from '@app/shared/misc/storage.service' | ||
12 | import { 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 | }) |
19 | export class RecommendedVideosComponent implements OnChanges { | 19 | export 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 @@ | |||
1 | import { Subject } from 'rxjs' | ||
1 | import { Component, OnInit } from '@angular/core' | 2 | import { Component, OnInit } from '@angular/core' |
2 | import { AuthService, Notifier } from '@app/core' | 3 | import { Notifier } from '@app/core' |
3 | import { I18n } from '@ngx-translate/i18n-polyfill' | 4 | import { User, UserService } from '@app/shared' |
4 | import { VideosOverview } from '@app/shared/overview/videos-overview.model' | 5 | import { ScreenService } from '@app/shared/misc/screen.service' |
5 | import { OverviewService } from '@app/shared/overview' | 6 | import { OverviewService } from '@app/shared/overview' |
7 | import { VideosOverview } from '@app/shared/overview/videos-overview.model' | ||
6 | import { Video } from '@app/shared/video/video.model' | 8 | import { Video } from '@app/shared/video/video.model' |
7 | import { ScreenService } from '@app/shared/misc/screen.service' | ||
8 | import { 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 | ||