Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Play next/prev video after removing current video from the playlist #5158

Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export default defineComponent({
loopEnabled: false,
reversePlaylist: false,
pauseOnCurrentVideo: false,
prevVideoBeforeDeletion: null,
channelName: '',
channelId: '',
playlistTitle: '',
Expand Down Expand Up @@ -85,15 +86,7 @@ export default defineComponent({
},

currentVideoIndexZeroBased: function () {
return this.playlistItems.findIndex((item) => {
if (item.playlistItemId != null && this.playlistItemId != null) {
return item.playlistItemId === this.playlistItemId
} else if (item.videoId != null) {
return item.videoId === this.videoId
} else {
return item.id === this.videoId
}
})
return this.findIndexOfCurrentVideoInPlaylist(this.playlistItems)
},
currentVideoIndexOneBased: function () {
return this.currentVideoIndexZeroBased + 1
Expand Down Expand Up @@ -123,19 +116,7 @@ export default defineComponent({

videoIndexInPlaylistItems: function () {
const playlistItems = this.shuffleEnabled ? this.randomizedPlaylistItems : this.playlistItems

return playlistItems.findIndex((item) => {
if (item.playlistItemId != null && this.playlistItemId != null) {
return item.playlistItemId === this.playlistItemId
} else if (item.videoId != null) {
return item.videoId === this.videoId
} else {
return item.id === this.videoId
}
})
},
videoIsFirstPlaylistItem: function () {
return this.videoIndexInPlaylistItems === 0
return this.findIndexOfCurrentVideoInPlaylist(playlistItems)
},
videoIsLastPlaylistItem: function () {
return this.videoIndexInPlaylistItems === (this.playlistItems.length - 1)
Expand All @@ -160,12 +141,12 @@ export default defineComponent({
},
selectedUserPlaylistVideoCount () {
// Re-fetch from local store when current user playlist updated
this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: true })
this.parseUserPlaylist(this.selectedUserPlaylist)
this.shufflePlaylistItems()
},
selectedUserPlaylistLastUpdatedAt () {
// Re-fetch from local store when current user playlist updated
this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: true })
this.parseUserPlaylist(this.selectedUserPlaylist)
},
videoId: function (newId, oldId) {
// Check if next video is from the shuffled list or if the user clicked a different video
Expand All @@ -184,6 +165,9 @@ export default defineComponent({
}
}
},
playlistItemId: function () {
this.prevVideoBeforeDeletion = null
},
watchViewLoading: function (newVal, oldVal) {
// This component is loaded/rendered before watch view loaded
if (oldVal && !newVal) {
Expand Down Expand Up @@ -232,6 +216,23 @@ export default defineComponent({
}
},
methods: {
findIndexOfCurrentVideoInPlaylist: function (playlist) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: this should be videos / playlistItems
findIndexOfCurrentVideoInPlaylist is called with various source of video lists (with different sorting orders applied)

const playlistItemId = this.playlistItemId
const prevVideoBeforeDeletion = this.prevVideoBeforeDeletion
const videoId = this.videoId
return playlist.findIndex((item) => {
if (item.playlistItemId && (playlistItemId || prevVideoBeforeDeletion?.playlistItemId)) {
return item.playlistItemId === playlistItemId || item.playlistItemId === prevVideoBeforeDeletion?.playlistItemId
} else if (item.videoId) {
return item.videoId === videoId || item.videoId === prevVideoBeforeDeletion?.videoId
} else if (item.id) {
return item.id === videoId || item.id === prevVideoBeforeDeletion?.videoId
}

return false
})
},

getPlaylistInfoWithDelay: function () {
if (this.getPlaylistInfoRun) { return }

Expand Down Expand Up @@ -348,8 +349,23 @@ export default defineComponent({
playlistType: this.playlistType,
}

const videoIndex = this.videoIndexInPlaylistItems
const targetVideoIndex = (this.videoIsFirstPlaylistItem || this.videoIsNotPlaylistItem) ? this.playlistItems.length - 1 : videoIndex - 1
let videoIndex = this.videoIndexInPlaylistItems

/*
* When the current video being watched in the playlist is deleted,
* the previous video is shown as the "current" one.
* So if we want to play the previous video, in this case,
* we actually want to actually play the "current" video.
* The only exception is when shuffle is enabled, as we don't actually
* want to play the last sequential video with shuffle.
*/
if (this.prevVideoBeforeDeletion && !this.shuffleEnabled) {
videoIndex++
}

// Wrap around to the end of the playlist only if there are no remaining earlier videos
const targetVideoIndex = (videoIndex === 0 || this.videoIsNotPlaylistItem) ? this.playlistItems.length - 1 : videoIndex - 1

if (this.shuffleEnabled) {
const targetPlaylistItem = this.randomizedPlaylistItems[targetVideoIndex]

Expand Down Expand Up @@ -466,24 +482,29 @@ export default defineComponent({
})
},

parseUserPlaylist: function (playlist, { allowPlayingVideoRemoval = true } = {}) {
parseUserPlaylist: function (playlist) {
this.playlistTitle = playlist.playlistName
this.channelName = ''
this.channelId = ''

if (this.playlistItems.length === 0 || allowPlayingVideoRemoval) {
this.playlistItems = playlist.videos
} else {
// `this.currentVideo` relies on `playlistItems`
const latestPlaylistContainsCurrentVideo = playlist.videos.some(v => v.playlistItemId === this.playlistItemId)
// Only update list of videos if latest video list still contains currently playing video
if (latestPlaylistContainsCurrentVideo) {
this.playlistItems = playlist.videos
}
const isCurrentVideoInParsedPlaylist = this.findIndexOfCurrentVideoInPlaylist(playlist.videos) !== -1
if (!isCurrentVideoInParsedPlaylist) {
Comment on lines +490 to +491
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use double negative here... (and below)

// grab 2nd video if the 1st one is current & deleted
// or the prior video in the list before the current video's deletion
const targetVideoIndex = (this.currentVideoIndexZeroBased === 0 ? 1 : this.currentVideoIndexZeroBased - 1)
this.prevVideoBeforeDeletion = this.playlistItems[targetVideoIndex]
}

let playlistItems = playlist.videos
if (this.reversePlaylist) {
this.playlistItems = this.playlistItems.toReversed()
playlistItems = playlistItems.toReversed()
}
this.playlistItems = playlistItems

// grab the first video of the parsed playlit if the current video is not in either the current or parsed data
// (e.g., reloading the page after the current video has already been removed from the playlist)
if (!isCurrentVideoInParsedPlaylist && this.prevVideoBeforeDeletion == null) {
this.prevVideoBeforeDeletion = this.playlistItems[0]
}

this.isLoading = false
Expand Down