]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts
Add buttons in playlist page
[github/Chocobozzz/PeerTube.git] / client / src / app / +my-account / my-account-video-playlists / my-account-video-playlist-elements.component.ts
1 import { Subject, Subscription } from 'rxjs'
2 import { CdkDragDrop } from '@angular/cdk/drag-drop'
3 import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
4 import { ActivatedRoute, Router } from '@angular/router'
5 import { ComponentPagination, ConfirmService, Notifier, ScreenService } from '@app/core'
6 import { DropdownAction } from '@app/shared/shared-main'
7 import { VideoShareComponent } from '@app/shared/shared-share-modal'
8 import { VideoPlaylist, VideoPlaylistElement, VideoPlaylistService } from '@app/shared/shared-video-playlist'
9 import { I18n } from '@ngx-translate/i18n-polyfill'
10 import { VideoPlaylistType } from '@shared/models'
11
12 @Component({
13 selector: 'my-account-video-playlist-elements',
14 templateUrl: './my-account-video-playlist-elements.component.html',
15 styleUrls: [ './my-account-video-playlist-elements.component.scss' ]
16 })
17 export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestroy {
18 @ViewChild('videoShareModal') videoShareModal: VideoShareComponent
19
20 playlistElements: VideoPlaylistElement[] = []
21 playlist: VideoPlaylist
22
23 playlistActions: DropdownAction<VideoPlaylist>[][] = []
24
25 pagination: ComponentPagination = {
26 currentPage: 1,
27 itemsPerPage: 10,
28 totalItems: null
29 }
30
31 onDataSubject = new Subject<any[]>()
32
33 private videoPlaylistId: string | number
34 private paramsSub: Subscription
35
36 constructor (
37 private notifier: Notifier,
38 private i18n: I18n,
39 private router: Router,
40 private confirmService: ConfirmService,
41 private route: ActivatedRoute,
42 private screenService: ScreenService,
43 private videoPlaylistService: VideoPlaylistService
44 ) {}
45
46 ngOnInit () {
47 this.playlistActions = [
48 [
49 {
50 label: this.i18n('Update playlist'),
51 iconName: 'edit',
52 linkBuilder: playlist => [ '/my-account', 'video-playlists', 'update', playlist.uuid ]
53 },
54 {
55 label: this.i18n('Delete playlist'),
56 iconName: 'delete',
57 handler: playlist => this.deleteVideoPlaylist(playlist)
58 }
59 ]
60 ]
61
62 this.paramsSub = this.route.params.subscribe(routeParams => {
63 this.videoPlaylistId = routeParams[ 'videoPlaylistId' ]
64 this.loadElements()
65
66 this.loadPlaylistInfo()
67 })
68 }
69
70 ngOnDestroy () {
71 if (this.paramsSub) this.paramsSub.unsubscribe()
72 }
73
74 drop (event: CdkDragDrop<any>) {
75 const previousIndex = event.previousIndex
76 const newIndex = event.currentIndex
77
78 if (previousIndex === newIndex) return
79
80 const oldPosition = this.playlistElements[previousIndex].position
81 let insertAfter = this.playlistElements[newIndex].position
82
83 if (oldPosition > insertAfter) insertAfter--
84
85 const element = this.playlistElements[previousIndex]
86
87 this.playlistElements.splice(previousIndex, 1)
88 this.playlistElements.splice(newIndex, 0, element)
89
90 this.videoPlaylistService.reorderPlaylist(this.playlist.id, oldPosition, insertAfter)
91 .subscribe(
92 () => {
93 this.reorderClientPositions()
94 },
95
96 err => this.notifier.error(err.message)
97 )
98 }
99
100 onElementRemoved (element: VideoPlaylistElement) {
101 const oldFirst = this.findFirst()
102
103 this.playlistElements = this.playlistElements.filter(v => v.id !== element.id)
104 this.reorderClientPositions(oldFirst)
105 }
106
107 onNearOfBottom () {
108 // Last page
109 if (this.pagination.totalItems <= (this.pagination.currentPage * this.pagination.itemsPerPage)) return
110
111 this.pagination.currentPage += 1
112 this.loadElements()
113 }
114
115 trackByFn (index: number, elem: VideoPlaylistElement) {
116 return elem.id
117 }
118
119 isRegularPlaylist (playlist: VideoPlaylist) {
120 return playlist?.type.id === VideoPlaylistType.REGULAR
121 }
122
123 showShareModal () {
124 this.videoShareModal.show()
125 }
126
127 async deleteVideoPlaylist (videoPlaylist: VideoPlaylist) {
128 const res = await this.confirmService.confirm(
129 this.i18n(
130 'Do you really want to delete {{playlistDisplayName}}?',
131 { playlistDisplayName: videoPlaylist.displayName }
132 ),
133 this.i18n('Delete')
134 )
135 if (res === false) return
136
137 this.videoPlaylistService.removeVideoPlaylist(videoPlaylist)
138 .subscribe(
139 () => {
140 this.router.navigate([ '/my-account', 'video-playlists' ])
141
142 this.notifier.success(
143 this.i18n('Playlist {{playlistDisplayName}} deleted.', { playlistDisplayName: videoPlaylist.displayName })
144 )
145 },
146
147 error => this.notifier.error(error.message)
148 )
149 }
150
151 /**
152 * Returns null to not have drag and drop delay.
153 * In small views, where elements are about 100% wide,
154 * we add a delay to prevent unwanted drag&drop.
155 *
156 * @see {@link https://github.com/Chocobozzz/PeerTube/issues/2078}
157 *
158 * @returns {null|number} Null for no delay, or a number in milliseconds.
159 */
160 getDragStartDelay (): null | number {
161 if (this.screenService.isInTouchScreen()) {
162 return 500
163 }
164
165 return null
166 }
167
168 private loadElements () {
169 this.videoPlaylistService.getPlaylistVideos(this.videoPlaylistId, this.pagination)
170 .subscribe(({ total, data }) => {
171 this.playlistElements = this.playlistElements.concat(data)
172 this.pagination.totalItems = total
173
174 this.onDataSubject.next(data)
175 })
176 }
177
178 private loadPlaylistInfo () {
179 this.videoPlaylistService.getVideoPlaylist(this.videoPlaylistId)
180 .subscribe(playlist => {
181 this.playlist = playlist
182 })
183 }
184
185 private reorderClientPositions (first?: VideoPlaylistElement) {
186 if (this.playlistElements.length === 0) return
187
188 const oldFirst = first || this.findFirst()
189 let i = 1
190
191 for (const element of this.playlistElements) {
192 element.position = i
193 i++
194 }
195
196 // Reload playlist thumbnail if the first element changed
197 const newFirst = this.findFirst()
198 if (oldFirst && newFirst && oldFirst.id !== newFirst.id) {
199 this.playlist.refreshThumbnail()
200 }
201 }
202
203 private findFirst () {
204 return this.playlistElements.find(e => e.position === 1)
205 }
206 }