import { debounceTime, filter } from 'rxjs/operators'
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'
import { AuthService, DisableForReuseHook, Notifier } from '@app/core'
-import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
-import { Video, VideoExistInPlaylist, VideoPlaylistCreate, VideoPlaylistElementCreate, VideoPlaylistPrivacy, VideoPlaylistElementUpdate } from '@shared/models'
-import { secondsToTime } from '../../../assets/player/utils'
+import { FormReactive, FormReactiveService } from '@app/shared/shared-forms'
+import { secondsToTime } from '@shared/core-utils'
+import {
+ CachedVideoExistInPlaylist,
+ Video,
+ VideoPlaylistCreate,
+ VideoPlaylistElementCreate,
+ VideoPlaylistElementUpdate,
+ VideoPlaylistPrivacy
+} from '@shared/models'
import { VIDEO_PLAYLIST_DISPLAY_NAME_VALIDATOR } from '../form-validators/video-playlist-validators'
import { CachedPlaylist, VideoPlaylistService } from './video-playlist.service'
-import { invoke, last } from 'lodash'
-const logger = debug('peertube:playlists:VideoAddToPlaylistComponent')
+const debugLogger = debug('peertube:playlists:VideoAddToPlaylistComponent')
type PlaylistElement = {
enabled: boolean
isNewPlaylistBlockOpened = false
videoPlaylistSearch: string
- videoPlaylistSearchChanged = new Subject<string>()
+ videoPlaylistSearchChanged = new Subject<void>()
videoPlaylists: PlaylistSummary[] = []
private listenToPlaylistChangeSub: Subscription
private playlistsData: CachedPlaylist[] = []
+ private pendingAddId: number
+
constructor (
- protected formValidatorService: FormValidatorService,
+ protected formReactiveService: FormReactiveService,
private authService: AuthService,
private notifier: Notifier,
private videoPlaylistService: VideoPlaylistService,
.subscribe(result => {
this.playlistsData = result.data
- this.videoPlaylistService.runPlaylistCheck(this.video.id)
+ this.videoPlaylistService.runVideoExistsInPlaylistCheck(this.video.id)
})
this.videoPlaylistSearchChanged
}
reload () {
- logger('Reloading component')
+ debugLogger('Reloading component')
this.videoPlaylists = []
this.videoPlaylistSearch = undefined
}
load () {
- logger('Loading component')
+ debugLogger('Loading component')
this.listenToVideoPlaylistChange()
.subscribe(playlistsResult => {
this.playlistsData = playlistsResult.data
- this.videoPlaylistService.runPlaylistCheck(this.video.id)
+ this.videoPlaylistService.runVideoExistsInPlaylistCheck(this.video.id)
})
}
}
createPlaylist () {
- const displayName = this.form.value[ 'displayName' ]
+ const displayName = this.form.value['displayName']
const videoPlaylistCreate: VideoPlaylistCreate = {
displayName,
privacy: VideoPlaylistPrivacy.PRIVATE
}
- this.videoPlaylistService.createVideoPlaylist(videoPlaylistCreate).subscribe(
- () => {
- this.isNewPlaylistBlockOpened = false
+ this.videoPlaylistService.createVideoPlaylist(videoPlaylistCreate)
+ .subscribe({
+ next: () => {
+ this.isNewPlaylistBlockOpened = false
- this.cd.markForCheck()
- },
+ this.cd.markForCheck()
+ },
- err => this.notifier.error(err.message)
- )
+ error: err => this.notifier.error(err.message)
+ })
}
onVideoPlaylistSearchChanged () {
}
isPrimaryCheckboxChecked (playlist: PlaylistSummary) {
- return playlist.elements.filter(e => e.enabled)
- .length !== 0
+ // Reduce latency when adding a video to a playlist using pendingAddId
+ return this.pendingAddId === playlist.id ||
+ playlist.elements.filter(e => e.enabled).length !== 0
}
toggleOptionalRow (playlist: PlaylistSummary) {
}
this.videoPlaylistService.updateVideoOfPlaylist(playlist.id, element.playlistElementId, body, this.video.id)
- .subscribe(
- () => {
+ .subscribe({
+ next: () => {
this.notifier.success($localize`Timestamps updated`)
},
- err => {
- this.notifier.error(err.message)
- },
+ error: err => this.notifier.error(err.message),
- () => this.cd.markForCheck()
- )
+ complete: () => this.cd.markForCheck()
+ })
}
private isOptionalRowDisplayed (playlist: PlaylistSummary) {
private removeVideoFromPlaylist (playlist: PlaylistSummary, elementId: number) {
this.videoPlaylistService.removeVideoFromPlaylist(playlist.id, elementId, this.video.id)
- .subscribe(
- () => {
+ .subscribe({
+ next: () => {
this.notifier.success($localize`Video removed from ${playlist.displayName}`)
},
- err => {
- this.notifier.error(err.message)
- },
+ error: err => this.notifier.error(err.message),
- () => this.cd.markForCheck()
- )
+ complete: () => this.cd.markForCheck()
+ })
}
private listenToVideoPlaylistChange () {
}
}
- private rebuildPlaylists (existResult: VideoExistInPlaylist[]) {
- logger('Got existing results for %d.', this.video.id, existResult)
+ private rebuildPlaylists (existResult: CachedVideoExistInPlaylist[]) {
+ debugLogger('Got existing results for %d.', this.video.id, existResult)
const oldPlaylists = this.videoPlaylists
this.videoPlaylists.push(playlistSummary)
}
- logger('Rebuilt playlist state for video %d.', this.video.id, this.videoPlaylists)
+ debugLogger('Rebuilt playlist state for video %d.', this.video.id, this.videoPlaylists)
this.cd.markForCheck()
}
if (element.startTimestamp) body.startTimestamp = element.startTimestamp
if (element.stopTimestamp && element.stopTimestamp !== this.video.duration) body.stopTimestamp = element.stopTimestamp
+ this.pendingAddId = playlist.id
+
this.videoPlaylistService.addVideoInPlaylist(playlist.id, body)
- .subscribe(
- res => {
+ .subscribe({
+ next: res => {
const message = body.startTimestamp || body.stopTimestamp
? $localize`Video added in ${playlist.displayName} at timestamps ${this.formatTimestamp(element)}`
: $localize`Video added in ${playlist.displayName}`
if (element) element.playlistElementId = res.videoPlaylistElement.id
},
- err => {
+ error: err => {
+ this.pendingAddId = undefined
+ this.cd.markForCheck()
+
this.notifier.error(err.message)
},
- () => this.cd.markForCheck()
- )
+ complete: () => {
+ this.pendingAddId = undefined
+ this.cd.markForCheck()
+ }
+ })
}
private formatTimestamp (element: PlaylistElement) {