diff options
author | Rigel Kent <sendmemail@rigelk.eu> | 2019-12-11 20:20:42 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2019-12-13 09:13:43 +0100 |
commit | bee29df8a9ba3090be3daa8ff806dd9a26d7a5cf (patch) | |
tree | 9e9f6d509ed24f799f82667109498b9561474a4d | |
parent | d816f3a063febac1cad09ab3a32e5f0d29353627 (diff) | |
download | PeerTube-bee29df8a9ba3090be3daa8ff806dd9a26d7a5cf.tar.gz PeerTube-bee29df8a9ba3090be3daa8ff806dd9a26d7a5cf.tar.zst PeerTube-bee29df8a9ba3090be3daa8ff806dd9a26d7a5cf.zip |
autoplay next video support for playlists
18 files changed, 144 insertions, 18 deletions
diff --git a/client/src/app/shared/images/global-icon.component.scss b/client/src/app/shared/images/global-icon.component.scss index 32fb9badb..6795d6628 100644 --- a/client/src/app/shared/images/global-icon.component.scss +++ b/client/src/app/shared/images/global-icon.component.scss | |||
@@ -1,4 +1,6 @@ | |||
1 | ::ng-deep svg { | 1 | ::ng-deep { |
2 | width: inherit; | 2 | svg { |
3 | height: inherit; | 3 | width: inherit; |
4 | height: inherit; | ||
5 | } | ||
4 | } | 6 | } |
diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts index e0b3f1faf..7707d7dda 100644 --- a/client/src/app/shared/users/user.model.ts +++ b/client/src/app/shared/users/user.model.ts | |||
@@ -17,6 +17,7 @@ export class User implements UserServerModel { | |||
17 | 17 | ||
18 | autoPlayVideo: boolean | 18 | autoPlayVideo: boolean |
19 | autoPlayNextVideo: boolean | 19 | autoPlayNextVideo: boolean |
20 | autoPlayNextVideoPlaylist: boolean | ||
20 | webTorrentEnabled: boolean | 21 | webTorrentEnabled: boolean |
21 | videosHistoryEnabled: boolean | 22 | videosHistoryEnabled: boolean |
22 | videoLanguages: string[] | 23 | videoLanguages: string[] |
diff --git a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.scss b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.scss index b55ca0dea..4d9d249d9 100644 --- a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.scss +++ b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.scss | |||
@@ -72,10 +72,6 @@ my-video-thumbnail, | |||
72 | 72 | ||
73 | a { | 73 | a { |
74 | width: auto; | 74 | width: auto; |
75 | |||
76 | &:hover { | ||
77 | text-decoration: underline !important; | ||
78 | } | ||
79 | } | 75 | } |
80 | 76 | ||
81 | .video-info-account, .video-info-timestamp { | 77 | .video-info-account, .video-info-timestamp { |
diff --git a/client/src/app/videos/+video-watch/video-watch-playlist.component.html b/client/src/app/videos/+video-watch/video-watch-playlist.component.html index c89936bd1..c07ba1ed6 100644 --- a/client/src/app/videos/+video-watch/video-watch-playlist.component.html +++ b/client/src/app/videos/+video-watch/video-watch-playlist.component.html | |||
@@ -14,6 +14,17 @@ | |||
14 | <span>{{ currentPlaylistPosition }}</span><span>{{ playlistPagination.totalItems }}</span> | 14 | <span>{{ currentPlaylistPosition }}</span><span>{{ playlistPagination.totalItems }}</span> |
15 | </div> | 15 | </div> |
16 | </div> | 16 | </div> |
17 | |||
18 | <div class="playlist-controls"> | ||
19 | <my-global-icon | ||
20 | iconName="videos" | ||
21 | [class.active]="autoPlayNextVideoPlaylist" | ||
22 | (click)="switchAutoPlayNextVideoPlaylist()" | ||
23 | [ngbTooltip]="autoPlayNextVideoPlaylistSwitchText" | ||
24 | placement="bottom auto" | ||
25 | container="body" | ||
26 | ></my-global-icon> | ||
27 | </div> | ||
17 | </div> | 28 | </div> |
18 | 29 | ||
19 | <div *ngFor="let playlistElement of playlistElements"> | 30 | <div *ngFor="let playlistElement of playlistElements"> |
diff --git a/client/src/app/videos/+video-watch/video-watch-playlist.component.scss b/client/src/app/videos/+video-watch/video-watch-playlist.component.scss index 4c24d6b05..ba8d1c3e1 100644 --- a/client/src/app/videos/+video-watch/video-watch-playlist.component.scss +++ b/client/src/app/videos/+video-watch/video-watch-playlist.component.scss | |||
@@ -34,6 +34,21 @@ | |||
34 | margin: 0 3px; | 34 | margin: 0 3px; |
35 | } | 35 | } |
36 | } | 36 | } |
37 | |||
38 | .playlist-controls { | ||
39 | display: flex; | ||
40 | margin: 10px 0; | ||
41 | |||
42 | my-global-icon { | ||
43 | &:not(.active) { | ||
44 | opacity: .5 | ||
45 | } | ||
46 | |||
47 | ::ng-deep { | ||
48 | cursor: pointer; | ||
49 | } | ||
50 | } | ||
51 | } | ||
37 | } | 52 | } |
38 | 53 | ||
39 | my-video-playlist-element-miniature { | 54 | my-video-playlist-element-miniature { |
diff --git a/client/src/app/videos/+video-watch/video-watch-playlist.component.ts b/client/src/app/videos/+video-watch/video-watch-playlist.component.ts index 524055ce2..ed2aeda6e 100644 --- a/client/src/app/videos/+video-watch/video-watch-playlist.component.ts +++ b/client/src/app/videos/+video-watch/video-watch-playlist.component.ts | |||
@@ -3,9 +3,12 @@ import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' | |||
3 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' | 3 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' |
4 | import { VideoDetails, VideoPlaylistPrivacy } from '@shared/models' | 4 | import { VideoDetails, VideoPlaylistPrivacy } from '@shared/models' |
5 | import { Router } from '@angular/router' | 5 | import { Router } from '@angular/router' |
6 | import { AuthService } from '@app/core' | 6 | import { User, UserService } from '@app/shared' |
7 | import { AuthService, Notifier } from '@app/core' | ||
7 | import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service' | 8 | import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service' |
8 | import { VideoPlaylistElement } from '@app/shared/video-playlist/video-playlist-element.model' | 9 | import { VideoPlaylistElement } from '@app/shared/video-playlist/video-playlist-element.model' |
10 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | ||
11 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
9 | 12 | ||
10 | @Component({ | 13 | @Component({ |
11 | selector: 'my-video-watch-playlist', | 14 | selector: 'my-video-watch-playlist', |
@@ -13,6 +16,8 @@ import { VideoPlaylistElement } from '@app/shared/video-playlist/video-playlist- | |||
13 | styleUrls: [ './video-watch-playlist.component.scss' ] | 16 | styleUrls: [ './video-watch-playlist.component.scss' ] |
14 | }) | 17 | }) |
15 | export class VideoWatchPlaylistComponent { | 18 | export class VideoWatchPlaylistComponent { |
19 | static LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST = 'auto_play_video_playlist' | ||
20 | |||
16 | @Input() video: VideoDetails | 21 | @Input() video: VideoDetails |
17 | @Input() playlist: VideoPlaylist | 22 | @Input() playlist: VideoPlaylist |
18 | 23 | ||
@@ -23,14 +28,24 @@ export class VideoWatchPlaylistComponent { | |||
23 | totalItems: null | 28 | totalItems: null |
24 | } | 29 | } |
25 | 30 | ||
31 | autoPlayNextVideoPlaylist: boolean | ||
32 | autoPlayNextVideoPlaylistSwitchText = '' | ||
26 | noPlaylistVideos = false | 33 | noPlaylistVideos = false |
27 | currentPlaylistPosition = 1 | 34 | currentPlaylistPosition = 1 |
28 | 35 | ||
29 | constructor ( | 36 | constructor ( |
37 | private userService: UserService, | ||
30 | private auth: AuthService, | 38 | private auth: AuthService, |
39 | private notifier: Notifier, | ||
40 | private i18n: I18n, | ||
31 | private videoPlaylist: VideoPlaylistService, | 41 | private videoPlaylist: VideoPlaylistService, |
32 | private router: Router | 42 | private router: Router |
33 | ) {} | 43 | ) { |
44 | this.autoPlayNextVideoPlaylist = this.auth.isLoggedIn() | ||
45 | ? this.auth.getUser().autoPlayNextVideoPlaylist | ||
46 | : peertubeLocalStorage.getItem(VideoWatchPlaylistComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) !== 'false' | ||
47 | this.setAutoPlayNextVideoPlaylistSwitchText() | ||
48 | } | ||
34 | 49 | ||
35 | onPlaylistVideosNearOfBottom () { | 50 | onPlaylistVideosNearOfBottom () { |
36 | // Last page | 51 | // Last page |
@@ -121,4 +136,33 @@ export class VideoWatchPlaylistComponent { | |||
121 | this.router.navigate([],{ queryParams: { videoId: next.video.uuid, start, stop } }) | 136 | this.router.navigate([],{ queryParams: { videoId: next.video.uuid, start, stop } }) |
122 | } | 137 | } |
123 | } | 138 | } |
139 | |||
140 | switchAutoPlayNextVideoPlaylist () { | ||
141 | this.autoPlayNextVideoPlaylist = !this.autoPlayNextVideoPlaylist | ||
142 | this.setAutoPlayNextVideoPlaylistSwitchText() | ||
143 | |||
144 | peertubeLocalStorage.setItem( | ||
145 | VideoWatchPlaylistComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST, | ||
146 | this.autoPlayNextVideoPlaylist.toString() | ||
147 | ) | ||
148 | |||
149 | if (this.auth.isLoggedIn()) { | ||
150 | const details = { | ||
151 | autoPlayNextVideoPlaylist: this.autoPlayNextVideoPlaylist | ||
152 | } | ||
153 | |||
154 | this.userService.updateMyProfile(details).subscribe( | ||
155 | () => { | ||
156 | this.auth.refreshUserInformation() | ||
157 | }, | ||
158 | err => this.notifier.error(err.message) | ||
159 | ) | ||
160 | } | ||
161 | } | ||
162 | |||
163 | private setAutoPlayNextVideoPlaylistSwitchText () { | ||
164 | this.autoPlayNextVideoPlaylistSwitchText = this.i18n('{{verb}} autoplay for playlists', { | ||
165 | verb: this.autoPlayNextVideoPlaylist ? this.i18n('Disable') : this.i18n('Enable') | ||
166 | }) | ||
167 | } | ||
124 | } | 168 | } |
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 c57b00032..97f3a336e 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html | |||
@@ -217,6 +217,7 @@ | |||
217 | <my-recommended-videos | 217 | <my-recommended-videos |
218 | [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }" | 218 | [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }" |
219 | [user]="user" | 219 | [user]="user" |
220 | [playlist]="playlist" | ||
220 | (gotRecommendations)="onRecommendations($event)" | 221 | (gotRecommendations)="onRecommendations($event)" |
221 | ></my-recommended-videos> | 222 | ></my-recommended-videos> |
222 | </div> | 223 | </div> |
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 156a3235a..f13acec40 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -37,6 +37,7 @@ import { PluginService } from '@app/core/plugins/plugin.service' | |||
37 | import { HooksService } from '@app/core/plugins/hooks.service' | 37 | import { HooksService } from '@app/core/plugins/hooks.service' |
38 | import { PlatformLocation } from '@angular/common' | 38 | import { PlatformLocation } from '@angular/common' |
39 | import { randomInt } from '@shared/core-utils/miscs/miscs' | 39 | import { randomInt } from '@shared/core-utils/miscs/miscs' |
40 | import { RecommendedVideosComponent } from '../recommendations/recommended-videos.component' | ||
40 | 41 | ||
41 | @Component({ | 42 | @Component({ |
42 | selector: 'my-video-watch', | 43 | selector: 'my-video-watch', |
@@ -436,10 +437,13 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
436 | 437 | ||
437 | this.player.one('ended', () => { | 438 | this.player.one('ended', () => { |
438 | if (this.playlist) { | 439 | if (this.playlist) { |
439 | this.zone.run(() => this.videoWatchPlaylist.navigateToNextPlaylistVideo()) | 440 | if ( |
441 | this.user && this.user.autoPlayNextVideoPlaylist || | ||
442 | peertubeLocalStorage.getItem(VideoWatchPlaylistComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) === 'true' | ||
443 | ) this.zone.run(() => this.videoWatchPlaylist.navigateToNextPlaylistVideo()) | ||
440 | } else if ( | 444 | } else if ( |
441 | this.user && this.user.autoPlayNextVideo || | 445 | this.user && this.user.autoPlayNextVideo || |
442 | peertubeLocalStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true' | 446 | peertubeLocalStorage.getItem(RecommendedVideosComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true' |
443 | ) { | 447 | ) { |
444 | this.zone.run(() => this.autoplayNext()) | 448 | this.zone.run(() => this.autoplayNext()) |
445 | } | 449 | } |
@@ -447,7 +451,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
447 | 451 | ||
448 | this.player.one('stopped', () => { | 452 | this.player.one('stopped', () => { |
449 | if (this.playlist) { | 453 | if (this.playlist) { |
450 | this.zone.run(() => this.videoWatchPlaylist.navigateToNextPlaylistVideo()) | 454 | if ( |
455 | this.user && this.user.autoPlayNextVideoPlaylist || | ||
456 | peertubeLocalStorage.getItem(VideoWatchPlaylistComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) === 'true' | ||
457 | ) this.zone.run(() => this.videoWatchPlaylist.navigateToNextPlaylistVideo()) | ||
451 | } | 458 | } |
452 | }) | 459 | }) |
453 | 460 | ||
diff --git a/client/src/app/videos/+video-watch/video-watch.module.ts b/client/src/app/videos/+video-watch/video-watch.module.ts index f083aca4d..2e45e5674 100644 --- a/client/src/app/videos/+video-watch/video-watch.module.ts +++ b/client/src/app/videos/+video-watch/video-watch.module.ts | |||
@@ -12,6 +12,7 @@ import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap' | |||
12 | import { RecommendationsModule } from '@app/videos/recommendations/recommendations.module' | 12 | import { RecommendationsModule } from '@app/videos/recommendations/recommendations.module' |
13 | import { VideoWatchPlaylistComponent } from '@app/videos/+video-watch/video-watch-playlist.component' | 13 | import { VideoWatchPlaylistComponent } from '@app/videos/+video-watch/video-watch-playlist.component' |
14 | import { QRCodeModule } from 'angularx-qrcode' | 14 | import { QRCodeModule } from 'angularx-qrcode' |
15 | import { InputSwitchModule } from 'primeng/inputswitch' | ||
15 | 16 | ||
16 | @NgModule({ | 17 | @NgModule({ |
17 | imports: [ | 18 | imports: [ |
@@ -19,7 +20,8 @@ import { QRCodeModule } from 'angularx-qrcode' | |||
19 | SharedModule, | 20 | SharedModule, |
20 | NgbTooltipModule, | 21 | NgbTooltipModule, |
21 | QRCodeModule, | 22 | QRCodeModule, |
22 | RecommendationsModule | 23 | RecommendationsModule, |
24 | InputSwitchModule | ||
23 | ], | 25 | ], |
24 | 26 | ||
25 | declarations: [ | 27 | declarations: [ |
diff --git a/client/src/app/videos/recommendations/recommended-videos.component.html b/client/src/app/videos/recommendations/recommended-videos.component.html index 5f223078a..c82642c1c 100644 --- a/client/src/app/videos/recommendations/recommended-videos.component.html +++ b/client/src/app/videos/recommendations/recommended-videos.component.html | |||
@@ -4,15 +4,17 @@ | |||
4 | <div i18n class="title-page title-page-single"> | 4 | <div i18n class="title-page title-page-single"> |
5 | Other videos | 5 | Other videos |
6 | </div> | 6 | </div> |
7 | <div class="d-flex title-page-autoplay"> | 7 | <div *ngIf="!playlist" class="d-flex title-page-autoplay"> |
8 | <span>Autoplay</span> | 8 | <span i18n>Autoplay</span> |
9 | <p-inputSwitch [(ngModel)]="autoPlayNextVideo" (ngModelChange)="switchAutoPlayNextVideo()"></p-inputSwitch> | 9 | <p-inputSwitch [(ngModel)]="autoPlayNextVideo" (ngModelChange)="switchAutoPlayNextVideo()"></p-inputSwitch> |
10 | </div> | 10 | </div> |
11 | </div> | 11 | </div> |
12 | 12 | ||
13 | <div *ngFor="let video of (videos$ | async)"> | 13 | <div *ngFor="let video of (videos$ | async); let i = index; let length = count"> |
14 | <my-video-miniature [video]="video" [user]="user" (videoBlacklisted)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()"> | 14 | <my-video-miniature [video]="video" [user]="user" (videoBlacklisted)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()"> |
15 | </my-video-miniature> | 15 | </my-video-miniature> |
16 | |||
17 | <hr *ngIf="!playlist && i == 0 && length > 1" /> | ||
16 | </div> | 18 | </div> |
17 | </ng-container> | 19 | </ng-container> |
18 | </div> | 20 | </div> |
diff --git a/client/src/app/videos/recommendations/recommended-videos.component.ts b/client/src/app/videos/recommendations/recommended-videos.component.ts index 4c3cde225..771ae54a2 100644 --- a/client/src/app/videos/recommendations/recommended-videos.component.ts +++ b/client/src/app/videos/recommendations/recommended-videos.component.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Component, Input, Output, OnChanges, EventEmitter } from '@angular/core' | 1 | import { Component, Input, Output, OnChanges, EventEmitter } from '@angular/core' |
2 | import { Observable } from 'rxjs' | 2 | import { Observable } from 'rxjs' |
3 | import { Video } from '@app/shared/video/video.model' | 3 | import { Video } from '@app/shared/video/video.model' |
4 | import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' | ||
4 | import { RecommendationInfo } from '@app/shared/video/recommendation-info.model' | 5 | import { RecommendationInfo } from '@app/shared/video/recommendation-info.model' |
5 | import { RecommendedVideosStore } from '@app/videos/recommendations/recommended-videos.store' | 6 | import { RecommendedVideosStore } from '@app/videos/recommendations/recommended-videos.store' |
6 | import { User } from '@app/shared' | 7 | import { User } from '@app/shared' |
@@ -14,10 +15,11 @@ import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | |||
14 | styleUrls: [ './recommended-videos.component.scss' ] | 15 | styleUrls: [ './recommended-videos.component.scss' ] |
15 | }) | 16 | }) |
16 | export class RecommendedVideosComponent implements OnChanges { | 17 | export class RecommendedVideosComponent implements OnChanges { |
17 | private static LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO = 'auto_play_next_video' | 18 | static LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO = 'auto_play_next_video' |
18 | 19 | ||
19 | @Input() inputRecommendation: RecommendationInfo | 20 | @Input() inputRecommendation: RecommendationInfo |
20 | @Input() user: User | 21 | @Input() user: User |
22 | @Input() playlist: VideoPlaylist | ||
21 | @Output() gotRecommendations = new EventEmitter<Video[]>() | 23 | @Output() gotRecommendations = new EventEmitter<Video[]>() |
22 | 24 | ||
23 | readonly hasVideos$: Observable<boolean> | 25 | readonly hasVideos$: Observable<boolean> |
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts index cfc346c35..ba976ab03 100644 --- a/server/controllers/api/users/me.ts +++ b/server/controllers/api/users/me.ts | |||
@@ -176,6 +176,7 @@ async function updateMe (req: express.Request, res: express.Response) { | |||
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.autoPlayNextVideo !== undefined) user.autoPlayNextVideo = body.autoPlayNextVideo |
179 | if (body.autoPlayNextVideoPlaylist !== undefined) user.autoPlayNextVideoPlaylist = body.autoPlayNextVideoPlaylist | ||
179 | if (body.videosHistoryEnabled !== undefined) user.videosHistoryEnabled = body.videosHistoryEnabled | 180 | if (body.videosHistoryEnabled !== undefined) user.videosHistoryEnabled = body.videosHistoryEnabled |
180 | if (body.videoLanguages !== undefined) user.videoLanguages = body.videoLanguages | 181 | if (body.videoLanguages !== undefined) user.videoLanguages = body.videoLanguages |
181 | if (body.theme !== undefined) user.theme = body.theme | 182 | 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 16a95f120..008916a04 100644 --- a/server/helpers/custom-validators/users.ts +++ b/server/helpers/custom-validators/users.ts | |||
@@ -69,6 +69,10 @@ function isUserAutoPlayNextVideoValid (value: any) { | |||
69 | return isBooleanValid(value) | 69 | return isBooleanValid(value) |
70 | } | 70 | } |
71 | 71 | ||
72 | function isUserAutoPlayNextVideoPlaylistValid (value: any) { | ||
73 | return isBooleanValid(value) | ||
74 | } | ||
75 | |||
72 | function isNoInstanceConfigWarningModal (value: any) { | 76 | function isNoInstanceConfigWarningModal (value: any) { |
73 | return isBooleanValid(value) | 77 | return isBooleanValid(value) |
74 | } | 78 | } |
@@ -111,6 +115,7 @@ export { | |||
111 | isUserWebTorrentEnabledValid, | 115 | isUserWebTorrentEnabledValid, |
112 | isUserAutoPlayVideoValid, | 116 | isUserAutoPlayVideoValid, |
113 | isUserAutoPlayNextVideoValid, | 117 | isUserAutoPlayNextVideoValid, |
118 | isUserAutoPlayNextVideoPlaylistValid, | ||
114 | isUserDisplayNameValid, | 119 | isUserDisplayNameValid, |
115 | isUserDescriptionValid, | 120 | isUserDescriptionValid, |
116 | isNoInstanceConfigWarningModal, | 121 | isNoInstanceConfigWarningModal, |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index d0cf4d5de..00238f7a1 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -14,7 +14,7 @@ import { CONFIG, registerConfigChangedHandler } from './config' | |||
14 | 14 | ||
15 | // --------------------------------------------------------------------------- | 15 | // --------------------------------------------------------------------------- |
16 | 16 | ||
17 | const LAST_MIGRATION_VERSION = 455 | 17 | const LAST_MIGRATION_VERSION = 460 |
18 | 18 | ||
19 | // --------------------------------------------------------------------------- | 19 | // --------------------------------------------------------------------------- |
20 | 20 | ||
diff --git a/server/initializers/migrations/0460-user-playlist-autoplay.ts b/server/initializers/migrations/0460-user-playlist-autoplay.ts new file mode 100644 index 000000000..3067ac1a4 --- /dev/null +++ b/server/initializers/migrations/0460-user-playlist-autoplay.ts | |||
@@ -0,0 +1,27 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | async function up (utils: { | ||
4 | transaction: Sequelize.Transaction, | ||
5 | queryInterface: Sequelize.QueryInterface, | ||
6 | sequelize: Sequelize.Sequelize, | ||
7 | db: any | ||
8 | }): Promise<void> { | ||
9 | { | ||
10 | const data = { | ||
11 | type: Sequelize.BOOLEAN, | ||
12 | allowNull: false, | ||
13 | defaultValue: true | ||
14 | } | ||
15 | |||
16 | await utils.queryInterface.addColumn('user', 'autoPlayNextVideoPlaylist', data) | ||
17 | } | ||
18 | } | ||
19 | |||
20 | function down (options) { | ||
21 | throw new Error('Not implemented.') | ||
22 | } | ||
23 | |||
24 | export { | ||
25 | up, | ||
26 | down | ||
27 | } | ||
diff --git a/server/models/account/user.ts b/server/models/account/user.ts index 522ea3310..b2cd25bc3 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts | |||
@@ -26,6 +26,7 @@ import { | |||
26 | isUserAdminFlagsValid, | 26 | isUserAdminFlagsValid, |
27 | isUserAutoPlayVideoValid, | 27 | isUserAutoPlayVideoValid, |
28 | isUserAutoPlayNextVideoValid, | 28 | isUserAutoPlayNextVideoValid, |
29 | isUserAutoPlayNextVideoPlaylistValid, | ||
29 | isUserBlockedReasonValid, | 30 | isUserBlockedReasonValid, |
30 | isUserBlockedValid, | 31 | isUserBlockedValid, |
31 | isUserEmailVerifiedValid, | 32 | isUserEmailVerifiedValid, |
@@ -167,6 +168,12 @@ export class UserModel extends Model<UserModel> { | |||
167 | @Column | 168 | @Column |
168 | autoPlayNextVideo: boolean | 169 | autoPlayNextVideo: boolean |
169 | 170 | ||
171 | @AllowNull(false) | ||
172 | @Default(true) | ||
173 | @Is('UserAutoPlayNextVideoPlaylist', value => throwIfNotValid(value, isUserAutoPlayNextVideoPlaylistValid, 'auto play next video for playlists boolean')) | ||
174 | @Column | ||
175 | autoPlayNextVideoPlaylist: boolean | ||
176 | |||
170 | @AllowNull(true) | 177 | @AllowNull(true) |
171 | @Default(null) | 178 | @Default(null) |
172 | @Is('UserVideoLanguages', value => throwIfNotValid(value, isUserVideoLanguages, 'video languages')) | 179 | @Is('UserVideoLanguages', value => throwIfNotValid(value, isUserVideoLanguages, 'video languages')) |
@@ -619,6 +626,7 @@ export class UserModel extends Model<UserModel> { | |||
619 | videosHistoryEnabled: this.videosHistoryEnabled, | 626 | videosHistoryEnabled: this.videosHistoryEnabled, |
620 | autoPlayVideo: this.autoPlayVideo, | 627 | autoPlayVideo: this.autoPlayVideo, |
621 | autoPlayNextVideo: this.autoPlayNextVideo, | 628 | autoPlayNextVideo: this.autoPlayNextVideo, |
629 | autoPlayNextVideoPlaylist: this.autoPlayNextVideoPlaylist, | ||
622 | videoLanguages: this.videoLanguages, | 630 | videoLanguages: this.videoLanguages, |
623 | 631 | ||
624 | role: this.role, | 632 | role: this.role, |
diff --git a/shared/models/users/user-update-me.model.ts b/shared/models/users/user-update-me.model.ts index 0a833f84c..db6539cd2 100644 --- a/shared/models/users/user-update-me.model.ts +++ b/shared/models/users/user-update-me.model.ts | |||
@@ -8,6 +8,7 @@ export interface UserUpdateMe { | |||
8 | webTorrentEnabled?: boolean | 8 | webTorrentEnabled?: boolean |
9 | autoPlayVideo?: boolean | 9 | autoPlayVideo?: boolean |
10 | autoPlayNextVideo?: boolean | 10 | autoPlayNextVideo?: boolean |
11 | autoPlayNextVideoPlaylist?: boolean | ||
11 | videosHistoryEnabled?: boolean | 12 | videosHistoryEnabled?: boolean |
12 | videoLanguages?: string[] | 13 | videoLanguages?: string[] |
13 | 14 | ||
diff --git a/shared/models/users/user.model.ts b/shared/models/users/user.model.ts index 1ca8ddcba..90d59ac56 100644 --- a/shared/models/users/user.model.ts +++ b/shared/models/users/user.model.ts | |||
@@ -18,6 +18,7 @@ export interface User { | |||
18 | 18 | ||
19 | autoPlayVideo: boolean | 19 | autoPlayVideo: boolean |
20 | autoPlayNextVideo: boolean | 20 | autoPlayNextVideo: boolean |
21 | autoPlayNextVideoPlaylist: boolean | ||
21 | webTorrentEnabled: boolean | 22 | webTorrentEnabled: boolean |
22 | videosHistoryEnabled: boolean | 23 | videosHistoryEnabled: boolean |
23 | videoLanguages: string[] | 24 | videoLanguages: string[] |