aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html5
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts4
-rw-r--r--client/src/app/shared/users/user.model.ts1
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.html6
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.ts17
-rw-r--r--client/src/app/videos/recommendations/recommended-videos.component.ts4
-rw-r--r--server/controllers/api/users/me.ts1
-rw-r--r--server/helpers/custom-validators/users.ts5
-rw-r--r--server/models/account/user.ts8
-rw-r--r--server/tests/api/check-params/users.ts8
-rw-r--r--server/tests/api/users/users.ts13
-rw-r--r--shared/models/users/user-update-me.model.ts1
-rw-r--r--shared/models/users/user.model.ts1
14 files changed, 74 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 3a91facb4..fbf8fdf3c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,6 +37,8 @@
37/scripts/i18n/generate-iso639-target.ts 37/scripts/i18n/generate-iso639-target.ts
38 38
39# Other 39# Other
40/dump.rdb
41/.theia/
40/profiling/ 42/profiling/
41/*.zip 43/*.zip
42/*.tar.xz 44/*.tar.xz
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
index a11238925..06fd9833a 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
+++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
@@ -47,6 +47,11 @@
47 inputName="autoPlayVideo" formControlName="autoPlayVideo" 47 inputName="autoPlayVideo" formControlName="autoPlayVideo"
48 i18n-labelText labelText="Automatically plays video" 48 i18n-labelText labelText="Automatically plays video"
49 ></my-peertube-checkbox> 49 ></my-peertube-checkbox>
50
51 <my-peertube-checkbox
52 inputName="autoPlayNextVideo" formControlName="autoPlayNextVideo"
53 i18n-labelText labelText="Automatically starts playing next video"
54 ></my-peertube-checkbox>
50 </div> 55 </div>
51 56
52 <input type="submit" i18n-value value="Save" [disabled]="!form.valid"> 57 <input type="submit" i18n-value value="Save" [disabled]="!form.valid">
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
index 4fb828082..99eee23b8 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
@@ -36,6 +36,7 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI
36 nsfwPolicy: null, 36 nsfwPolicy: null,
37 webTorrentEnabled: null, 37 webTorrentEnabled: null,
38 autoPlayVideo: null, 38 autoPlayVideo: null,
39 autoPlayNextVideo: null,
39 videoLanguages: null 40 videoLanguages: null
40 }) 41 })
41 42
@@ -57,6 +58,7 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI
57 nsfwPolicy: this.user.nsfwPolicy, 58 nsfwPolicy: this.user.nsfwPolicy,
58 webTorrentEnabled: this.user.webTorrentEnabled, 59 webTorrentEnabled: this.user.webTorrentEnabled,
59 autoPlayVideo: this.user.autoPlayVideo === true, 60 autoPlayVideo: this.user.autoPlayVideo === true,
61 autoPlayNextVideo: this.user.autoPlayNextVideo,
60 videoLanguages 62 videoLanguages
61 }) 63 })
62 }) 64 })
@@ -66,6 +68,7 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI
66 const nsfwPolicy = this.form.value[ 'nsfwPolicy' ] 68 const nsfwPolicy = this.form.value[ 'nsfwPolicy' ]
67 const webTorrentEnabled = this.form.value['webTorrentEnabled'] 69 const webTorrentEnabled = this.form.value['webTorrentEnabled']
68 const autoPlayVideo = this.form.value['autoPlayVideo'] 70 const autoPlayVideo = this.form.value['autoPlayVideo']
71 const autoPlayNextVideo = this.form.value['autoPlayNextVideo']
69 72
70 let videoLanguages: string[] = this.form.value['videoLanguages'] 73 let videoLanguages: string[] = this.form.value['videoLanguages']
71 if (Array.isArray(videoLanguages)) { 74 if (Array.isArray(videoLanguages)) {
@@ -84,6 +87,7 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI
84 nsfwPolicy, 87 nsfwPolicy,
85 webTorrentEnabled, 88 webTorrentEnabled,
86 autoPlayVideo, 89 autoPlayVideo,
90 autoPlayNextVideo,
87 videoLanguages 91 videoLanguages
88 } 92 }
89 93
diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts
index 656b73dd2..e0b3f1faf 100644
--- a/client/src/app/shared/users/user.model.ts
+++ b/client/src/app/shared/users/user.model.ts
@@ -16,6 +16,7 @@ export class User implements UserServerModel {
16 adminFlags?: UserAdminFlag 16 adminFlags?: UserAdminFlag
17 17
18 autoPlayVideo: boolean 18 autoPlayVideo: boolean
19 autoPlayNextVideo: boolean
19 webTorrentEnabled: boolean 20 webTorrentEnabled: boolean
20 videosHistoryEnabled: boolean 21 videosHistoryEnabled: boolean
21 videoLanguages: string[] 22 videoLanguages: string[]
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 6a02f630a..cd60c407f 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.html
+++ b/client/src/app/videos/+video-watch/video-watch.component.html
@@ -199,7 +199,11 @@
199 <my-video-comments [video]="video" [user]="user"></my-video-comments> 199 <my-video-comments [video]="video" [user]="user"></my-video-comments>
200 </div> 200 </div>
201 201
202 <my-recommended-videos [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }" [user]="user"></my-recommended-videos> 202 <my-recommended-videos
203 [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }"
204 [user]="user"
205 (gotRecommendations)="onRecommendations($event)"
206 ></my-recommended-videos>
203 </div> 207 </div>
204 208
205 <div class="row privacy-concerns" *ngIf="hasAlreadyAcceptedPrivacyConcern === false"> 209 <div class="row privacy-concerns" *ngIf="hasAlreadyAcceptedPrivacyConcern === false">
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts
index 21a24113f..1e7991738 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.ts
+++ b/client/src/app/videos/+video-watch/video-watch.component.ts
@@ -35,6 +35,7 @@ import { getStoredTheater } from '../../../assets/player/peertube-player-local-s
35import { PluginService } from '@app/core/plugins/plugin.service' 35import { PluginService } from '@app/core/plugins/plugin.service'
36import { HooksService } from '@app/core/plugins/hooks.service' 36import { HooksService } from '@app/core/plugins/hooks.service'
37import { PlatformLocation } from '@angular/common' 37import { PlatformLocation } from '@angular/common'
38import { randomInt } from '@shared/core-utils/miscs/miscs'
38 39
39@Component({ 40@Component({
40 selector: 'my-video-watch', 41 selector: 'my-video-watch',
@@ -69,6 +70,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
69 remoteServerDown = false 70 remoteServerDown = false
70 hotkeys: Hotkey[] 71 hotkeys: Hotkey[]
71 72
73 private nextVideoUuid = ''
72 private currentTime: number 74 private currentTime: number
73 private paramsSub: Subscription 75 private paramsSub: Subscription
74 private queryParamsSub: Subscription 76 private queryParamsSub: Subscription
@@ -217,6 +219,13 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
217 return this.video.tags 219 return this.video.tags
218 } 220 }
219 221
222 onRecommendations (videos: Video[]) {
223 if (videos.length > 0) {
224 // Pick a random video until the recommendations are improved
225 this.nextVideoUuid = videos[randomInt(0,videos.length - 1)].uuid
226 }
227 }
228
220 onVideoRemoved () { 229 onVideoRemoved () {
221 this.redirectService.redirectToHomepage() 230 this.redirectService.redirectToHomepage()
222 } 231 }
@@ -477,6 +486,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
477 this.player.one('ended', () => { 486 this.player.one('ended', () => {
478 if (this.playlist) { 487 if (this.playlist) {
479 this.zone.run(() => this.videoWatchPlaylist.navigateToNextPlaylistVideo()) 488 this.zone.run(() => this.videoWatchPlaylist.navigateToNextPlaylistVideo())
489 } else if (this.user && this.user.autoPlayNextVideo) {
490 this.zone.run(() => this.autoplayNext())
480 } 491 }
481 }) 492 })
482 493
@@ -500,6 +511,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
500 this.hooks.runAction('action:video-watch.video.loaded', 'video-watch') 511 this.hooks.runAction('action:video-watch.video.loaded', 'video-watch')
501 } 512 }
502 513
514 private autoplayNext () {
515 if (this.nextVideoUuid) {
516 this.router.navigate([ '/videos/watch', this.nextVideoUuid ])
517 }
518 }
519
503 private setRating (nextRating: UserVideoRateType) { 520 private setRating (nextRating: UserVideoRateType) {
504 const ratingMethods: { [id in UserVideoRateType]: (id: number) => Observable<any> } = { 521 const ratingMethods: { [id in UserVideoRateType]: (id: number) => Observable<any> } = {
505 like: this.videoService.setVideoLike, 522 like: this.videoService.setVideoLike,
diff --git a/client/src/app/videos/recommendations/recommended-videos.component.ts b/client/src/app/videos/recommendations/recommended-videos.component.ts
index 68fd750cc..7e0fb8856 100644
--- a/client/src/app/videos/recommendations/recommended-videos.component.ts
+++ b/client/src/app/videos/recommendations/recommended-videos.component.ts
@@ -1,4 +1,4 @@
1import { Component, Input, OnChanges } from '@angular/core' 1import { Component, Input, Output, OnChanges, EventEmitter } from '@angular/core'
2import { Observable } from 'rxjs' 2import { Observable } from 'rxjs'
3import { Video } from '@app/shared/video/video.model' 3import { Video } from '@app/shared/video/video.model'
4import { RecommendationInfo } from '@app/shared/video/recommendation-info.model' 4import { RecommendationInfo } from '@app/shared/video/recommendation-info.model'
@@ -12,6 +12,7 @@ import { User } from '@app/shared'
12export class RecommendedVideosComponent implements OnChanges { 12export class RecommendedVideosComponent implements OnChanges {
13 @Input() inputRecommendation: RecommendationInfo 13 @Input() inputRecommendation: RecommendationInfo
14 @Input() user: User 14 @Input() user: User
15 @Output() gotRecommendations = new EventEmitter<Video[]>()
15 16
16 readonly hasVideos$: Observable<boolean> 17 readonly hasVideos$: Observable<boolean>
17 readonly videos$: Observable<Video[]> 18 readonly videos$: Observable<Video[]>
@@ -21,6 +22,7 @@ export class RecommendedVideosComponent implements OnChanges {
21 ) { 22 ) {
22 this.videos$ = this.store.recommendations$ 23 this.videos$ = this.store.recommendations$
23 this.hasVideos$ = this.store.hasRecommendations$ 24 this.hasVideos$ = this.store.hasRecommendations$
25 this.videos$.subscribe(videos => this.gotRecommendations.emit(videos))
24 } 26 }
25 27
26 public ngOnChanges (): void { 28 public ngOnChanges (): void {
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts
index bf872ca52..cfc346c35 100644
--- a/server/controllers/api/users/me.ts
+++ b/server/controllers/api/users/me.ts
@@ -175,6 +175,7 @@ async function updateMe (req: express.Request, res: express.Response) {
175 if (body.nsfwPolicy !== undefined) user.nsfwPolicy = body.nsfwPolicy 175 if (body.nsfwPolicy !== undefined) user.nsfwPolicy = body.nsfwPolicy
176 if (body.webTorrentEnabled !== undefined) user.webTorrentEnabled = body.webTorrentEnabled 176 if (body.webTorrentEnabled !== undefined) user.webTorrentEnabled = body.webTorrentEnabled
177 if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo 177 if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo
178 if (body.autoPlayNextVideo !== undefined) user.autoPlayNextVideo = body.autoPlayNextVideo
178 if (body.videosHistoryEnabled !== undefined) user.videosHistoryEnabled = body.videosHistoryEnabled 179 if (body.videosHistoryEnabled !== undefined) user.videosHistoryEnabled = body.videosHistoryEnabled
179 if (body.videoLanguages !== undefined) user.videoLanguages = body.videoLanguages 180 if (body.videoLanguages !== undefined) user.videoLanguages = body.videoLanguages
180 if (body.theme !== undefined) user.theme = body.theme 181 if (body.theme !== undefined) user.theme = body.theme
diff --git a/server/helpers/custom-validators/users.ts b/server/helpers/custom-validators/users.ts
index 68e84d9eb..16a95f120 100644
--- a/server/helpers/custom-validators/users.ts
+++ b/server/helpers/custom-validators/users.ts
@@ -65,6 +65,10 @@ function isUserBlockedValid (value: any) {
65 return isBooleanValid(value) 65 return isBooleanValid(value)
66} 66}
67 67
68function isUserAutoPlayNextVideoValid (value: any) {
69 return isBooleanValid(value)
70}
71
68function isNoInstanceConfigWarningModal (value: any) { 72function isNoInstanceConfigWarningModal (value: any) {
69 return isBooleanValid(value) 73 return isBooleanValid(value)
70} 74}
@@ -106,6 +110,7 @@ export {
106 isUserNSFWPolicyValid, 110 isUserNSFWPolicyValid,
107 isUserWebTorrentEnabledValid, 111 isUserWebTorrentEnabledValid,
108 isUserAutoPlayVideoValid, 112 isUserAutoPlayVideoValid,
113 isUserAutoPlayNextVideoValid,
109 isUserDisplayNameValid, 114 isUserDisplayNameValid,
110 isUserDescriptionValid, 115 isUserDescriptionValid,
111 isNoInstanceConfigWarningModal, 116 isNoInstanceConfigWarningModal,
diff --git a/server/models/account/user.ts b/server/models/account/user.ts
index 451e1fd6b..38c6d474a 100644
--- a/server/models/account/user.ts
+++ b/server/models/account/user.ts
@@ -25,6 +25,7 @@ import {
25 isNoInstanceConfigWarningModal, 25 isNoInstanceConfigWarningModal,
26 isUserAdminFlagsValid, 26 isUserAdminFlagsValid,
27 isUserAutoPlayVideoValid, 27 isUserAutoPlayVideoValid,
28 isUserAutoPlayNextVideoValid,
28 isUserBlockedReasonValid, 29 isUserBlockedReasonValid,
29 isUserBlockedValid, 30 isUserBlockedValid,
30 isUserEmailVerifiedValid, 31 isUserEmailVerifiedValid,
@@ -160,6 +161,12 @@ export class UserModel extends Model<UserModel> {
160 @Column 161 @Column
161 autoPlayVideo: boolean 162 autoPlayVideo: boolean
162 163
164 @AllowNull(false)
165 @Default(false)
166 @Is('UserAutoPlayNextVideo', value => throwIfNotValid(value, isUserAutoPlayNextVideoValid, 'auto play next video boolean'))
167 @Column
168 autoPlayNextVideo: boolean
169
163 @AllowNull(true) 170 @AllowNull(true)
164 @Default(null) 171 @Default(null)
165 @Is('UserVideoLanguages', value => throwIfNotValid(value, isUserVideoLanguages, 'video languages')) 172 @Is('UserVideoLanguages', value => throwIfNotValid(value, isUserVideoLanguages, 'video languages'))
@@ -597,6 +604,7 @@ export class UserModel extends Model<UserModel> {
597 webTorrentEnabled: this.webTorrentEnabled, 604 webTorrentEnabled: this.webTorrentEnabled,
598 videosHistoryEnabled: this.videosHistoryEnabled, 605 videosHistoryEnabled: this.videosHistoryEnabled,
599 autoPlayVideo: this.autoPlayVideo, 606 autoPlayVideo: this.autoPlayVideo,
607 autoPlayNextVideo: this.autoPlayNextVideo,
600 videoLanguages: this.videoLanguages, 608 videoLanguages: this.videoLanguages,
601 609
602 role: this.role, 610 role: this.role,
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts
index 9d7ff8984..5d5af284c 100644
--- a/server/tests/api/check-params/users.ts
+++ b/server/tests/api/check-params/users.ts
@@ -418,6 +418,14 @@ describe('Test users API validators', function () {
418 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) 418 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
419 }) 419 })
420 420
421 it('Should fail with an invalid autoPlayNextVideo attribute', async function () {
422 const fields = {
423 autoPlayNextVideo: -1
424 }
425
426 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
427 })
428
421 it('Should fail with an invalid videosHistoryEnabled attribute', async function () { 429 it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
422 const fields = { 430 const fields = {
423 videosHistoryEnabled: -1 431 videosHistoryEnabled: -1
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts
index 95b1bb626..ca06942e7 100644
--- a/server/tests/api/users/users.ts
+++ b/server/tests/api/users/users.ts
@@ -481,6 +481,19 @@ describe('Test users', function () {
481 expect(user.autoPlayVideo).to.be.false 481 expect(user.autoPlayVideo).to.be.false
482 }) 482 })
483 483
484 it('Should be able to change the autoPlayNextVideo attribute', async function () {
485 await updateMyUser({
486 url: server.url,
487 accessToken: accessTokenUser,
488 autoPlayNextVideo: true
489 })
490
491 const res = await getMyUserInformation(server.url, accessTokenUser)
492 const user = res.body
493
494 expect(user.autoPlayNextVideo).to.be.true
495 })
496
484 it('Should be able to change the email attribute', async function () { 497 it('Should be able to change the email attribute', async function () {
485 await updateMyUser({ 498 await updateMyUser({
486 url: server.url, 499 url: server.url,
diff --git a/shared/models/users/user-update-me.model.ts b/shared/models/users/user-update-me.model.ts
index 99b9a65bd..0a833f84c 100644
--- a/shared/models/users/user-update-me.model.ts
+++ b/shared/models/users/user-update-me.model.ts
@@ -7,6 +7,7 @@ export interface UserUpdateMe {
7 7
8 webTorrentEnabled?: boolean 8 webTorrentEnabled?: boolean
9 autoPlayVideo?: boolean 9 autoPlayVideo?: boolean
10 autoPlayNextVideo?: boolean
10 videosHistoryEnabled?: boolean 11 videosHistoryEnabled?: boolean
11 videoLanguages?: string[] 12 videoLanguages?: string[]
12 13
diff --git a/shared/models/users/user.model.ts b/shared/models/users/user.model.ts
index f67d262b0..1ca8ddcba 100644
--- a/shared/models/users/user.model.ts
+++ b/shared/models/users/user.model.ts
@@ -17,6 +17,7 @@ export interface User {
17 adminFlags?: UserAdminFlag 17 adminFlags?: UserAdminFlag
18 18
19 autoPlayVideo: boolean 19 autoPlayVideo: boolean
20 autoPlayNextVideo: boolean
20 webTorrentEnabled: boolean 21 webTorrentEnabled: boolean
21 videosHistoryEnabled: boolean 22 videosHistoryEnabled: boolean
22 videoLanguages: string[] 23 videoLanguages: string[]