Use playlistPosition for playlists instead of videoId
This commit is contained in:
parent
3c6a44a181
commit
d142c7b9c0
|
@ -1,4 +1,7 @@
|
||||||
<div *ngIf="playlist && video" class="playlist" myInfiniteScroller [autoInit]="true" [onItself]="true" (nearOfBottom)="onPlaylistVideosNearOfBottom()">
|
<div
|
||||||
|
*ngIf="playlist && currentPlaylistPosition" class="playlist"
|
||||||
|
myInfiniteScroller [autoInit]="true" [onItself]="true" (nearOfBottom)="onPlaylistVideosNearOfBottom()"
|
||||||
|
>
|
||||||
<div class="playlist-info">
|
<div class="playlist-info">
|
||||||
<div class="playlist-display-name">
|
<div class="playlist-display-name">
|
||||||
{{ playlist.displayName }}
|
{{ playlist.displayName }}
|
||||||
|
@ -36,7 +39,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngFor="let playlistElement of playlistElements">
|
<div *ngFor="let playlistElement of playlistElements" [ngClass]="'element-' + playlistElement.position">
|
||||||
<my-video-playlist-element-miniature
|
<my-video-playlist-element-miniature
|
||||||
[playlistElement]="playlistElement" [playlist]="playlist" [owned]="isPlaylistOwned()" (elementRemoved)="onElementRemoved($event)"
|
[playlistElement]="playlistElement" [playlist]="playlist" [owned]="isPlaylistOwned()" (elementRemoved)="onElementRemoved($event)"
|
||||||
[playing]="currentPlaylistPosition === playlistElement.position" [accountLink]="false" [position]="playlistElement.position"
|
[playing]="currentPlaylistPosition === playlistElement.position" [accountLink]="false" [position]="playlistElement.position"
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { Component, Input } from '@angular/core'
|
|
||||||
|
import { Component, EventEmitter, Input, Output } from '@angular/core'
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
import { AuthService, ComponentPagination, LocalStorageService, Notifier, SessionStorageService, UserService } from '@app/core'
|
import { AuthService, ComponentPagination, LocalStorageService, Notifier, SessionStorageService, UserService } from '@app/core'
|
||||||
import { VideoPlaylist, VideoPlaylistElement, VideoPlaylistService } from '@app/shared/shared-video-playlist'
|
import { VideoPlaylist, VideoPlaylistElement, VideoPlaylistService } from '@app/shared/shared-video-playlist'
|
||||||
import { peertubeLocalStorage, peertubeSessionStorage } from '@root-helpers/peertube-web-storage'
|
import { peertubeLocalStorage, peertubeSessionStorage } from '@root-helpers/peertube-web-storage'
|
||||||
import { VideoDetails, VideoPlaylistPrivacy } from '@shared/models'
|
import { VideoPlaylistPrivacy } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-video-watch-playlist',
|
selector: 'my-video-watch-playlist',
|
||||||
|
@ -14,9 +15,10 @@ export class VideoWatchPlaylistComponent {
|
||||||
static LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST = 'auto_play_video_playlist'
|
static LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST = 'auto_play_video_playlist'
|
||||||
static SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST = 'loop_playlist'
|
static SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST = 'loop_playlist'
|
||||||
|
|
||||||
@Input() video: VideoDetails
|
|
||||||
@Input() playlist: VideoPlaylist
|
@Input() playlist: VideoPlaylist
|
||||||
|
|
||||||
|
@Output() videoFound = new EventEmitter<string>()
|
||||||
|
|
||||||
playlistElements: VideoPlaylistElement[] = []
|
playlistElements: VideoPlaylistElement[] = []
|
||||||
playlistPagination: ComponentPagination = {
|
playlistPagination: ComponentPagination = {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
|
@ -29,7 +31,8 @@ export class VideoWatchPlaylistComponent {
|
||||||
loopPlaylist: boolean
|
loopPlaylist: boolean
|
||||||
loopPlaylistSwitchText = ''
|
loopPlaylistSwitchText = ''
|
||||||
noPlaylistVideos = false
|
noPlaylistVideos = false
|
||||||
currentPlaylistPosition = 1
|
|
||||||
|
currentPlaylistPosition: number
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
|
@ -44,6 +47,7 @@ export class VideoWatchPlaylistComponent {
|
||||||
this.autoPlayNextVideoPlaylist = this.auth.isLoggedIn()
|
this.autoPlayNextVideoPlaylist = this.auth.isLoggedIn()
|
||||||
? this.auth.getUser().autoPlayNextVideoPlaylist
|
? this.auth.getUser().autoPlayNextVideoPlaylist
|
||||||
: this.localStorageService.getItem(VideoWatchPlaylistComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) !== 'false'
|
: this.localStorageService.getItem(VideoWatchPlaylistComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) !== 'false'
|
||||||
|
|
||||||
this.setAutoPlayNextVideoPlaylistSwitchText()
|
this.setAutoPlayNextVideoPlaylistSwitchText()
|
||||||
|
|
||||||
// defaults to false
|
// defaults to false
|
||||||
|
@ -51,12 +55,12 @@ export class VideoWatchPlaylistComponent {
|
||||||
this.setLoopPlaylistSwitchText()
|
this.setLoopPlaylistSwitchText()
|
||||||
}
|
}
|
||||||
|
|
||||||
onPlaylistVideosNearOfBottom () {
|
onPlaylistVideosNearOfBottom (position?: number) {
|
||||||
// Last page
|
// Last page
|
||||||
if (this.playlistPagination.totalItems <= (this.playlistPagination.currentPage * this.playlistPagination.itemsPerPage)) return
|
if (this.playlistPagination.totalItems <= (this.playlistPagination.currentPage * this.playlistPagination.itemsPerPage)) return
|
||||||
|
|
||||||
this.playlistPagination.currentPage += 1
|
this.playlistPagination.currentPage += 1
|
||||||
this.loadPlaylistElements(this.playlist,false)
|
this.loadPlaylistElements(this.playlist, false, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
onElementRemoved (playlistElement: VideoPlaylistElement) {
|
onElementRemoved (playlistElement: VideoPlaylistElement) {
|
||||||
|
@ -83,26 +87,26 @@ export class VideoWatchPlaylistComponent {
|
||||||
return this.playlist.privacy.id === VideoPlaylistPrivacy.PUBLIC
|
return this.playlist.privacy.id === VideoPlaylistPrivacy.PUBLIC
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPlaylistElements (playlist: VideoPlaylist, redirectToFirst = false) {
|
loadPlaylistElements (playlist: VideoPlaylist, redirectToFirst = false, position?: number) {
|
||||||
this.videoPlaylist.getPlaylistVideos(playlist.uuid, this.playlistPagination)
|
this.videoPlaylist.getPlaylistVideos(playlist.uuid, this.playlistPagination)
|
||||||
.subscribe(({ total, data }) => {
|
.subscribe(({ total, data }) => {
|
||||||
this.playlistElements = this.playlistElements.concat(data)
|
this.playlistElements = this.playlistElements.concat(data)
|
||||||
this.playlistPagination.totalItems = total
|
this.playlistPagination.totalItems = total
|
||||||
|
|
||||||
const firstAvailableVideos = this.playlistElements.find(e => !!e.video)
|
const firstAvailableVideo = this.playlistElements.find(e => !!e.video)
|
||||||
if (!firstAvailableVideos) {
|
if (!firstAvailableVideo) {
|
||||||
this.noPlaylistVideos = true
|
this.noPlaylistVideos = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updatePlaylistIndex(this.video)
|
if (position) this.updatePlaylistIndex(position)
|
||||||
|
|
||||||
if (redirectToFirst) {
|
if (redirectToFirst) {
|
||||||
const extras = {
|
const extras = {
|
||||||
queryParams: {
|
queryParams: {
|
||||||
start: firstAvailableVideos.startTimestamp,
|
start: firstAvailableVideo.startTimestamp,
|
||||||
stop: firstAvailableVideos.stopTimestamp,
|
stop: firstAvailableVideo.stopTimestamp,
|
||||||
videoId: firstAvailableVideos.video.uuid
|
playlistPosition: firstAvailableVideo.position
|
||||||
},
|
},
|
||||||
replaceUrl: true
|
replaceUrl: true
|
||||||
}
|
}
|
||||||
|
@ -111,18 +115,26 @@ export class VideoWatchPlaylistComponent {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePlaylistIndex (video: VideoDetails) {
|
updatePlaylistIndex (position: number) {
|
||||||
if (this.playlistElements.length === 0 || !video) return
|
if (this.playlistElements.length === 0 || !position) return
|
||||||
|
|
||||||
for (const playlistElement of this.playlistElements) {
|
for (const playlistElement of this.playlistElements) {
|
||||||
if (playlistElement.video && playlistElement.video.id === video.id) {
|
// >= if the previous videos were not valid
|
||||||
|
if (playlistElement.video && playlistElement.position >= position) {
|
||||||
this.currentPlaylistPosition = playlistElement.position
|
this.currentPlaylistPosition = playlistElement.position
|
||||||
|
|
||||||
|
this.videoFound.emit(playlistElement.video.uuid)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
document.querySelector('.element-' + this.currentPlaylistPosition).scrollIntoView(false)
|
||||||
|
}, 0)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load more videos to find our video
|
// Load more videos to find our video
|
||||||
this.onPlaylistVideosNearOfBottom()
|
this.onPlaylistVideosNearOfBottom(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
findNextPlaylistVideo (position = this.currentPlaylistPosition): VideoPlaylistElement {
|
findNextPlaylistVideo (position = this.currentPlaylistPosition): VideoPlaylistElement {
|
||||||
|
@ -147,9 +159,10 @@ export class VideoWatchPlaylistComponent {
|
||||||
navigateToNextPlaylistVideo () {
|
navigateToNextPlaylistVideo () {
|
||||||
const next = this.findNextPlaylistVideo(this.currentPlaylistPosition + 1)
|
const next = this.findNextPlaylistVideo(this.currentPlaylistPosition + 1)
|
||||||
if (!next) return
|
if (!next) return
|
||||||
|
|
||||||
const start = next.startTimestamp
|
const start = next.startTimestamp
|
||||||
const stop = next.stopTimestamp
|
const stop = next.stopTimestamp
|
||||||
this.router.navigate([],{ queryParams: { videoId: next.video.uuid, start, stop } })
|
this.router.navigate([],{ queryParams: { playlistPosition: next.position, start, stop } })
|
||||||
}
|
}
|
||||||
|
|
||||||
switchAutoPlayNextVideoPlaylist () {
|
switchAutoPlayNextVideoPlaylist () {
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
|
|
||||||
<my-video-watch-playlist
|
<my-video-watch-playlist
|
||||||
#videoWatchPlaylist
|
#videoWatchPlaylist
|
||||||
[video]="video" [playlist]="playlist" class="playlist"
|
[playlist]="playlist" class="playlist"
|
||||||
|
(videoFound)="onPlaylistVideoFound($event)"
|
||||||
></my-video-watch-playlist>
|
></my-video-watch-playlist>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
video: VideoDetails = null
|
video: VideoDetails = null
|
||||||
videoCaptions: VideoCaption[] = []
|
videoCaptions: VideoCaption[] = []
|
||||||
|
|
||||||
|
playlistPosition: number
|
||||||
playlist: VideoPlaylist = null
|
playlist: VideoPlaylist = null
|
||||||
|
|
||||||
completeDescriptionShown = false
|
completeDescriptionShown = false
|
||||||
|
@ -140,9 +141,9 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
if (playlistId) this.loadPlaylist(playlistId)
|
if (playlistId) this.loadPlaylist(playlistId)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.queryParamsSub = this.route.queryParams.subscribe(async queryParams => {
|
this.queryParamsSub = this.route.queryParams.subscribe(queryParams => {
|
||||||
const videoId = queryParams[ 'videoId' ]
|
this.playlistPosition = queryParams[ 'playlistPosition' ]
|
||||||
if (videoId) this.loadVideo(videoId)
|
this.videoWatchPlaylist.updatePlaylistIndex(this.playlistPosition)
|
||||||
|
|
||||||
const start = queryParams[ 'start' ]
|
const start = queryParams[ 'start' ]
|
||||||
if (this.player && start) this.player.currentTime(parseInt(start, 10))
|
if (this.player && start) this.player.currentTime(parseInt(start, 10))
|
||||||
|
@ -335,6 +336,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
return genericChannelDisplayName.includes(this.video.channel.displayName)
|
return genericChannelDisplayName.includes(this.video.channel.displayName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onPlaylistVideoFound (videoId: string) {
|
||||||
|
this.loadVideo(videoId)
|
||||||
|
}
|
||||||
|
|
||||||
private loadVideo (videoId: string) {
|
private loadVideo (videoId: string) {
|
||||||
// Video did not change
|
// Video did not change
|
||||||
if (this.video && this.video.uuid === videoId) return
|
if (this.video && this.video.uuid === videoId) return
|
||||||
|
@ -392,8 +397,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
.subscribe(playlist => {
|
.subscribe(playlist => {
|
||||||
this.playlist = playlist
|
this.playlist = playlist
|
||||||
|
|
||||||
const videoId = this.route.snapshot.queryParams['videoId']
|
this.videoWatchPlaylist.loadPlaylistElements(playlist, !this.playlistPosition, this.playlistPosition)
|
||||||
this.videoWatchPlaylist.loadPlaylistElements(playlist, !videoId)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,8 +462,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
this.remoteServerDown = false
|
this.remoteServerDown = false
|
||||||
this.currentTime = undefined
|
this.currentTime = undefined
|
||||||
|
|
||||||
this.videoWatchPlaylist.updatePlaylistIndex(video)
|
|
||||||
|
|
||||||
if (this.isVideoBlur(this.video)) {
|
if (this.isVideoBlur(this.video)) {
|
||||||
const res = await this.confirmService.confirm(
|
const res = await this.confirmService.confirm(
|
||||||
$localize`This video contains mature or explicit content. Are you sure you want to watch it?`,
|
$localize`This video contains mature or explicit content. Are you sure you want to watch it?`,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
import { fromEvent, Observable, Subscription } from 'rxjs'
|
||||||
import { distinctUntilChanged, filter, map, share, startWith, throttleTime } from 'rxjs/operators'
|
import { distinctUntilChanged, filter, map, share, startWith, throttleTime } from 'rxjs/operators'
|
||||||
import { AfterContentChecked, Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'
|
import { AfterContentChecked, Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'
|
||||||
import { fromEvent, Observable, Subscription } from 'rxjs'
|
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[myInfiniteScroller]'
|
selector: '[myInfiniteScroller]'
|
||||||
|
@ -80,7 +80,9 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy, AfterConten
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMaximumScroll () {
|
private getMaximumScroll () {
|
||||||
return this.container.scrollHeight - window.innerHeight
|
const elementHeight = this.onItself ? this.container.clientHeight : window.innerHeight
|
||||||
|
|
||||||
|
return this.container.scrollHeight - elementHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasScroll () {
|
private hasScroll () {
|
||||||
|
|
|
@ -37,6 +37,7 @@ export class VideoShareComponent {
|
||||||
@Input() video: VideoDetails = null
|
@Input() video: VideoDetails = null
|
||||||
@Input() videoCaptions: VideoCaption[] = []
|
@Input() videoCaptions: VideoCaption[] = []
|
||||||
@Input() playlist: VideoPlaylist = null
|
@Input() playlist: VideoPlaylist = null
|
||||||
|
@Input() playlistPosition: number = null
|
||||||
|
|
||||||
activeVideoId: TabId = 'url'
|
activeVideoId: TabId = 'url'
|
||||||
activePlaylistId: TabId = 'url'
|
activePlaylistId: TabId = 'url'
|
||||||
|
@ -45,8 +46,6 @@ export class VideoShareComponent {
|
||||||
isAdvancedCustomizationCollapsed = true
|
isAdvancedCustomizationCollapsed = true
|
||||||
includeVideoInPlaylist = false
|
includeVideoInPlaylist = false
|
||||||
|
|
||||||
private playlistPosition: number = null
|
|
||||||
|
|
||||||
constructor (private modalService: NgbModal) { }
|
constructor (private modalService: NgbModal) { }
|
||||||
|
|
||||||
show (currentVideoTimestamp?: number, currentPlaylistPosition?: number) {
|
show (currentVideoTimestamp?: number, currentPlaylistPosition?: number) {
|
||||||
|
@ -107,7 +106,7 @@ export class VideoShareComponent {
|
||||||
|
|
||||||
if (!this.includeVideoInPlaylist) return base
|
if (!this.includeVideoInPlaylist) return base
|
||||||
|
|
||||||
return base + '?videoId=' + this.video.uuid
|
return base + '?playlistPosition=' + this.playlistPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
notSecure () {
|
notSecure () {
|
||||||
|
|
|
@ -78,7 +78,7 @@ export class VideoPlaylistElementMiniatureComponent implements OnInit {
|
||||||
if (!this.playlistElement || !this.playlistElement.video) return {}
|
if (!this.playlistElement || !this.playlistElement.video) return {}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
videoId: this.playlistElement.video.uuid,
|
playlistPosition: this.playlistElement.position,
|
||||||
start: this.playlistElement.startTimestamp,
|
start: this.playlistElement.startTimestamp,
|
||||||
stop: this.playlistElement.stopTimestamp,
|
stop: this.playlistElement.stopTimestamp,
|
||||||
resume: true
|
resume: true
|
||||||
|
|
Loading…
Reference in New Issue