]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - 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
CommitLineData
ad453580 1import { Subject, Subscription } from 'rxjs'
bfbd9128 2import { CdkDragDrop } from '@angular/cdk/drag-drop'
82f443de
C
3import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
4import { ActivatedRoute, Router } from '@angular/router'
5import { ComponentPagination, ConfirmService, Notifier, ScreenService } from '@app/core'
6import { DropdownAction } from '@app/shared/shared-main'
7import { VideoShareComponent } from '@app/shared/shared-share-modal'
67ed6552 8import { VideoPlaylist, VideoPlaylistElement, VideoPlaylistService } from '@app/shared/shared-video-playlist'
82f443de
C
9import { I18n } from '@ngx-translate/i18n-polyfill'
10import { VideoPlaylistType } from '@shared/models'
f0a39880
C
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})
17export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestroy {
82f443de
C
18 @ViewChild('videoShareModal') videoShareModal: VideoShareComponent
19
bfbd9128 20 playlistElements: VideoPlaylistElement[] = []
c5a1ae50 21 playlist: VideoPlaylist
f0a39880 22
82f443de
C
23 playlistActions: DropdownAction<VideoPlaylist>[][] = []
24
f0a39880
C
25 pagination: ComponentPagination = {
26 currentPage: 1,
ad453580 27 itemsPerPage: 10,
f0a39880
C
28 totalItems: null
29 }
30
ad453580
C
31 onDataSubject = new Subject<any[]>()
32
f0a39880
C
33 private videoPlaylistId: string | number
34 private paramsSub: Subscription
35
36 constructor (
f0a39880 37 private notifier: Notifier,
82f443de
C
38 private i18n: I18n,
39 private router: Router,
40 private confirmService: ConfirmService,
f0a39880 41 private route: ActivatedRoute,
0c695c5c 42 private screenService: ScreenService,
c5a1ae50 43 private videoPlaylistService: VideoPlaylistService
f0a39880
C
44 ) {}
45
46 ngOnInit () {
82f443de
C
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
f0a39880
C
62 this.paramsSub = this.route.params.subscribe(routeParams => {
63 this.videoPlaylistId = routeParams[ 'videoPlaylistId' ]
64 this.loadElements()
c5a1ae50
C
65
66 this.loadPlaylistInfo()
f0a39880
C
67 })
68 }
69
70 ngOnDestroy () {
71 if (this.paramsSub) this.paramsSub.unsubscribe()
72 }
73
15e9d5ca
C
74 drop (event: CdkDragDrop<any>) {
75 const previousIndex = event.previousIndex
76 const newIndex = event.currentIndex
77
78 if (previousIndex === newIndex) return
79
bfbd9128
C
80 const oldPosition = this.playlistElements[previousIndex].position
81 let insertAfter = this.playlistElements[newIndex].position
b767c4a7
C
82
83 if (oldPosition > insertAfter) insertAfter--
15e9d5ca 84
bfbd9128 85 const element = this.playlistElements[previousIndex]
15e9d5ca 86
bfbd9128
C
87 this.playlistElements.splice(previousIndex, 1)
88 this.playlistElements.splice(newIndex, 0, element)
15e9d5ca 89
65af03a2
C
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 )
15e9d5ca
C
98 }
99
bfbd9128 100 onElementRemoved (element: VideoPlaylistElement) {
65af03a2
C
101 const oldFirst = this.findFirst()
102
bfbd9128 103 this.playlistElements = this.playlistElements.filter(v => v.id !== element.id)
65af03a2 104 this.reorderClientPositions(oldFirst)
c5a1ae50
C
105 }
106
f0a39880
C
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
bfbd9128 115 trackByFn (index: number, elem: VideoPlaylistElement) {
bce47964
C
116 return elem.id
117 }
118
82f443de
C
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
0c695c5c
JM
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
f0a39880 168 private loadElements () {
bfbd9128 169 this.videoPlaylistService.getPlaylistVideos(this.videoPlaylistId, this.pagination)
93cae479 170 .subscribe(({ total, data }) => {
bfbd9128 171 this.playlistElements = this.playlistElements.concat(data)
93cae479 172 this.pagination.totalItems = total
ad453580
C
173
174 this.onDataSubject.next(data)
f0a39880
C
175 })
176 }
c5a1ae50
C
177
178 private loadPlaylistInfo () {
179 this.videoPlaylistService.getVideoPlaylist(this.videoPlaylistId)
180 .subscribe(playlist => {
181 this.playlist = playlist
182 })
183 }
15e9d5ca 184
65af03a2
C
185 private reorderClientPositions (first?: VideoPlaylistElement) {
186 if (this.playlistElements.length === 0) return
187
188 const oldFirst = first || this.findFirst()
15e9d5ca
C
189 let i = 1
190
bfbd9128
C
191 for (const element of this.playlistElements) {
192 element.position = i
15e9d5ca
C
193 i++
194 }
65af03a2
C
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)
15e9d5ca 205 }
f0a39880 206}