Use playlistPosition for playlists instead of videoId

This commit is contained in:
Chocobozzz 2020-08-19 09:21:46 +02:00 committed by Chocobozzz
parent 3c6a44a181
commit d142c7b9c0
7 changed files with 54 additions and 34 deletions

View File

@ -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"

View File

@ -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 () {

View File

@ -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>

View File

@ -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?`,

View File

@ -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 () {

View File

@ -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 () {

View File

@ -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