]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/videos/+video-watch/video-watch-playlist.component.ts
Use form-control to display box-shadow on form inputs/selects upon focus
[github/Chocobozzz/PeerTube.git] / client / src / app / videos / +video-watch / video-watch-playlist.component.ts
CommitLineData
72675ebe
C
1import { Component, Input } from '@angular/core'
2import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
3import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
72675ebe 4import { VideoDetails, VideoPlaylistPrivacy } from '@shared/models'
72675ebe 5import { Router } from '@angular/router'
88a7f93f 6import { UserService } from '@app/shared'
bee29df8 7import { AuthService, Notifier } from '@app/core'
bfbd9128
C
8import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
9import { VideoPlaylistElement } from '@app/shared/video-playlist/video-playlist-element.model'
88a7f93f 10import { peertubeLocalStorage, peertubeSessionStorage } from '@app/shared/misc/peertube-web-storage'
bee29df8 11import { I18n } from '@ngx-translate/i18n-polyfill'
d3217560 12import { SessionStorageService, LocalStorageService } from '@app/shared/misc/storage.service'
72675ebe
C
13
14@Component({
15 selector: 'my-video-watch-playlist',
16 templateUrl: './video-watch-playlist.component.html',
17 styleUrls: [ './video-watch-playlist.component.scss' ]
18})
19export class VideoWatchPlaylistComponent {
bee29df8 20 static LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST = 'auto_play_video_playlist'
88a7f93f 21 static SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST = 'loop_playlist'
bee29df8 22
72675ebe
C
23 @Input() video: VideoDetails
24 @Input() playlist: VideoPlaylist
25
bfbd9128 26 playlistElements: VideoPlaylistElement[] = []
72675ebe
C
27 playlistPagination: ComponentPagination = {
28 currentPage: 1,
29 itemsPerPage: 30,
30 totalItems: null
31 }
32
bee29df8
RK
33 autoPlayNextVideoPlaylist: boolean
34 autoPlayNextVideoPlaylistSwitchText = ''
88a7f93f
RK
35 loopPlaylist: boolean
36 loopPlaylistSwitchText = ''
72675ebe
C
37 noPlaylistVideos = false
38 currentPlaylistPosition = 1
39
40 constructor (
bee29df8 41 private userService: UserService,
72675ebe 42 private auth: AuthService,
bee29df8
RK
43 private notifier: Notifier,
44 private i18n: I18n,
bfbd9128 45 private videoPlaylist: VideoPlaylistService,
d3217560
RK
46 private localStorageService: LocalStorageService,
47 private sessionStorageService: SessionStorageService,
72675ebe 48 private router: Router
bee29df8 49 ) {
706c5a47 50 // defaults to true
bee29df8
RK
51 this.autoPlayNextVideoPlaylist = this.auth.isLoggedIn()
52 ? this.auth.getUser().autoPlayNextVideoPlaylist
d3217560 53 : this.localStorageService.getItem(VideoWatchPlaylistComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) !== 'false'
bee29df8 54 this.setAutoPlayNextVideoPlaylistSwitchText()
88a7f93f 55
706c5a47 56 // defaults to false
d3217560 57 this.loopPlaylist = this.sessionStorageService.getItem(VideoWatchPlaylistComponent.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) === 'true'
88a7f93f 58 this.setLoopPlaylistSwitchText()
bee29df8 59 }
72675ebe
C
60
61 onPlaylistVideosNearOfBottom () {
62 // Last page
63 if (this.playlistPagination.totalItems <= (this.playlistPagination.currentPage * this.playlistPagination.itemsPerPage)) return
64
65 this.playlistPagination.currentPage += 1
66 this.loadPlaylistElements(this.playlist,false)
67 }
68
bfbd9128
C
69 onElementRemoved (playlistElement: VideoPlaylistElement) {
70 this.playlistElements = this.playlistElements.filter(e => e.id !== playlistElement.id)
72675ebe
C
71
72 this.playlistPagination.totalItems--
73 }
74
75 isPlaylistOwned () {
1acd784c
C
76 return this.playlist.isLocal === true &&
77 this.auth.isLoggedIn() &&
78 this.playlist.ownerAccount.name === this.auth.getUser().username
72675ebe
C
79 }
80
81 isUnlistedPlaylist () {
82 return this.playlist.privacy.id === VideoPlaylistPrivacy.UNLISTED
83 }
84
85 isPrivatePlaylist () {
86 return this.playlist.privacy.id === VideoPlaylistPrivacy.PRIVATE
87 }
88
89 isPublicPlaylist () {
90 return this.playlist.privacy.id === VideoPlaylistPrivacy.PUBLIC
91 }
92
93 loadPlaylistElements (playlist: VideoPlaylist, redirectToFirst = false) {
bfbd9128 94 this.videoPlaylist.getPlaylistVideos(playlist.uuid, this.playlistPagination)
93cae479 95 .subscribe(({ total, data }) => {
bfbd9128 96 this.playlistElements = this.playlistElements.concat(data)
93cae479 97 this.playlistPagination.totalItems = total
72675ebe 98
bfbd9128
C
99 const firstAvailableVideos = this.playlistElements.find(e => !!e.video)
100 if (!firstAvailableVideos) {
72675ebe
C
101 this.noPlaylistVideos = true
102 return
103 }
104
105 this.updatePlaylistIndex(this.video)
106
107 if (redirectToFirst) {
108 const extras = {
f1d9b2d6
C
109 queryParams: {
110 start: firstAvailableVideos.startTimestamp,
111 stop: firstAvailableVideos.stopTimestamp,
112 videoId: firstAvailableVideos.video.uuid
113 },
72675ebe
C
114 replaceUrl: true
115 }
116 this.router.navigate([], extras)
117 }
118 })
119 }
120
121 updatePlaylistIndex (video: VideoDetails) {
bfbd9128 122 if (this.playlistElements.length === 0 || !video) return
72675ebe 123
bfbd9128
C
124 for (const playlistElement of this.playlistElements) {
125 if (playlistElement.video && playlistElement.video.id === video.id) {
126 this.currentPlaylistPosition = playlistElement.position
72675ebe
C
127 return
128 }
129 }
130
131 // Load more videos to find our video
132 this.onPlaylistVideosNearOfBottom()
133 }
134
706c5a47
RK
135 findNextPlaylistVideo (position = this.currentPlaylistPosition): VideoPlaylistElement {
136 if (this.currentPlaylistPosition >= this.playlistPagination.totalItems) {
137 // we have reached the end of the playlist: either loop or stop
138 if (this.loopPlaylist) {
139 this.currentPlaylistPosition = position = 0
140 } else {
bfbd9128
C
141 return
142 }
706c5a47
RK
143 }
144
145 const next = this.playlistElements.find(e => e.position === position)
bfbd9128 146
706c5a47
RK
147 if (!next || !next.video) {
148 return this.findNextPlaylistVideo(position + 1)
72675ebe 149 }
706c5a47
RK
150
151 return next
152 }
153
154 navigateToNextPlaylistVideo () {
155 const next = this.findNextPlaylistVideo(this.currentPlaylistPosition + 1)
156 if (!next) return
157 const start = next.startTimestamp
158 const stop = next.stopTimestamp
159 this.router.navigate([],{ queryParams: { videoId: next.video.uuid, start, stop } })
72675ebe 160 }
bee29df8
RK
161
162 switchAutoPlayNextVideoPlaylist () {
163 this.autoPlayNextVideoPlaylist = !this.autoPlayNextVideoPlaylist
164 this.setAutoPlayNextVideoPlaylistSwitchText()
165
166 peertubeLocalStorage.setItem(
167 VideoWatchPlaylistComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST,
168 this.autoPlayNextVideoPlaylist.toString()
169 )
170
171 if (this.auth.isLoggedIn()) {
172 const details = {
173 autoPlayNextVideoPlaylist: this.autoPlayNextVideoPlaylist
174 }
175
176 this.userService.updateMyProfile(details).subscribe(
177 () => {
178 this.auth.refreshUserInformation()
179 },
180 err => this.notifier.error(err.message)
181 )
182 }
183 }
184
88a7f93f
RK
185 switchLoopPlaylist () {
186 this.loopPlaylist = !this.loopPlaylist
187 this.setLoopPlaylistSwitchText()
188
189 peertubeSessionStorage.setItem(
190 VideoWatchPlaylistComponent.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST,
191 this.loopPlaylist.toString()
192 )
193 }
194
bee29df8 195 private setAutoPlayNextVideoPlaylistSwitchText () {
88a7f93f
RK
196 this.autoPlayNextVideoPlaylistSwitchText = this.autoPlayNextVideoPlaylist
197 ? this.i18n('Stop autoplaying next video')
198 : this.i18n('Autoplay next video')
199 }
200
201 private setLoopPlaylistSwitchText () {
202 this.loopPlaylistSwitchText = this.loopPlaylist
203 ? this.i18n('Stop looping playlist videos')
204 : this.i18n('Loop playlist videos')
bee29df8 205 }
72675ebe 206}