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