From b90c3bd3c6593230d1ee39b829d396297b4f1901 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:30:30 +0100 Subject: [PATCH 01/10] Implement pagination for user playlists on the Playlist page --- src/renderer/views/Playlist/Playlist.js | 39 ++++++++++++++++++++++-- src/renderer/views/Playlist/Playlist.vue | 4 +-- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js index 826f034494ec3..c80d4d82ba754 100644 --- a/src/renderer/views/Playlist/Playlist.js +++ b/src/renderer/views/Playlist/Playlist.js @@ -54,6 +54,7 @@ export default defineComponent({ channelId: '', infoSource: 'local', playlistItems: [], + userPlaylistVisibleLimit: 100, continuationData: null, isLoadingMore: false, getPlaylistInfoDebounce: function() {}, @@ -102,7 +103,11 @@ export default defineComponent({ }, moreVideoDataAvailable() { - return this.continuationData !== null + if (this.isUserPlaylistRequested) { + return this.userPlaylistVisibleLimit < this.videoCount + } else { + return this.continuationData !== null + } }, isUserPlaylistRequested: function () { @@ -117,6 +122,18 @@ export default defineComponent({ return this.selectedUserPlaylist?._id !== this.quickBookmarkPlaylistId }, + + visiblePlaylistItems: function () { + if (this.isUserPlaylistRequested) { + if (this.userPlaylistVisibleLimit < this.videoCount) { + return this.playlistItems.slice(0, this.userPlaylistVisibleLimit) + } else { + return this.playlistItems + } + } else { + return this.playlistItems + } + } }, watch: { $route () { @@ -147,8 +164,10 @@ export default defineComponent({ this.getPlaylistInfoDebounce() }, }, - mounted: function () { + created: function () { this.getPlaylistInfoDebounce = debounce(this.getPlaylistInfo, 100) + }, + mounted: function () { this.getPlaylistInfoDebounce() }, methods: { @@ -250,7 +269,7 @@ export default defineComponent({ const dateString = new Date(result.updated * 1000) this.lastUpdated = dateString.toLocaleDateString(this.currentLocale, { year: 'numeric', month: 'short', day: 'numeric' }) - this.playlistItems = this.playlistItems.concat(result.videos) + this.allPlaylistItems = result.videos this.isLoading = false }).catch((err) => { @@ -298,6 +317,20 @@ export default defineComponent({ case 'local': this.getNextPageLocal() break + case 'user': + // Stop users from spamming the load more button, by replacing it with a loading symbol until the newly added items are renderered + this.isLoadingMore = true + + setTimeout(() => { + if (this.userPlaylistVisibleLimit + 100 < this.videoCount) { + this.userPlaylistVisibleLimit += 100 + } else { + this.userPlaylistVisibleLimit = this.videoCount + } + + this.isLoadingMore = false + }) + break case 'invidious': console.error('Playlist pagination is not currently supported when the Invidious backend is selected.') break diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue index ef3efef0ce00e..86f1393102341 100644 --- a/src/renderer/views/Playlist/Playlist.vue +++ b/src/renderer/views/Playlist/Playlist.vue @@ -44,7 +44,7 @@ tag="span" >
Date: Wed, 24 Jan 2024 22:24:55 +0100
Subject: [PATCH 05/10] Minor speed ups in the playlists store
---
src/renderer/store/modules/playlists.js | 27 +++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 704d6ebb58887..2d24234a8bd6b 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -63,10 +63,13 @@ const actions = {
payload.createdAt = Date.now()
payload.lastUpdatedAt = Date.now()
// Ensure all videos has required attributes
+
+ const currentTime = new Date().getTime()
+
if (Array.isArray(payload.videos)) {
payload.videos.forEach(videoData => {
if (videoData.timeAdded == null) {
- videoData.timeAdded = new Date().getTime()
+ videoData.timeAdded = currentTime
}
if (videoData.playlistItemId == null) {
videoData.playlistItemId = generateRandomUniqueId()
@@ -149,11 +152,14 @@ const actions = {
// Since this action will ensure uniqueness of `playlistItemId` of added video entries
try {
const { _id, videos } = payload
+
+ const currentTime = new Date().getTime()
+
const newVideoObjects = videos.map((video) => {
// Create a new object to prevent changing existing values outside
const videoData = Object.assign({}, video)
if (videoData.timeAdded == null) {
- videoData.timeAdded = new Date().getTime()
+ videoData.timeAdded = currentTime
}
videoData.playlistItemId = generateRandomUniqueId()
// For backward compatibility
@@ -188,6 +194,9 @@ const actions = {
dispatch('addPlaylist', playlist)
})
} else {
+ const dateNow = Date.now()
+ const currentTime = new Date().getTime()
+
payload.forEach((playlist) => {
let anythingUpdated = false
// Assign generated playlist ID in case DB data corrupted
@@ -205,19 +214,19 @@ const actions = {
// Assign current time as created time in case DB data corrupted
if (playlist.createdAt == null) {
// Time now in unix time, in ms
- playlist.createdAt = Date.now()
+ playlist.createdAt = dateNow
anythingUpdated = true
}
// Assign current time as last updated time in case DB data corrupted
if (playlist.lastUpdatedAt == null) {
// Time now in unix time, in ms
- playlist.lastUpdatedAt = Date.now()
+ playlist.lastUpdatedAt = dateNow
anythingUpdated = true
}
playlist.videos.forEach((v) => {
// Ensure all videos has `timeAdded` property
if (v.timeAdded == null) {
- v.timeAdded = new Date().getTime()
+ v.timeAdded = currentTime
anythingUpdated = true
}
@@ -257,8 +266,9 @@ const actions = {
return playlist.playlistName === 'Watch Later' || playlist._id === 'watchLater'
})
- const defaultFavoritesPlaylist = state.defaultPlaylists.find((e) => e._id === 'favorites')
if (favoritesPlaylist != null) {
+ const defaultFavoritesPlaylist = state.defaultPlaylists.find((e) => e._id === 'favorites')
+
// Update existing matching playlist only if it exists
if (favoritesPlaylist._id !== defaultFavoritesPlaylist._id || favoritesPlaylist.protected !== defaultFavoritesPlaylist.protected) {
const oldId = favoritesPlaylist._id
@@ -277,8 +287,9 @@ const actions = {
}
}
- const defaultWatchLaterPlaylist = state.defaultPlaylists.find((e) => e._id === 'watchLater')
if (watchLaterPlaylist != null) {
+ const defaultWatchLaterPlaylist = state.defaultPlaylists.find((e) => e._id === 'watchLater')
+
// Update existing matching playlist only if it exists
if (watchLaterPlaylist._id !== defaultWatchLaterPlaylist._id || watchLaterPlaylist.protected !== defaultWatchLaterPlaylist.protected) {
const oldId = watchLaterPlaylist._id
@@ -394,7 +405,7 @@ const mutations = {
addVideos(state, payload) {
const playlist = state.playlists.find(playlist => playlist._id === payload._id)
if (playlist) {
- playlist.videos = [].concat(playlist.videos).concat(payload.videos)
+ playlist.videos = [].concat(playlist.videos, payload.videos)
}
},
From a7bb2188980153bd203e2c6fe786705f1a798083 Mon Sep 17 00:00:00 2001
From: absidue <48293849+absidue@users.noreply.github.com>
Date: Wed, 24 Jan 2024 22:59:02 +0100
Subject: [PATCH 06/10] ft-list-video: Remove superfluous template around view
count
---
.../components/ft-list-video/ft-list-video.vue | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/renderer/components/ft-list-video/ft-list-video.vue b/src/renderer/components/ft-list-video/ft-list-video.vue
index 31c627bf8de15..3597329a628e5 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -126,12 +126,13 @@
>
{{ channelName }}
-
-
- •
- {{ $tc('Global.Counts.View Count', viewCount, {count: parsedViewCount}) }}
-
-
+
+ •
+ {{ $tc('Global.Counts.View Count', viewCount, {count: parsedViewCount}) }}
+
Date: Wed, 24 Jan 2024 23:02:21 +0100
Subject: [PATCH 07/10] ft-list-video: Replace watched property with
historyEntryExists computed property
---
.../components/ft-list-video/ft-list-video.js | 15 ++++-----------
.../components/ft-list-video/ft-list-video.vue | 2 +-
2 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/src/renderer/components/ft-list-video/ft-list-video.js b/src/renderer/components/ft-list-video/ft-list-video.js
index 11c35f95475db..1befb4403e3d2 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -97,7 +97,6 @@ export default defineComponent({
lengthSeconds: 0,
duration: '',
description: '',
- watched: false,
watchProgress: 0,
publishedText: '',
isLive: false,
@@ -223,7 +222,7 @@ export default defineComponent({
dropdownOptions: function () {
const options = [
{
- label: this.watched
+ label: this.historyEntryExists
? this.$t('Video.Remove From History')
: this.$t('Video.Mark As Watched'),
value: 'history'
@@ -343,7 +342,7 @@ export default defineComponent({
},
addWatchedStyle: function () {
- return this.watched && !this.inHistory
+ return this.historyEntryExists && !this.inHistory
},
externalPlayer: function () {
@@ -576,7 +575,7 @@ export default defineComponent({
}
this.openInExternalPlayer(payload)
- if (this.saveWatchedProgress && !this.watched) {
+ if (this.saveWatchedProgress && !this.historyEntryExists) {
this.markAsWatched()
}
},
@@ -584,7 +583,7 @@ export default defineComponent({
handleOptionsClick: function (option) {
switch (option) {
case 'history':
- if (this.watched) {
+ if (this.historyEntryExists) {
this.removeFromWatched()
} else {
this.markAsWatched()
@@ -727,8 +726,6 @@ export default defineComponent({
checkIfWatched: function () {
if (this.historyEntryExists) {
- this.watched = true
-
const historyEntry = this.historyEntry
if (this.saveWatchedProgress) {
@@ -744,7 +741,6 @@ export default defineComponent({
this.publishedText = ''
}
} else {
- this.watched = false
this.watchProgress = 0
}
},
@@ -766,8 +762,6 @@ export default defineComponent({
}
this.updateHistory(videoData)
showToast(this.$t('Video.Video has been marked as watched'))
-
- this.watched = true
},
removeFromWatched: function () {
@@ -775,7 +769,6 @@ export default defineComponent({
showToast(this.$t('Video.Video has been removed from your history'))
- this.watched = false
this.watchProgress = 0
},
diff --git a/src/renderer/components/ft-list-video/ft-list-video.vue b/src/renderer/components/ft-list-video/ft-list-video.vue
index 3597329a628e5..9d6c57f21b124 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -104,7 +104,7 @@
{{ $t("Video.Watched") }}
From f13ef1a43a2a1e2491507ff54c2b871fb346c470 Mon Sep 17 00:00:00 2001
From: absidue <48293849+absidue@users.noreply.github.com>
Date: Wed, 24 Jan 2024 23:02:49 +0100
Subject: [PATCH 08/10] playlist-info: Fix copying partially loaded user
playlists
---
src/renderer/components/playlist-info/playlist-info.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index f5c43941322d5..7deaf2d387100 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -226,7 +226,7 @@ export default defineComponent({
},
methods: {
toggleCopyVideosPrompt: function (force = false) {
- if (this.moreVideoDataAvailable && !force) {
+ if (this.moreVideoDataAvailable && !this.isUserPlaylist && !force) {
showToast(this.$t('User Playlists.SinglePlaylistView.Toast["Some videos in the playlist are not loaded yet. Click here to copy anyway."]'), 5000, () => {
this.toggleCopyVideosPrompt(true)
})
From 66756c162ac8da0ece69dc80ac2811c9c848c605 Mon Sep 17 00:00:00 2001
From: absidue <48293849+absidue@users.noreply.github.com>
Date: Thu, 25 Jan 2024 18:05:04 +0100
Subject: [PATCH 09/10] Fix the playlist number not getting lazy loaded
---
.../ft-list-video-numbered.css | 17 +++
.../ft-list-video-numbered.js | 124 ++++++++++++++++++
.../ft-list-video-numbered.vue | 53 ++++++++
.../watch-video-playlist.css | 13 --
.../watch-video-playlist.js | 9 +-
.../watch-video-playlist.vue | 46 +++----
src/renderer/views/Playlist/Playlist.js | 4 +-
src/renderer/views/Playlist/Playlist.scss | 5 -
src/renderer/views/Playlist/Playlist.vue | 44 +++----
9 files changed, 233 insertions(+), 82 deletions(-)
create mode 100644 src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.css
create mode 100644 src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.js
create mode 100644 src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.vue
diff --git a/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.css b/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.css
new file mode 100644
index 0000000000000..20e216423f167
--- /dev/null
+++ b/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.css
@@ -0,0 +1,17 @@
+/*
+ Set a height to invisible/unloaded elements, so that lazy loading actually works.
+ If we don't set a height, they all get a height of 0px (because they have no content),
+ so they all bunch up together and end up loading all of them in one go.
+ */
+.placeholder {
+ block-size: 40px;
+}
+
+.videoIndex {
+ color: var(--tertiary-text-color);
+ text-align: center;
+}
+
+.videoIndexIcon {
+ font-size: 14px;
+}
diff --git a/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.js b/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.js
new file mode 100644
index 0000000000000..9ed32bb8e9a89
--- /dev/null
+++ b/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.js
@@ -0,0 +1,124 @@
+import { defineComponent } from 'vue'
+import FtListVideo from '../ft-list-video/ft-list-video.vue'
+
+export default defineComponent({
+ name: 'FtListVideoNumbered',
+ components: {
+ 'ft-list-video': FtListVideo
+ },
+ props: {
+ data: {
+ type: Object,
+ required: true
+ },
+ playlistId: {
+ type: String,
+ default: null
+ },
+ playlistType: {
+ type: String,
+ default: null
+ },
+ playlistIndex: {
+ type: Number,
+ default: null
+ },
+ playlistReverse: {
+ type: Boolean,
+ default: false
+ },
+ playlistShuffle: {
+ type: Boolean,
+ default: false
+ },
+ playlistLoop: {
+ type: Boolean,
+ default: false
+ },
+ playlistItemId: {
+ type: String,
+ default: null,
+ },
+ appearance: {
+ type: String,
+ required: true
+ },
+ initialVisibleState: {
+ type: Boolean,
+ default: false,
+ },
+ alwaysShowAddToPlaylistButton: {
+ type: Boolean,
+ default: false,
+ },
+ quickBookmarkButtonEnabled: {
+ type: Boolean,
+ default: true,
+ },
+ canMoveVideoUp: {
+ type: Boolean,
+ default: false,
+ },
+ canMoveVideoDown: {
+ type: Boolean,
+ default: false,
+ },
+ canRemoveFromPlaylist: {
+ type: Boolean,
+ default: false,
+ },
+ videoIndex: {
+ type: Number,
+ default: -1
+ },
+ isCurrentVideo: {
+ type: Boolean,
+ default: false
+ },
+ useChannelsHiddenPreference: {
+ type: Boolean,
+ default: false,
+ }
+ },
+ data: function () {
+ return {
+ visible: false,
+ show: true
+ }
+ },
+ computed: {
+ channelsHidden() {
+ // Some component users like channel view will have this disabled
+ if (!this.useChannelsHiddenPreference) { return [] }
+
+ return JSON.parse(this.$store.getters.getChannelsHidden).map((ch) => {
+ // Legacy support
+ if (typeof ch === 'string') {
+ return { name: ch, preferredName: '', icon: '' }
+ }
+ return ch
+ })
+ },
+
+ // As we only use this component in Playlist and watch-video-playlist,
+ // where title filtering is never desired, we don't have any title filtering logic here,
+ // like we do in ft-list-video-lazy
+
+ shouldBeVisible() {
+ return !(this.channelsHidden.some(ch => ch.name === this.data.authorId) ||
+ this.channelsHidden.some(ch => ch.name === this.data.author))
+ }
+ },
+ created() {
+ this.visible = this.initialVisibleState
+ },
+ methods: {
+ onVisibilityChanged: function (visible) {
+ if (visible && this.shouldBeVisible) {
+ this.visible = visible
+ } else if (visible) {
+ this.show = false
+ }
+ }
+ }
+})
diff --git a/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.vue b/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.vue
new file mode 100644
index 0000000000000..745a704fe84c5
--- /dev/null
+++ b/src/renderer/components/ft-list-video-numbered/ft-list-video-numbered.vue
@@ -0,0 +1,53 @@
+
+
+
- {{ index + 1 }}
-
- {{ index + 1 }}
-