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

Playlist performance improvements #4597

Merged
Merged
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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
}
}
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<template>
<div
v-show="show"
v-observe-visibility="!initialVisibleState ? {
callback: onVisibilityChanged,
once: true,
} : null"
:class="{ placeholder: !visible }"
>
<template
v-if="visible"
>
<p
class="videoIndex"
>
<font-awesome-icon
v-if="isCurrentVideo"
class="videoIndexIcon"
:icon="['fas', 'play']"
/>
<template
v-else
>
{{ videoIndex + 1 }}
</template>
</p>
<ft-list-video
:data="data"
:playlist-id="playlistId"
:playlist-type="playlistType"
:playlist-index="playlistIndex"
:playlist-reverse="playlistReverse"
:playlist-shuffle="playlistShuffle"
:playlist-loop="playlistLoop"
:playlist-item-id="playlistItemId"
force-list-type="list"
:appearance="appearance"
:always-show-add-to-playlist-button="alwaysShowAddToPlaylistButton"
:quick-bookmark-button-enabled="quickBookmarkButtonEnabled"
:can-move-video-up="canMoveVideoUp"
:can-move-video-down="canMoveVideoDown"
:can-remove-from-playlist="canRemoveFromPlaylist"
@pause-player="$emit('pause-player')"
@move-video-up="$emit('move-video-up')"
@move-video-down="$emit('move-video-down')"
@remove-from-playlist="$emit('remove-from-playlist')"
/>
</template>
</div>
</template>

<script src="./ft-list-video-numbered.js" />
<style scoped src="./ft-list-video-numbered.css" />
15 changes: 4 additions & 11 deletions src/renderer/components/ft-list-video/ft-list-video.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ export default defineComponent({
lengthSeconds: 0,
duration: '',
description: '',
watched: false,
watchProgress: 0,
publishedText: '',
isLive: false,
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -343,7 +342,7 @@ export default defineComponent({
},

addWatchedStyle: function () {
return this.watched && !this.inHistory
return this.historyEntryExists && !this.inHistory
},

externalPlayer: function () {
Expand Down Expand Up @@ -576,15 +575,15 @@ export default defineComponent({
}
this.openInExternalPlayer(payload)

if (this.saveWatchedProgress && !this.watched) {
if (this.saveWatchedProgress && !this.historyEntryExists) {
this.markAsWatched()
}
},

handleOptionsClick: function (option) {
switch (option) {
case 'history':
if (this.watched) {
if (this.historyEntryExists) {
this.removeFromWatched()
} else {
this.markAsWatched()
Expand Down Expand Up @@ -727,8 +726,6 @@ export default defineComponent({

checkIfWatched: function () {
if (this.historyEntryExists) {
this.watched = true

const historyEntry = this.historyEntry

if (this.saveWatchedProgress) {
Expand All @@ -744,7 +741,6 @@ export default defineComponent({
this.publishedText = ''
}
} else {
this.watched = false
this.watchProgress = 0
}
},
Expand All @@ -766,16 +762,13 @@ export default defineComponent({
}
this.updateHistory(videoData)
showToast(this.$t('Video.Video has been marked as watched'))

this.watched = true
},

removeFromWatched: function () {
this.removeFromHistory(this.id)

showToast(this.$t('Video.Video has been removed from your history'))

this.watched = false
this.watchProgress = 0
},

Expand Down
17 changes: 9 additions & 8 deletions src/renderer/components/ft-list-video/ft-list-video.vue
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
{{ $t("Video.Watched") }}
</div>
<div
v-if="watched"
v-if="historyEntryExists"
class="watchedProgressBar"
:style="{inlineSize: progressPercentage + '%'}"
/>
Expand All @@ -129,12 +129,13 @@
<span v-else-if="channelName !== null">
{{ channelName }}
</span>
<template v-if="!isLive && !isUpcoming && !isPremium && !hideViews && viewCount != null">
<span class="viewCount">
<template v-if="channelId !== null"> • </template>
{{ $tc('Global.Counts.View Count', viewCount, {count: parsedViewCount}) }}
</span>
</template>
<span
v-if="!isLive && !isUpcoming && !isPremium && !hideViews && viewCount != null"
class="viewCount"
>
<template v-if="channelId !== null || channelName !== null"> • </template>
{{ $tc('Global.Counts.View Count', viewCount, {count: parsedViewCount}) }}
</span>
<span
v-if="uploadedTime !== '' && !isLive && !inHistory"
class="uploadedTime"
Expand All @@ -160,7 +161,7 @@
@click="handleOptionsClick"
/>
<p
v-if="((listType === 'list' || forceListType === 'list') && forceListType !== 'grid') &&
v-if="description && ((listType === 'list' || forceListType === 'list') && forceListType !== 'grid') &&
appearance === 'result'"
class="description"
v-html="description"
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/playlist-info/playlist-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,6 @@
transition: background 0.2s ease-in;
}

.videoIndexContainer {
text-align: center;
}

.videoIndex {
color: var(--tertiary-text-color);
}

.videoIndexIcon {
font-size: 14px;
color: var(--tertiary-text-color);
}

.videoInfo {
margin-inline-start: 30px;
position: relative;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineComponent, nextTick } from 'vue'
import { mapMutations } from 'vuex'
import FtLoader from '../ft-loader/ft-loader.vue'
import FtCard from '../ft-card/ft-card.vue'
import FtListVideoLazy from '../ft-list-video-lazy/ft-list-video-lazy.vue'
import FtListVideoNumbered from '../ft-list-video-numbered/ft-list-video-numbered.vue'
import { copyToClipboard, showToast } from '../../helpers/utils'
import {
getLocalPlaylist,
Expand All @@ -16,7 +16,7 @@ export default defineComponent({
components: {
'ft-loader': FtLoader,
'ft-card': FtCard,
'ft-list-video-lazy': FtListVideoLazy,
'ft-list-video-numbered': FtListVideoNumbered
},
props: {
playlistId: {
Expand Down Expand Up @@ -471,14 +471,13 @@ export default defineComponent({
parseUserPlaylist: function (playlist, { allowPlayingVideoRemoval = true } = {}) {
this.playlistTitle = playlist.playlistName
this.channelName = ''
this.channelThumbnail = ''
this.channelId = ''

if (this.playlistItems.length === 0 || allowPlayingVideoRemoval) {
this.playlistItems = playlist.videos
} else {
// `this.currentVideo` relies on `playlistItems`
const latestPlaylistContainsCurrentVideo = playlist.videos.find(v => v.playlistItemId === this.playlistItemId) != null
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
Expand Down Expand Up @@ -511,7 +510,7 @@ export default defineComponent({
const currentVideoItem = (this.$refs.currentVideoItem || [])[0]
if (container != null && currentVideoItem != null) {
// Watch view can be ready sooner than this component
container.scrollTop = currentVideoItem.offsetTop - container.offsetTop
container.scrollTop = currentVideoItem.$el.offsetTop - container.offsetTop
}
},

Expand Down
Loading
Loading