-import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'
-import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'
+import { CachedPlaylist, VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
import { AuthService, Notifier } from '@app/core'
-import { forkJoin } from 'rxjs'
+import { Subject, Subscription } from 'rxjs'
+import { debounceTime, filter } from 'rxjs/operators'
import { Video, VideoPlaylistCreate, VideoPlaylistElementCreate, VideoPlaylistPrivacy } from '@shared/models'
import { FormReactive, FormValidatorService, VideoPlaylistValidatorsService } from '@app/shared/forms'
import { I18n } from '@ngx-translate/i18n-polyfill'
import { secondsToTime } from '../../../assets/player/utils'
+import * as debug from 'debug'
+import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
+import { VideoExistInPlaylist } from '@shared/models/videos/playlist/video-exist-in-playlist.model'
+
+const logger = debug('peertube:playlists:VideoAddToPlaylistComponent')
type PlaylistSummary = {
id: number
inPlaylist: boolean
displayName: string
+ playlistElementId?: number
startTimestamp?: number
stopTimestamp?: number
}
templateUrl: './video-add-to-playlist.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
-export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, OnChanges {
+export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, OnChanges, OnDestroy, DisableForReuseHook {
@Input() video: Video
@Input() currentVideoTimestamp: number
@Input() lazyLoad = false
isNewPlaylistBlockOpened = false
+ videoPlaylistSearch: string
+ videoPlaylistSearchChanged = new Subject<string>()
videoPlaylists: PlaylistSummary[] = []
timestampOptions: {
startTimestampEnabled: boolean
}
displayOptions = false
+ private disabled = false
+
+ private listenToPlaylistChangeSub: Subscription
+ private playlistsData: CachedPlaylist[] = []
+
constructor (
protected formValidatorService: FormValidatorService,
private authService: AuthService,
this.buildForm({
displayName: this.videoPlaylistValidatorsService.VIDEO_PLAYLIST_DISPLAY_NAME
})
+
+ this.videoPlaylistService.listenToMyAccountPlaylistsChange()
+ .subscribe(result => {
+ this.playlistsData = result.data
+
+ this.videoPlaylistService.runPlaylistCheck(this.video.id)
+ })
+
+ this.videoPlaylistSearchChanged
+ .pipe(debounceTime(500))
+ .subscribe(() => this.load())
+
+ if (this.lazyLoad === false) this.load()
}
ngOnChanges (simpleChanges: SimpleChanges) {
if (simpleChanges['video']) {
- this.unload()
+ this.reload()
}
}
- init () {
- this.resetOptions(true)
+ ngOnDestroy () {
+ this.unsubscribePlaylistChanges()
+ }
+
+ disableForReuse () {
+ this.disabled = true
+ }
- if (this.lazyLoad !== true) this.load()
+ enabledForReuse () {
+ this.disabled = false
}
- unload () {
+ reload () {
+ logger('Reloading component')
+
this.videoPlaylists = []
+ this.videoPlaylistSearch = undefined
- this.init()
+ this.resetOptions(true)
+ this.load()
this.cd.markForCheck()
}
load () {
- forkJoin([
- this.videoPlaylistService.listAccountPlaylists(this.user.account, '-updatedAt'),
- this.videoPlaylistService.doesVideoExistInPlaylist(this.video.id)
- ])
- .subscribe(
- ([ playlistsResult, existResult ]) => {
- for (const playlist of playlistsResult.data) {
- const existingPlaylist = existResult[ this.video.id ].find(p => p.playlistId === playlist.id)
-
- this.videoPlaylists.push({
- id: playlist.id,
- displayName: playlist.displayName,
- inPlaylist: !!existingPlaylist,
- startTimestamp: existingPlaylist ? existingPlaylist.startTimestamp : undefined,
- stopTimestamp: existingPlaylist ? existingPlaylist.stopTimestamp : undefined
- })
- }
-
- this.cd.markForCheck()
- }
- )
+ logger('Loading component')
+
+ this.listenToPlaylistChanges()
+
+ this.videoPlaylistService.listMyPlaylistWithCache(this.user, this.videoPlaylistSearch)
+ .subscribe(playlistsResult => {
+ this.playlistsData = playlistsResult.data
+
+ this.videoPlaylistService.runPlaylistCheck(this.video.id)
+ })
}
openChange (opened: boolean) {
}
this.videoPlaylistService.createVideoPlaylist(videoPlaylistCreate).subscribe(
- res => {
- this.videoPlaylists.push({
- id: res.videoPlaylist.id,
- displayName,
- inPlaylist: false
- })
-
+ () => {
this.isNewPlaylistBlockOpened = false
this.cd.markForCheck()
return `(${start}-${stop})`
}
+ onVideoPlaylistSearchChanged () {
+ this.videoPlaylistSearchChanged.next()
+ }
+
private removeVideoFromPlaylist (playlist: PlaylistSummary) {
- this.videoPlaylistService.removeVideoFromPlaylist(playlist.id, this.video.id)
+ if (!playlist.playlistElementId) return
+
+ this.videoPlaylistService.removeVideoFromPlaylist(playlist.id, playlist.playlistElementId, this.video.id)
.subscribe(
() => {
this.notifier.success(this.i18n('Video removed from {{name}}', { name: playlist.displayName }))
-
- playlist.inPlaylist = false
},
err => {
this.notifier.error(err.message)
-
- playlist.inPlaylist = true
},
() => this.cd.markForCheck()
)
}
+ private listenToPlaylistChanges () {
+ this.unsubscribePlaylistChanges()
+
+ this.listenToPlaylistChangeSub = this.videoPlaylistService.listenToVideoPlaylistChange(this.video.id)
+ .pipe(filter(() => this.disabled === false))
+ .subscribe(existResult => this.rebuildPlaylists(existResult))
+ }
+
+ private unsubscribePlaylistChanges () {
+ if (this.listenToPlaylistChangeSub) {
+ this.listenToPlaylistChangeSub.unsubscribe()
+ this.listenToPlaylistChangeSub = undefined
+ }
+ }
+
+ private rebuildPlaylists (existResult: VideoExistInPlaylist[]) {
+ logger('Got existing results for %d.', this.video.id, existResult)
+
+ this.videoPlaylists = []
+ for (const playlist of this.playlistsData) {
+ const existingPlaylist = existResult.find(p => p.playlistId === playlist.id)
+
+ this.videoPlaylists.push({
+ id: playlist.id,
+ displayName: playlist.displayName,
+ inPlaylist: !!existingPlaylist,
+ playlistElementId: existingPlaylist ? existingPlaylist.playlistElementId : undefined,
+ startTimestamp: existingPlaylist ? existingPlaylist.startTimestamp : undefined,
+ stopTimestamp: existingPlaylist ? existingPlaylist.stopTimestamp : undefined
+ })
+ }
+
+ logger('Rebuilt playlist state for video %d.', this.video.id, this.videoPlaylists)
+
+ this.cd.markForCheck()
+ }
+
private addVideoInPlaylist (playlist: PlaylistSummary) {
const body: VideoPlaylistElementCreate = { videoId: this.video.id }
this.videoPlaylistService.addVideoInPlaylist(playlist.id, body)
.subscribe(
() => {
- playlist.inPlaylist = true
-
- playlist.startTimestamp = body.startTimestamp
- playlist.stopTimestamp = body.stopTimestamp
-
const message = body.startTimestamp || body.stopTimestamp
? this.i18n('Video added in {{n}} at timestamps {{t}}', { n: playlist.displayName, t: this.formatTimestamp(playlist) })
: this.i18n('Video added in {{n}}', { n: playlist.displayName })
err => {
this.notifier.error(err.message)
-
- playlist.inPlaylist = false
},
() => this.cd.markForCheck()