From 2a7bf560358bab61ba25d258fd634a560fca4ca6 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 16 May 2023 14:30:45 +0800
Subject: [PATCH 001/236] (Replicate) Push up batch 1 of playlist functionality
---
src/datastores/handlers/base.js | 4 +
src/datastores/handlers/electron.js | 7 +
src/datastores/handlers/web.js | 4 +
src/main/index.js | 9 +
.../ft-list-playlist/ft-list-playlist.js | 15 +-
.../components/playlist-info/playlist-info.js | 158 +++++++++++-------
.../playlist-info/playlist-info.vue | 88 +++++++++-
.../watch-video-playlist.js | 22 +++
.../watch-video-playlist.vue | 5 +-
src/renderer/store/modules/playlists.js | 70 +++++++-
src/renderer/views/Playlist/Playlist.css | 4 +
src/renderer/views/Playlist/Playlist.js | 97 +++++++++--
src/renderer/views/Playlist/Playlist.vue | 81 +++++----
.../views/UserPlaylists/UserPlaylists.js | 70 ++++----
.../views/UserPlaylists/UserPlaylists.vue | 5 -
15 files changed, 492 insertions(+), 147 deletions(-)
diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js
index 11eebc32e2d0e..f5595715afcc9 100644
--- a/src/datastores/handlers/base.js
+++ b/src/datastores/handlers/base.js
@@ -108,6 +108,10 @@ class Playlists {
return db.playlists.find({})
}
+ static upsert(playlist) {
+ return db.profiles.update({ _id: playlist._id }, playlist, { upsert: true })
+ }
+
static upsertVideoByPlaylistName(playlistName, videoData) {
return db.playlists.update(
{ playlistName },
diff --git a/src/datastores/handlers/electron.js b/src/datastores/handlers/electron.js
index ddb90ff82434e..98d76b5435bbe 100644
--- a/src/datastores/handlers/electron.js
+++ b/src/datastores/handlers/electron.js
@@ -126,6 +126,13 @@ class Playlists {
)
}
+ static upsert(playlist) {
+ return ipcRenderer.invoke(
+ IpcChannels.DB_PLAYLISTS,
+ { action: DBActions.GENERAL.UPSERT, data: playlist }
+ )
+ }
+
static upsertVideoByPlaylistName(playlistName, videoData) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
diff --git a/src/datastores/handlers/web.js b/src/datastores/handlers/web.js
index a81eb305d1dd9..e781e01b10a16 100644
--- a/src/datastores/handlers/web.js
+++ b/src/datastores/handlers/web.js
@@ -81,6 +81,10 @@ class Playlists {
return baseHandlers.playlists.find()
}
+ static upsert(playlist) {
+ return baseHandlers.playlists.upsert(playlist)
+ }
+
static upsertVideoByPlaylistName(playlistName, videoData) {
return baseHandlers.playlists.upsertVideoByPlaylistName(playlistName, videoData)
}
diff --git a/src/main/index.js b/src/main/index.js
index 9d44efd68020f..bffdf946c7f23 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -897,6 +897,15 @@ function runApp() {
case DBActions.GENERAL.FIND:
return await baseHandlers.playlists.find()
+ case DBActions.GENERAL.UPSERT:
+ await baseHandlers.playlists.upsert(data)
+ syncOtherWindows(
+ IpcChannels.SYNC_PLAYLISTS,
+ event,
+ { event: SyncEvents.PLAYLISTS.UPSERT, data }
+ )
+ return null
+
case DBActions.PLAYLISTS.UPSERT_VIDEO:
await baseHandlers.playlists.upsertVideoByPlaylistName(data.playlistName, data.videoData)
syncOtherWindows(
diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.js b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
index 5eb0532e5bc48..6788a69759531 100644
--- a/src/renderer/components/ft-list-playlist/ft-list-playlist.js
+++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
@@ -45,7 +45,9 @@ export default defineComponent({
}
},
created: function () {
- if (this.data.dataSource === 'local') {
+ if (this.data._id != null) {
+ this.parseUserData()
+ } else if (this.data.dataSource === 'local') {
this.parseLocalData()
} else {
this.parseInvidiousData()
@@ -87,6 +89,17 @@ export default defineComponent({
this.videoCount = this.data.videoCount
},
+ parseUserData: function () {
+ this.title = this.data.title
+ if (this.data.videos.length > 0) {
+ this.thumbnail = `https://i.ytimg.com/vi/${this.data.videos[0].videoId}/mqdefault.jpg`
+ } else {
+ this.thumbnail = 'https://i.ytimg.com/vi/aaaaaa/mqdefault.jpg'
+ }
+ this.channelName = ''
+ this.videoCount = this.data.videoCount
+ },
+
...mapActions([
'openInExternalPlayer'
])
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 907417ba58431..2b5d0656749f9 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -1,35 +1,73 @@
import { defineComponent } from 'vue'
+import { mapActions } from 'vuex'
import FtShareButton from '../ft-share-button/ft-share-button.vue'
-import { copyToClipboard, formatNumber, openExternalLink } from '../../helpers/utils'
+import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
+import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
+import FtInput from '../ft-input/ft-input.vue'
export default defineComponent({
name: 'PlaylistInfo',
components: {
- 'ft-share-button': FtShareButton
+ 'ft-share-button': FtShareButton,
+ 'ft-flex-box': FtFlexBox,
+ 'ft-icon-button': FtIconButton,
+ 'ft-input': FtInput,
},
props: {
- data: {
- type: Object,
- required: true
- }
+ id: {
+ type: String,
+ required: true,
+ },
+ firstVideoId: {
+ type: String,
+ required: true,
+ },
+ title: {
+ type: String,
+ required: true,
+ },
+ channelThumbnail: {
+ type: String,
+ required: true,
+ },
+ channelName: {
+ type: String,
+ required: true,
+ },
+ channelId: {
+ type: String,
+ required: true,
+ },
+ videoCount: {
+ type: Number,
+ required: true,
+ },
+ viewCount: {
+ type: Number,
+ required: true,
+ },
+ lastUpdated: {
+ type: String,
+ default: undefined,
+ },
+ description: {
+ type: String,
+ required: true,
+ },
+ infoSource: {
+ type: String,
+ required: true,
+ },
},
data: function () {
return {
- id: '',
- firstVideoId: '',
- title: '',
- channelThumbnail: '',
- channelName: '',
- channelId: '',
- videoCount: 0,
- viewCount: 0,
- lastUpdated: '',
- description: '',
- infoSource: ''
+ editMode: false,
+ newTitle: '',
+ newDescription: '',
}
},
computed: {
- hideSharingActions: function() {
+ hideSharingActions: function () {
return this.$store.getters.getHideSharingActions
},
@@ -49,6 +87,14 @@ export default defineComponent({
return this.$store.getters.getHideVideoViews
},
+ userPlaylists: function () {
+ return this.$store.getters.getAllPlaylists
+ },
+
+ selectedPlaylist: function () {
+ return this.userPlaylists.find((playlist) => playlist._id === this.id)
+ },
+
thumbnail: function () {
let baseUrl
if (this.backendPreference === 'invidious') {
@@ -67,49 +113,49 @@ export default defineComponent({
default:
return `${baseUrl}/vi/${this.firstVideoId}/mqdefault.jpg`
}
- }
+ },
},
mounted: function () {
- this.id = this.data.id
- this.firstVideoId = this.data.firstVideoId
- this.title = this.data.title
- this.channelName = this.data.channelName
- this.channelThumbnail = this.data.channelThumbnail
- this.channelId = this.data.channelId
- this.uploadedTime = this.data.uploaded_at
- this.description = this.data.description
- this.infoSource = this.data.infoSource
+ this.newTitle = this.title
+ this.newDescription = this.description
// Causes errors if not put inside of a check
- if (typeof (this.data.viewCount) !== 'undefined' && !isNaN(this.data.viewCount)) {
- this.viewCount = this.hideViews ? null : formatNumber(this.data.viewCount)
- }
-
- if (typeof (this.data.videoCount) !== 'undefined' && !isNaN(this.data.videoCount)) {
- this.videoCount = formatNumber(this.data.videoCount)
- }
-
- this.lastUpdated = this.data.lastUpdated
+ // if (
+ // typeof this.data.viewCount !== 'undefined' &&
+ // !isNaN(this.data.viewCount)
+ // ) {
+ // this.viewCount = this.hideViews ? null : formatNumber(this.data.viewCount)
+ // }
+ //
+ // if (
+ // typeof this.data.videoCount !== 'undefined' &&
+ // !isNaN(this.data.videoCount)
+ // ) {
+ // this.videoCount = formatNumber(this.data.videoCount)
+ // }
+ //
+ // this.lastUpdated = this.data.lastUpdated
},
methods: {
- sharePlaylist: function (method) {
- const youtubeUrl = `https://youtube.com/playlist?list=${this.id}`
- const invidiousUrl = `${this.currentInvidiousInstance}/playlist?list=${this.id}`
-
- switch (method) {
- case 'copyYoutube':
- copyToClipboard(youtubeUrl, { messageOnSuccess: this.$t('Share.YouTube URL copied to clipboard') })
- break
- case 'openYoutube':
- openExternalLink(youtubeUrl)
- break
- case 'copyInvidious':
- copyToClipboard(invidiousUrl, { messageOnSuccess: this.$t('Share.Invidious URL copied to clipboard') })
- break
- case 'openInvidious':
- openExternalLink(invidiousUrl)
- break
+ savePlaylistInfo: function () {
+ const playlist = {
+ playlistName: this.newTitle,
+ protected: this.selectedPlaylist.protected,
+ removeOnWatched: this.selectedPlaylist.removeOnWatched,
+ description: this.newDescription,
+ videos: this.selectedPlaylist.videos,
+ _id: this.id,
}
- }
- }
+ this.updatePlaylist(playlist)
+ this.cancelEditMode()
+ },
+
+ cancelEditMode: function () {
+ this.newTitle = this.title
+ this.newDescription = this.description
+ this.editMode = false
+ },
+
+ ...mapActions(['updatePlaylist']),
+ },
})
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index d7a2083de7c37..fd5cc613d6a34 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -18,19 +18,45 @@
-
+ (newTitle = input)"
+ />
+
{{ title }}
- {{ videoCount }} {{ $t("Playlist.Videos") }} - {{ viewCount }} {{ $t("Playlist.Views") }} -
-
- {{ $t("Playlist.Last Updated On") }}
+ {{ videoCount }} {{ $t("Playlist.Videos") }}
+
+ - {{ viewCount }} {{ $t("Playlist.Views") }}
+
+
+ -
+
+ {{ $t("Playlist.Last Updated On") }}
+
+ {{ lastUpdated }}
- {{ lastUpdated }}
+ newDescription = input"
+ />
@@ -41,6 +67,7 @@
class="channelShareWrapper"
>
@@ -56,6 +83,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
playlist._id === this.playlistId)
+ },
+
currentVideoIndex: function () {
const index = this.playlistItems.findIndex((item) => {
if (typeof item.videoId !== 'undefined') {
@@ -135,6 +143,8 @@ export default defineComponent({
if (cachedPlaylist?.id === this.playlistId) {
this.loadCachedPlaylistInformation(cachedPlaylist)
+ } else if (this.selectedPlaylist != null) {
+ this.parseUserPlaylist(this.selectedPlaylist)
} else if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
this.getPlaylistInformationInvidious()
} else {
@@ -390,6 +400,18 @@ export default defineComponent({
})
},
+ parseUserPlaylist: function (playlist) {
+ this.playlistTitle = playlist.title
+ this.videoCount = playlist.videoCount
+ this.channelName = playlist.author ? playlist.author.name : ''
+ this.channelThumbnail = playlist.author ? playlist.author.bestAvatar.url : ''
+ this.channelId = playlist.author ? playlist.author.channelID : ''
+
+ this.playlistItems = playlist.videos
+
+ this.isLoading = false
+ },
+
shufflePlaylistItems: function () {
// Prevents the array from affecting the original object
const remainingItems = [].concat(this.playlistItems)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
index 4c2e23db8c0f7..d3053c621ce9c 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
@@ -15,15 +15,16 @@
- {{ channelName }}
+ {{ channelName }} -
- - {{ currentVideoIndex }} / {{ playlistVideoCount }}
+ {{ currentVideoIndex }} / {{ playlistVideoCount }}
>')
+ console.log({ payload })
if (payload.length === 0) {
commit('setAllPlaylists', state.playlists)
dispatch('addPlaylists', payload)
+ dispatch('addPlaylists', state.playlists)
} else {
+ const findFavorites = payload.filter((playlist) => {
+ return playlist.playlistName === 'Favorites' || playlist._id === 'favorites'
+ })
+ const findWatchLater = payload.filter((playlist) => {
+ return playlist.playlistName === 'Watch Later' || playlist._id === 'watchLater'
+ })
+
+ if (findFavorites.length === 0) {
+ dispatch('addPlaylist', state.playlists[0])
+ payload.push(state.playlists[0])
+ } else {
+ const favoritesPlaylist = findFavorites[0]
+
+ if (favoritesPlaylist._id !== 'favorites') {
+ const oldId = favoritesPlaylist._id
+ favoritesPlaylist._id = 'favorites'
+ dispatch('addPlaylist', favoritesPlaylist)
+ dispatch('removePlaylist', oldId)
+ }
+ }
+
+ if (findWatchLater.length === 0) {
+ dispatch('addPlaylist', state.playlists[1])
+ payload.push(state.playlists[1])
+ } else {
+ const watchLaterPlaylist = findFavorites[0]
+
+ if (watchLaterPlaylist._id !== 'favorites') {
+ const oldId = watchLaterPlaylist._id
+ watchLaterPlaylist._id = 'favorites'
+ dispatch('addPlaylist', watchLaterPlaylist)
+ dispatch('removePlaylist', oldId)
+ }
+ }
+
commit('setAllPlaylists', payload)
}
} catch (errMessage) {
@@ -142,6 +194,18 @@ const mutations = {
state.playlists = state.playlists.concat(payload)
},
+ upsertPlaylistToList(state, updatedPlaylist) {
+ const i = state.playlists.findIndex((p) => {
+ return p._id === updatedPlaylist._id
+ })
+
+ if (i === -1) {
+ state.playlists.push(updatedPlaylist)
+ } else {
+ state.playlists.splice(i, 1, updatedPlaylist)
+ }
+ },
+
addVideo(state, payload) {
const playlist = state.playlists.find(playlist => playlist.playlistName === payload.playlistName)
if (playlist) {
diff --git a/src/renderer/views/Playlist/Playlist.css b/src/renderer/views/Playlist/Playlist.css
index f762bfc71f93d..7b2414b74014a 100644
--- a/src/renderer/views/Playlist/Playlist.css
+++ b/src/renderer/views/Playlist/Playlist.css
@@ -70,3 +70,7 @@
max-width: 35vw;
}
}
+
+.message {
+ color: var(--tertiary-text-color);
+}
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 8551c4f27289f..0c98dd84639d8 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -36,11 +36,20 @@ export default defineComponent({
data: function () {
return {
isLoading: false,
- playlistId: null,
- infoData: {},
+ playlistId: '',
+ playlistTitle: '',
+ playlistDescription: '',
+ firstVideoId: '',
+ viewCount: 0,
+ videoCount: 0,
+ lastUpdated: undefined,
+ channelName: '',
+ channelThumbnail: '',
+ channelId: '',
+ infoSource: 'local',
playlistItems: [],
continuationData: null,
- isLoadingMore: false
+ isLoadingMore: false,
}
},
computed: {
@@ -55,21 +64,33 @@ export default defineComponent({
},
currentLocale: function () {
return this.$i18n.locale.replace('_', '-')
- }
+ },
+ userPlaylists: function () {
+ return this.$store.getters.getAllPlaylists
+ },
+ selectedPlaylist: function () {
+ return this.userPlaylists.find(playlist => playlist._id === this.playlistId)
+ },
},
watch: {
$route () {
// react to route changes...
- this.getPlaylist()
+ this.getPlaylistInfo()
}
},
mounted: function () {
- this.getPlaylist()
+ this.getPlaylistInfo()
},
methods: {
- getPlaylist: function () {
+ getPlaylistInfo: function () {
+ this.isLoading = true
this.playlistId = this.$route.params.id
+ if (this.selectedPlaylist != null) {
+ this.parseUserPlaylist(this.selectedPlaylist)
+ return
+ }
+
switch (this.backendPreference) {
case 'local':
this.getPlaylistLocal()
@@ -80,8 +101,6 @@ export default defineComponent({
}
},
getPlaylistLocal: function () {
- this.isLoading = true
-
getLocalPlaylist(this.playlistId).then((result) => {
this.infoData = {
id: this.playlistId,
@@ -97,10 +116,22 @@ export default defineComponent({
infoSource: 'local'
}
+ this.playlistId = result.id
+ this.playlistTitle = result.title
+ this.playlistDescription = result.info.description ?? ''
+ this.firstVideoId = result.items[0].id
+ this.viewCount = extractNumberFromString(result.info.views)
+ this.videoCount = extractNumberFromString(result.info.total_items)
+ this.lastUpdated = result.info.last_updated ?? ''
+ this.channelName = result.info.author?.name ?? ''
+ this.channelThumbnail = result.info.author?.best_thumbnail?.url ?? ''
+ this.channelId = result.info.author?.id
+ this.infoSource = 'local'
+
this.updateSubscriptionDetails({
- channelThumbnailUrl: this.infoData.channelThumbnail,
- channelName: this.infoData.channelName,
- channelId: this.infoData.channelId
+ channelThumbnailUrl: this.channelThumbnail,
+ channelName: this.channelName,
+ channelId: this.channelId
})
this.playlistItems = result.items.map(parseLocalPlaylistVideo)
@@ -122,8 +153,6 @@ export default defineComponent({
},
getPlaylistInvidious: function () {
- this.isLoading = true
-
invidiousGetPlaylistInfo(this.playlistId).then((result) => {
this.infoData = {
id: result.playlistId,
@@ -138,14 +167,25 @@ export default defineComponent({
infoSource: 'invidious'
}
+ this.id = result.playlistId
+ this.title = result.title
+ this.description = result.description
+ this.firstVideoId = result.videos[0].videoId
+ this.viewCount = result.viewCount
+ this.videoCount = result.videoCount
+ this.channelName = result.author
+ this.channelThumbnail = youtubeImageUrlToInvidious(result.authorThumbnails[2].url, this.currentInvidiousInstance)
+ this.channelId = result.authorId
+ this.infoSource = 'invidious'
+
this.updateSubscriptionDetails({
channelThumbnailUrl: result.authorThumbnails[2].url,
- channelName: this.infoData.channelName,
- channelId: this.infoData.channelId
+ channelName: this.channelName,
+ channelId: this.channelId
})
const dateString = new Date(result.updated * 1000)
- this.infoData.lastUpdated = dateString.toLocaleDateString(this.currentLocale, { year: 'numeric', month: 'short', day: 'numeric' })
+ this.lastUpdated = dateString.toLocaleDateString(this.currentLocale, { year: 'numeric', month: 'short', day: 'numeric' })
this.playlistItems = this.playlistItems.concat(result.videos)
@@ -162,6 +202,29 @@ export default defineComponent({
})
},
+ parseUserPlaylist: function (playlist) {
+ this.playlistId = playlist._id
+ this.playlistTitle = playlist.title
+ this.playlistDescription = playlist.description
+
+ if (playlist.videos.length > 0) {
+ this.firstVideoId = playlist.videos[0].videoId
+ } else {
+ this.firstVideoId = ''
+ }
+ this.viewCount = 0
+ this.videoCount = playlist.videoCount
+ this.lastUpdated = undefined
+ this.channelName = playlist.author ? playlist.author.name : ''
+ this.channelThumbnail = playlist.author ? playlist.author.bestAvatar.url : ''
+ this.channelId = playlist.author ? playlist.author.channelID : ''
+ this.infoSource = 'user'
+
+ this.playlistItems = playlist.videos
+
+ this.isLoading = false
+ },
+
getNextPage: function () {
switch (this.infoData.infoSource) {
case 'local':
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index b7d60a8c774d7..db1abb3ae4aaf 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -7,7 +7,17 @@
@@ -15,40 +25,51 @@
v-if="!isLoading"
class="playlistItems"
>
-
-
- {{ index + 1 }}
-
-
-
+
+ {{ index + 1 }}
+
+
+
+
+
+
+
+
+
+
-
+
+ This playlist currently has no videos.
+
-
-
-
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index b3477dbc13657..ff57605d552da 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -34,9 +34,23 @@ export default defineComponent({
return this.$store.getters.getFavorites
},
+ allPlaylists: function () {
+ return this.$store.getters.getAllPlaylists.map((playlist) => {
+ playlist.title = playlist.playlistName
+ playlist.type = 'playlist'
+ playlist.thumbnail = ''
+ playlist.channelName = ''
+ playlist.channelId = ''
+ playlist.playlistId = ''
+ playlist.description = playlist.description ? playlist.description : ''
+ playlist.videoCount = playlist.videos.length
+ return playlist
+ })
+ },
+
fullData: function () {
- const data = [].concat(this.favoritesPlaylist.videos).reverse()
- if (this.favoritesPlaylist.videos.length < this.dataLimit) {
+ const data = this.allPlaylists
+ if (this.allPlaylists.length < this.dataLimit) {
return data
} else {
return data.slice(0, this.dataLimit)
@@ -62,7 +76,7 @@ export default defineComponent({
this.activeData = this.fullData
- if (this.activeData.length < this.favoritesPlaylist.videos.length) {
+ if (this.activeData.length < this.allPlaylists.length) {
this.showLoadMoreButton = true
} else {
this.showLoadMoreButton = false
@@ -86,31 +100,31 @@ export default defineComponent({
this.filterPlaylistDebounce()
},
filterPlaylist: function() {
- if (this.query === '') {
- this.activeData = this.fullData
- if (this.activeData.length < this.favoritesPlaylist.videos.length) {
- this.showLoadMoreButton = true
- } else {
- this.showLoadMoreButton = false
- }
- } else {
- const lowerCaseQuery = this.query.toLowerCase()
- const filteredQuery = this.favoritesPlaylist.videos.filter((video) => {
- if (typeof (video.title) !== 'string' || typeof (video.author) !== 'string') {
- return false
- } else {
- return video.title.toLowerCase().includes(lowerCaseQuery) || video.author.toLowerCase().includes(lowerCaseQuery)
- }
- }).sort((a, b) => {
- return b.timeAdded - a.timeAdded
- })
- if (filteredQuery.length <= this.searchDataLimit) {
- this.showLoadMoreButton = false
- } else {
- this.showLoadMoreButton = true
- }
- this.activeData = filteredQuery.length < this.searchDataLimit ? filteredQuery : filteredQuery.slice(0, this.searchDataLimit)
- }
+ // if (this.query === '') {
+ // this.activeData = this.fullData
+ // if (this.activeData.length < this.allPlaylists.length) {
+ // this.showLoadMoreButton = true
+ // } else {
+ // this.showLoadMoreButton = false
+ // }
+ // } else {
+ // const lowerCaseQuery = this.query.toLowerCase()
+ // const filteredQuery = this.favoritesPlaylist.videos.filter((video) => {
+ // if (typeof (video.title) !== 'string' || typeof (video.author) !== 'string') {
+ // return false
+ // } else {
+ // return video.title.toLowerCase().includes(lowerCaseQuery) || video.author.toLowerCase().includes(lowerCaseQuery)
+ // }
+ // }).sort((a, b) => {
+ // return b.timeAdded - a.timeAdded
+ // })
+ // if (filteredQuery.length <= this.searchDataLimit) {
+ // this.showLoadMoreButton = false
+ // } else {
+ // this.showLoadMoreButton = true
+ // }
+ // this.activeData = filteredQuery.length < this.searchDataLimit ? filteredQuery : filteredQuery.slice(0, this.searchDataLimit)
+ // }
},
}
})
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index 09097ef8f2186..d2f8660a2491c 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -10,11 +10,6 @@
>
{{ $t("User Playlists.Your Playlists") }}
-
Date: Tue, 16 May 2023 15:20:02 +0800
Subject: [PATCH 002/236] (Replicate) Push up batch two of playlists
functionality
---
src/constants.js | 1 +
src/datastores/handlers/base.js | 18 +-
src/datastores/handlers/electron.js | 18 +-
src/datastores/handlers/web.js | 16 +-
src/main/index.js | 10 +-
.../components/ft-list-video/ft-list-video.js | 57 +++-
.../ft-list-video/ft-list-video.vue | 11 +-
.../ft-playlist-add-video-prompt.css | 23 ++
.../ft-playlist-add-video-prompt.js | 88 ++++++
.../ft-playlist-add-video-prompt.vue | 34 +++
.../ft-playlist-selector.js | 62 +++++
.../ft-playlist-selector.scss | 254 ++++++++++++++++++
.../ft-playlist-selector.vue | 41 +++
.../components/ft-prompt/ft-prompt.css | 6 +-
.../components/playlist-info/playlist-info.js | 10 +-
.../playlist-info/playlist-info.vue | 4 +-
src/renderer/scss-partials/_ft-list-item.scss | 9 +
src/renderer/store/modules/playlists.js | 41 ++-
src/renderer/store/modules/settings.js | 4 +
src/renderer/store/modules/utils.js | 27 ++
src/renderer/views/Playlist/Playlist.js | 11 +-
.../views/UserPlaylists/UserPlaylists.js | 8 +-
22 files changed, 674 insertions(+), 79 deletions(-)
create mode 100644 src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
create mode 100644 src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
create mode 100644 src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
create mode 100644 src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
create mode 100644 src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
create mode 100644 src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue
diff --git a/src/constants.js b/src/constants.js
index bd80da2ffdc17..cc82cdcce9cf0 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -65,6 +65,7 @@ const SyncEvents = {
},
PLAYLISTS: {
+ UPSERT: 'sync-playlists-upsert',
UPSERT_VIDEO: 'sync-playlists-upsert-video',
DELETE_VIDEO: 'sync-playlists-delete-video'
}
diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js
index f5595715afcc9..f9f110e3f7e7c 100644
--- a/src/datastores/handlers/base.js
+++ b/src/datastores/handlers/base.js
@@ -109,12 +109,12 @@ class Playlists {
}
static upsert(playlist) {
- return db.profiles.update({ _id: playlist._id }, playlist, { upsert: true })
+ return db.playlists.update({ _id: playlist._id }, playlist, { upsert: true })
}
- static upsertVideoByPlaylistName(playlistName, videoData) {
+ static upsertVideoByPlaylistId(_id, videoData) {
return db.playlists.update(
- { playlistName },
+ { _id },
{ $push: { videos: videoData } },
{ upsert: true }
)
@@ -132,25 +132,25 @@ class Playlists {
return db.playlists.remove({ _id, protected: { $ne: true } })
}
- static deleteVideoIdByPlaylistName(playlistName, videoId) {
+ static deleteVideoIdByPlaylistId(_id, videoId) {
return db.playlists.update(
- { playlistName },
+ { _id },
{ $pull: { videos: { videoId } } },
{ upsert: true }
)
}
- static deleteVideoIdsByPlaylistName(playlistName, videoIds) {
+ static deleteVideoIdsByPlaylistId(_id, videoIds) {
return db.playlists.update(
- { playlistName },
+ { _id },
{ $pull: { videos: { $in: videoIds } } },
{ upsert: true }
)
}
- static deleteAllVideosByPlaylistName(playlistName) {
+ static deleteAllVideosByPlaylistId(_id) {
return db.playlists.update(
- { playlistName },
+ { _id },
{ $set: { videos: [] } },
{ upsert: true }
)
diff --git a/src/datastores/handlers/electron.js b/src/datastores/handlers/electron.js
index 98d76b5435bbe..caba5752ff406 100644
--- a/src/datastores/handlers/electron.js
+++ b/src/datastores/handlers/electron.js
@@ -129,16 +129,16 @@ class Playlists {
static upsert(playlist) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
- { action: DBActions.GENERAL.UPSERT, data: playlist }
+ { action: DBActions.PLAYLISTS.UPSERT, data: playlist }
)
}
- static upsertVideoByPlaylistName(playlistName, videoData) {
+ static upsertVideoByPlaylistId(_id, videoData) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
{
action: DBActions.PLAYLISTS.UPSERT_VIDEO,
- data: { playlistName, videoData }
+ data: { _id, videoData }
}
)
}
@@ -160,32 +160,32 @@ class Playlists {
)
}
- static deleteVideoIdByPlaylistName(playlistName, videoId) {
+ static deleteVideoIdByPlaylistId(_id, videoId) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
{
action: DBActions.PLAYLISTS.DELETE_VIDEO_ID,
- data: { playlistName, videoId }
+ data: { _id, videoId }
}
)
}
- static deleteVideoIdsByPlaylistName(playlistName, videoIds) {
+ static deleteVideoIdsByPlaylistId(_id, videoIds) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
{
action: DBActions.PLAYLISTS.DELETE_VIDEO_IDS,
- data: { playlistName, videoIds }
+ data: { _id, videoIds }
}
)
}
- static deleteAllVideosByPlaylistName(playlistName) {
+ static deleteAllVideosByPlaylistId(_id) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
{
action: DBActions.PLAYLISTS.DELETE_ALL_VIDEOS,
- data: playlistName
+ data: _id
}
)
}
diff --git a/src/datastores/handlers/web.js b/src/datastores/handlers/web.js
index e781e01b10a16..16ccc5c5bbb44 100644
--- a/src/datastores/handlers/web.js
+++ b/src/datastores/handlers/web.js
@@ -85,8 +85,8 @@ class Playlists {
return baseHandlers.playlists.upsert(playlist)
}
- static upsertVideoByPlaylistName(playlistName, videoData) {
- return baseHandlers.playlists.upsertVideoByPlaylistName(playlistName, videoData)
+ static upsertVideoByPlaylistId(_id, videoData) {
+ return baseHandlers.playlists.upsertVideoByPlaylistId(_id, videoData)
}
static upsertVideoIdsByPlaylistId(_id, videoIds) {
@@ -97,16 +97,16 @@ class Playlists {
return baseHandlers.playlists.delete(_id)
}
- static deleteVideoIdByPlaylistName(playlistName, videoId) {
- return baseHandlers.playlists.deleteVideoIdByPlaylistName(playlistName, videoId)
+ static deleteVideoIdByPlaylistId(_id, videoId) {
+ return baseHandlers.playlists.deleteVideoIdByPlaylistId(_id, videoId)
}
- static deleteVideoIdsByPlaylistName(playlistName, videoIds) {
- return baseHandlers.playlists.deleteVideoIdsByPlaylistName(playlistName, videoIds)
+ static deleteVideoIdsByPlaylistId(_id, videoIds) {
+ return baseHandlers.playlists.deleteVideoIdsByPlaylistId(_id, videoIds)
}
- static deleteAllVideosByPlaylistName(playlistName) {
- return baseHandlers.playlists.deleteAllVideosByPlaylistName(playlistName)
+ static deleteAllVideosByPlaylistId(_id) {
+ return baseHandlers.playlists.deleteAllVideosByPlaylistId(_id)
}
static deleteMultiple(ids) {
diff --git a/src/main/index.js b/src/main/index.js
index bffdf946c7f23..da1d603f9f852 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -897,7 +897,7 @@ function runApp() {
case DBActions.GENERAL.FIND:
return await baseHandlers.playlists.find()
- case DBActions.GENERAL.UPSERT:
+ case DBActions.PLAYLISTS.UPSERT:
await baseHandlers.playlists.upsert(data)
syncOtherWindows(
IpcChannels.SYNC_PLAYLISTS,
@@ -907,7 +907,7 @@ function runApp() {
return null
case DBActions.PLAYLISTS.UPSERT_VIDEO:
- await baseHandlers.playlists.upsertVideoByPlaylistName(data.playlistName, data.videoData)
+ await baseHandlers.playlists.upsertVideoByPlaylistId(data._id, data.videoData)
syncOtherWindows(
IpcChannels.SYNC_PLAYLISTS,
event,
@@ -928,7 +928,7 @@ function runApp() {
return null
case DBActions.PLAYLISTS.DELETE_VIDEO_ID:
- await baseHandlers.playlists.deleteVideoIdByPlaylistName(data.playlistName, data.videoId)
+ await baseHandlers.playlists.deleteVideoIdByPlaylistId(data._id, data.videoId)
syncOtherWindows(
IpcChannels.SYNC_PLAYLISTS,
event,
@@ -937,13 +937,13 @@ function runApp() {
return null
case DBActions.PLAYLISTS.DELETE_VIDEO_IDS:
- await baseHandlers.playlists.deleteVideoIdsByPlaylistName(data.playlistName, data.videoIds)
+ await baseHandlers.playlists.deleteVideoIdsByPlaylistId(data._id, data.videoIds)
// TODO: Syncing (implement only when it starts being used)
// syncOtherWindows(IpcChannels.SYNC_PLAYLISTS, event, { event: '_', data })
return null
case DBActions.PLAYLISTS.DELETE_ALL_VIDEOS:
- await baseHandlers.playlists.deleteAllVideosByPlaylistName(data)
+ await baseHandlers.playlists.deleteAllVideosByPlaylistId(data)
// TODO: Syncing (implement only when it starts being used)
// syncOtherWindows(IpcChannels.SYNC_PLAYLISTS, event, { event: '_', data })
return null
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 df374042a5dba..7b0cd23873070 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -347,11 +347,32 @@ export default defineComponent({
}
},
- toggleSave: function () {
+ addToPlaylist: function () {
+ const videoData = {
+ videoId: this.id,
+ title: this.title,
+ author: this.channelName,
+ authorId: this.channelId,
+ published: '',
+ description: this.description,
+ viewCount: this.viewCount,
+ lengthSeconds: this.data.lengthSeconds,
+ timeAdded: new Date().getTime(),
+ isLive: false,
+ paid: false,
+ type: 'video'
+ }
+
+ this.$emit('add-to-playlist', videoData)
+ },
+
+ toggleFavorite: function () {
if (this.inFavoritesPlaylist) {
- this.removeFromPlaylist()
+ this.removeFromFavorites()
+ showToast(this.$t('Video.Video has been removed from your saved list'))
} else {
- this.addToPlaylist()
+ this.addToFavorites()
+ showToast(this.$t('Video.Video has been saved'))
}
},
@@ -536,7 +557,7 @@ export default defineComponent({
this.watchProgress = 0
},
- addToPlaylist: function () {
+ addToFavorites: function () {
const videoData = {
videoId: this.id,
title: this.title,
@@ -553,24 +574,39 @@ export default defineComponent({
}
const payload = {
- playlistName: 'Favorites',
+ _id: 'favorites',
videoData: videoData
}
this.addVideo(payload)
-
- showToast(this.$t('Video.Video has been saved'))
},
- removeFromPlaylist: function () {
+ removeFromFavorites: function () {
const payload = {
playlistName: 'Favorites',
videoId: this.id
}
this.removeVideo(payload)
+ },
+
+ togglePlaylistPrompt: function () {
+ const videoData = {
+ videoId: this.id,
+ title: this.title,
+ author: this.channelName,
+ authorId: this.channelId,
+ published: '',
+ description: this.description,
+ viewCount: this.viewCount,
+ lengthSeconds: this.data.lengthSeconds,
+ timeAdded: new Date().getTime(),
+ isLive: false,
+ paid: false,
+ type: 'video'
+ }
- showToast(this.$t('Video.Video has been removed from your saved list'))
+ this.showAddToPlaylistPrompt(videoData)
},
...mapActions([
@@ -578,7 +614,8 @@ export default defineComponent({
'updateHistory',
'removeFromHistory',
'addVideo',
- 'removeVideo'
+ 'removeVideo',
+ 'showAddToPlaylistPrompt',
])
}
})
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 2e5967b383190..1cb53aa8b5081 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -52,7 +52,16 @@
:theme="favoriteIconTheme"
:padding="appearance === `watchPlaylistItem` ? 5 : 6"
:size="appearance === `watchPlaylistItem` ? 14 : 18"
- @click="toggleSave"
+ @click="toggleFavorite"
+ />
+
.
+*/
+
+/*
+* Credit goes to pavelvaravko for making this css.
+* https://codepen.io/pavelvaravko/pen/qjojOr
+*/
+
+/* select starting stylings ------------------------------*/
+.center {
+ text-align: center;
+}
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
new file mode 100644
index 0000000000000..2ba7dbc3602a4
--- /dev/null
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -0,0 +1,88 @@
+import Vue from 'vue'
+import { mapActions } from 'vuex'
+import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
+import FtPrompt from '../ft-prompt/ft-prompt.vue'
+import FtButton from '../ft-button/ft-button.vue'
+import FtPlaylistSelector from '../ft-playlist-selector/ft-playlist-selector.vue'
+
+export default Vue.extend({
+ name: 'FtPlaylistAddVideoPrompt',
+ components: {
+ FtFlexBox,
+ FtPrompt,
+ FtButton,
+ FtPlaylistSelector,
+ },
+ data: function () {
+ return {
+ playlistAddVideoPromptValues: [
+ 'save',
+ 'cancel'
+ ],
+ selectedPlaylists: []
+ }
+ },
+ computed: {
+ allPlaylists: function () {
+ return this.$store.getters.getAllPlaylists
+ },
+ selectedPlaylistsCount: function () {
+ return this.selectedPlaylists.length
+ },
+ showAddToPlaylistPrompt: function () {
+ return this.$store.getters.getShowAddToPlaylistPrompt
+ },
+ playlistAddVideoObject: function () {
+ return this.$store.getters.getPlaylistAddVideoObject
+ },
+ playlistAddVideoPromptNames: function () {
+ return [
+ 'Save',
+ 'Cancel'
+ ]
+ }
+ },
+ mounted: function () {
+ // this.parseUserData()
+ },
+ methods: {
+ handleAddToPlaylistPrompt: function (option) {
+ console.log(option)
+ this.hideAddToPlaylistPrompt()
+ },
+
+ countSelected: function (index) {
+ const indexOfVideo = this.selectedPlaylists.indexOf(index)
+ if (indexOfVideo !== -1) {
+ this.selectedPlaylists.splice(indexOfVideo, 1)
+ } else {
+ this.selectedPlaylists.push(index)
+ }
+ },
+
+ addSelectedToPlaylists: function () {
+ let addedPlaylists = 0
+ this.selectedPlaylists.forEach((index) => {
+ const playlist = this.allPlaylists[index]
+ const videoId = this.playlistAddVideoObject.videoId
+ const findVideo = playlist.videos.findIndex((video) => {
+ return video.videoId === videoId
+ })
+ if (findVideo === -1) {
+ const payload = {
+ _id: playlist._id,
+ videoData: this.playlistAddVideoObject
+ }
+ this.addVideo(payload)
+ addedPlaylists++
+ }
+ })
+ this.handleAddToPlaylistPrompt(null)
+ },
+
+ ...mapActions([
+ 'addVideo',
+ 'hideAddToPlaylistPrompt'
+ ])
+ }
+})
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
new file mode 100644
index 0000000000000..3cd2b8199977f
--- /dev/null
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -0,0 +1,34 @@
+
+
+
+ Select a Playlist to add your video(s) to
+
+
+ {{ selectedPlaylistsCount }} Selected
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
new file mode 100644
index 0000000000000..1b7134c9a3da1
--- /dev/null
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
@@ -0,0 +1,62 @@
+import Vue from 'vue'
+import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
+import { mapActions } from 'vuex'
+
+export default Vue.extend({
+ name: 'FtPlaylistSelector',
+ components: {
+ 'ft-icon-button': FtIconButton
+ },
+ props: {
+ data: {
+ type: Object,
+ required: true
+ },
+ index: {
+ type: Number,
+ required: true
+ },
+ appearance: {
+ type: String,
+ default: 'grid'
+ }
+ },
+ data: function () {
+ return {
+ title: '',
+ thumbnail: '',
+ playlistId: '',
+ videoCount: 0,
+ selected: false
+ }
+ },
+ computed: {
+ currentInvidiousInstance: function () {
+ return this.$store.getters.getCurrentInvidiousInstance
+ }
+ },
+ mounted: function () {
+ this.parseUserData()
+ },
+ methods: {
+ parseUserData: function () {
+ this.title = this.data.playlistName
+ if (this.data.videos.length > 0) {
+ this.thumbnail = `https://i.ytimg.com/vi/${this.data.videos[0].videoId}/mqdefault.jpg`
+ } else {
+ this.thumbnail = 'https://i.ytimg.com/vi/aaaaaa/mqdefault.jpg'
+ }
+ this.playlistLink = this.data._id
+ this.videoCount = this.data.videoCount ? this.data.videoCount : this.data.videos.length
+ },
+
+ toggleSelection: function () {
+ this.selected = !this.selected
+ this.$emit('selected', this.index)
+ },
+
+ ...mapActions([
+ 'openInExternalPlayer'
+ ])
+ }
+})
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
new file mode 100644
index 0000000000000..7e389e727d143
--- /dev/null
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
@@ -0,0 +1,254 @@
+$thumbnail-overlay-opacity: 0.85;
+$watched-transition-duration: 0.5s;
+
+@mixin is-result {
+ @at-root {
+ .result#{&} {
+ @content;
+ }
+ }
+}
+
+@mixin is-watch-playlist-item {
+ @at-root {
+ .watchPlaylistItem#{&} {
+ @content;
+ }
+ }
+}
+
+@mixin is-recommendation {
+ @at-root {
+ .recommendation#{&} {
+ @content;
+ }
+ }
+}
+
+@mixin is-sidebar-item {
+ @at-root {
+ .watchPlaylistItem#{&},
+ .recommendation#{&} {
+ @content;
+ }
+ }
+}
+
+@mixin low-contrast-when-watched($col) {
+ color: $col;
+
+ @at-root {
+ .watched &,
+ .watched#{&} {
+ color: var(--tertiary-text-color);
+ }
+ .watched:hover &,
+ .watched:hover#{&} {
+ color: $col;
+ transition-duration: $watched-transition-duration;
+ }
+ }
+}
+
+
+.ft-list-item {
+ padding: 6px;
+
+ &:hover {
+ background-color: var(--bg-color);
+ @include low-contrast-when-watched(var(--primary-text-color));
+
+ .thumbnailImage {
+ opacity: 0.3;
+ }
+ }
+ &.selected {
+ background-color: var(--bg-color);
+ @include low-contrast-when-watched(var(--primary-text-color));
+
+ .thumbnailImage {
+ opacity: 0.3;
+ transition-duration: $watched-transition-duration;
+ }
+ }
+ .videoThumbnail {
+ position: relative;
+
+ .thumbnailLink {
+ display: flex;
+ }
+ .videoWatched {
+ position: absolute;
+ top: 0;
+ padding: 2px;
+ opacity: $thumbnail-overlay-opacity;
+ color: var(--primary-text-color);
+ background-color: var(--bg-color);
+ pointer-events: none;
+ }
+ .videoDuration {
+ position: absolute;
+ bottom: 4px;
+ right: 4px;
+ padding: 3px 4px;
+ line-height: 1.2;
+ font-size: 15px;
+ border-radius: 5px;
+ margin: 0;
+ opacity: $thumbnail-overlay-opacity;
+ color: var(--primary-text-color);
+ background-color: var(--card-bg-color);
+ pointer-events: none;
+
+ &.live {
+ background-color: #f22;
+ color: #fff;
+ }
+ @include is-watch-playlist-item {
+ font-size: 12px;
+ }
+ }
+ .externalPlayerIcon {
+ position: absolute;
+ bottom: 4px;
+ left: 4px;
+ font-size: 17px;
+ opacity: $thumbnail-overlay-opacity;
+ }
+ .favoritesIcon {
+ position: absolute;
+ top: 3px;
+ right: 3px;
+ font-size: 17px;
+ opacity: $thumbnail-overlay-opacity;
+ }
+ .playlistIcon {
+ position: absolute;
+ top: 40px;
+ right: 3px;
+ font-size: 17px;
+ opacity: $thumbnail-overlay-opacity;
+ }
+ .watchedProgressBar {
+ height: 2px;
+ position: absolute;
+ bottom: 0;
+ background-color: var(--primary-color);
+ z-index: 2;
+ }
+ .videoCountContainer {
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 60px;
+ font-size: 20px;
+
+ .background,
+ .inner {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ }
+ .background {
+ background-color: var(--bg-color);
+ opacity: 0.9;
+ }
+ .inner {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ color: var(--primary-text-color);
+ }
+ }
+ }
+ .channelThumbnail {
+ display: flex;
+ justify-content: center;
+
+ .channelImage {
+ height: 130px;
+ border-radius: 50%;
+ }
+ }
+ .info {
+ flex: 1;
+ position: relative;
+
+ .optionsButton {
+ float: right; // ohhhh man, float was finally the right choice for something;
+ }
+ .externalPlayerButton {
+ float: right;
+ }
+ .title {
+ font-size: 20px;
+ @include low-contrast-when-watched(var(--primary-text-color));
+ text-decoration: none;
+ word-wrap: break-word;
+ word-break: break-word;
+
+ @include is-sidebar-item {
+ font-size: 15px;
+ }
+ }
+ .infoLine {
+ margin-top: 5px;
+ font-size: 14px;
+
+ @include is-sidebar-item {
+ font-size: 12px;
+ }
+ & {
+ @include low-contrast-when-watched(var(--secondary-text-color));
+ }
+ .channelName {
+ @include low-contrast-when-watched(var(--secondary-text-color));
+ }
+ }
+ .description {
+ font-size: 14px;
+ max-height: 50px;
+ overflow-y: hidden;
+ @include low-contrast-when-watched(var(--secondary-text-color));
+ }
+ }
+ &.grid {
+ display: flex;
+ flex-direction: column;
+ min-width: 245px;
+ min-height: 230px;
+ padding-bottom: 20px;
+
+ .videoThumbnail,
+ .channelThumbnail {
+ margin-bottom: 12px;
+
+ .thumbnailImage {
+ width: 100%;
+ }
+ }
+ .title {
+ font-size: 22px;
+ }
+ .infoLine {
+ margin-top: 8px;
+ font-size: 13px;
+ }
+ }
+}
+
+.videoWatched,
+.live {
+ text-transform: uppercase;
+}
+
+.selectedIcon {
+ position: absolute;
+ top: calc(50% - 25px);
+ left: calc(50% - 25px);
+ font-size: 50px;
+}
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue
new file mode 100644
index 0000000000000..356702b96259b
--- /dev/null
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
diff --git a/src/renderer/components/ft-prompt/ft-prompt.css b/src/renderer/components/ft-prompt/ft-prompt.css
index 87e71c4fcf410..dbd2f3b37d9d4 100644
--- a/src/renderer/components/ft-prompt/ft-prompt.css
+++ b/src/renderer/components/ft-prompt/ft-prompt.css
@@ -1,7 +1,7 @@
.prompt {
position: fixed;
- top: 0px;
- left: 0px;
+ top: 0;
+ left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.7);
@@ -20,7 +20,7 @@
}
.promptCard:not(.autosize) {
- width: 95%;
+ width: 100%;
margin: 0;
position: absolute;
left: 2.5%;
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 2b5d0656749f9..9791313bdc29c 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -147,13 +147,17 @@ export default defineComponent({
_id: this.id,
}
this.updatePlaylist(playlist)
- this.cancelEditMode()
+ this.exitEditMode()
},
- cancelEditMode: function () {
+ enterEditMode: function () {
this.newTitle = this.title
this.newDescription = this.description
- this.editMode = false
+ this.editMode = true
+ },
+
+ exitEditMode: function () {
+ this.newTitle = this.title
},
...mapActions(['updatePlaylist']),
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index fd5cc613d6a34..6f9a5b455a3ab 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -97,7 +97,7 @@
title="Cancel"
icon="times"
theme="primary"
- @click="cancelEditMode"
+ @click="exitEditMode"
/>
>')
console.log({ payload })
if (payload.length === 0) {
- commit('setAllPlaylists', state.playlists)
- dispatch('addPlaylists', payload)
- dispatch('addPlaylists', state.playlists)
+ dispatch('addPlaylists', state.defaultPlaylists)
} else {
const findFavorites = payload.filter((playlist) => {
return playlist.playlistName === 'Favorites' || playlist._id === 'favorites'
@@ -137,10 +136,10 @@ const actions = {
}
},
- async removeAllVideos({ commit }, playlistName) {
+ async removeAllVideos({ commit }, _id) {
try {
- await DBPlaylistHandlers.deleteAllVideosByPlaylistName(playlistName)
- commit('removeAllVideos', playlistName)
+ await DBPlaylistHandlers.deleteAllVideosByPlaylistId(_id)
+ commit('removeAllVideos', _id)
} catch (errMessage) {
console.error(errMessage)
}
@@ -166,8 +165,8 @@ const actions = {
async removeVideo({ commit }, payload) {
try {
- const { playlistName, videoId } = payload
- await DBPlaylistHandlers.deleteVideoIdByPlaylistName(playlistName, videoId)
+ const { _id, videoId } = payload
+ await DBPlaylistHandlers.deleteVideoIdByPlaylistId(_id, videoId)
commit('removeVideo', payload)
} catch (errMessage) {
console.error(errMessage)
@@ -176,8 +175,8 @@ const actions = {
async removeVideos({ commit }, payload) {
try {
- const { playlistName, videoIds } = payload
- await DBPlaylistHandlers.deleteVideoIdsByPlaylistName(playlistName, videoIds)
+ const { _id, videoIds } = payload
+ await DBPlaylistHandlers.deleteVideoIdsByPlaylistId(_id, videoIds)
commit('removeVideos', payload)
} catch (errMessage) {
console.error(errMessage)
@@ -207,7 +206,7 @@ const mutations = {
},
addVideo(state, payload) {
- const playlist = state.playlists.find(playlist => playlist.playlistName === payload.playlistName)
+ const playlist = state.playlists.find(playlist => playlist._id === payload._id)
if (playlist) {
playlist.videos.push(payload.videoData)
}
@@ -224,15 +223,15 @@ const mutations = {
state.playlists = state.playlists.filter(playlist => playlist.protected !== true)
},
- removeAllVideos(state, playlistName) {
- const playlist = state.playlists.find(playlist => playlist.playlistName === playlistName)
+ removeAllVideos(state, playlistId) {
+ const playlist = state.playlists.find(playlist => playlist._id === playlistId)
if (playlist) {
playlist.videos = []
}
},
removeVideo(state, payload) {
- const playlist = state.playlists.findIndex(playlist => playlist.playlistName === payload.playlistName)
+ const playlist = state.playlists.findIndex(playlist => playlist._id === payload._id)
if (playlist !== -1) {
state.playlists[playlist].videos = state.playlists[playlist].videos.filter(video => video.videoId !== payload.videoId)
}
diff --git a/src/renderer/store/modules/settings.js b/src/renderer/store/modules/settings.js
index 5fcb15dde0a77..f6439f28ce2a6 100644
--- a/src/renderer/store/modules/settings.js
+++ b/src/renderer/store/modules/settings.js
@@ -490,6 +490,10 @@ const customActions = {
ipcRenderer.on(IpcChannels.SYNC_PLAYLISTS, (_, { event, data }) => {
switch (event) {
+ case SyncEvents.PLAYLISTS.UPSERT:
+ commit('upsertPlaylistToList', data)
+ break
+
case SyncEvents.PLAYLISTS.UPSERT_VIDEO:
commit('addVideo', data)
break
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index aeeedd7a06ede..97850ab69e2a5 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -28,7 +28,9 @@ const state = {
},
cachedPlaylist: null,
showProgressBar: false,
+ showAddToPlaylistPrompt: false,
progressBarPercentage: 0,
+ playlistAddVideoObject: [],
regionNames: [],
regionValues: [],
recentBlogPosts: [],
@@ -73,6 +75,14 @@ const getters = {
return state.searchSettings
},
+ getShowAddToPlaylistPrompt () {
+ return state.showAddToPlaylistPrompt
+ },
+
+ getPlaylistAddVideoObject () {
+ return state.playlistAddVideoObject
+ },
+
getShowProgressBar () {
return state.showProgressBar
},
@@ -236,6 +246,15 @@ const actions = {
})
},
+ showAddToPlaylistPrompt ({ commit }, videoArray) {
+ commit('setShowAddToPlaylistPrompt', true)
+ commit('setPlaylistAddVideoObject', videoArray)
+ },
+
+ hideAddToPlaylistPrompt ({ commit }) {
+ commit('setShowAddToPlaylistPrompt', false)
+ },
+
updateShowProgressBar ({ commit }, value) {
commit('setShowProgressBar', value)
},
@@ -633,6 +652,14 @@ const mutations = {
}
},
+ setShowAddToPlaylistPrompt (state, payload) {
+ state.showAddToPlaylistPrompt = payload
+ },
+
+ setPlaylistAddVideoObject (state, payload) {
+ state.playlistAddVideoObject = payload
+ },
+
setPopularCache (state, value) {
state.popularCache = value
},
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 0c98dd84639d8..f4d5312968b4b 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -76,7 +76,10 @@ export default defineComponent({
$route () {
// react to route changes...
this.getPlaylistInfo()
- }
+ },
+ selectedPlaylist () {
+ this.getPlaylistInfo()
+ },
},
mounted: function () {
this.getPlaylistInfo()
@@ -204,8 +207,8 @@ export default defineComponent({
parseUserPlaylist: function (playlist) {
this.playlistId = playlist._id
- this.playlistTitle = playlist.title
- this.playlistDescription = playlist.description
+ this.playlistTitle = playlist.title ? playlist.title : playlist.playlistName
+ this.playlistDescription = playlist.description ? playlist.description : ''
if (playlist.videos.length > 0) {
this.firstVideoId = playlist.videos[0].videoId
@@ -213,7 +216,7 @@ export default defineComponent({
this.firstVideoId = ''
}
this.viewCount = 0
- this.videoCount = playlist.videoCount
+ this.videoCount = playlist.videoCount ? playlist.videoCount : playlist.videos.length
this.lastUpdated = undefined
this.channelName = playlist.author ? playlist.author.name : ''
this.channelThumbnail = playlist.author ? playlist.author.bestAvatar.url : ''
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index ff57605d552da..5a618cf1e6487 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -17,7 +17,7 @@ export default defineComponent({
'ft-loader': FtLoader,
'ft-button': FtButton,
'ft-element-list': FtElementList,
- 'ft-input': FtInput
+ 'ft-input': FtInput,
},
data: function () {
return {
@@ -35,14 +35,14 @@ export default defineComponent({
},
allPlaylists: function () {
- return this.$store.getters.getAllPlaylists.map((playlist) => {
+ const playlists = this.$store.getters.getAllPlaylists
+ return [].concat(playlists).map((playlist) => {
playlist.title = playlist.playlistName
playlist.type = 'playlist'
playlist.thumbnail = ''
playlist.channelName = ''
playlist.channelId = ''
playlist.playlistId = ''
- playlist.description = playlist.description ? playlist.description : ''
playlist.videoCount = playlist.videos.length
return playlist
})
@@ -55,7 +55,7 @@ export default defineComponent({
} else {
return data.slice(0, this.dataLimit)
}
- }
+ },
},
watch: {
query() {
From 5ce3e617ac1e9a76d04fb4811aea5f10de112387 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 16 May 2023 15:52:50 +0800
Subject: [PATCH 003/236] (Replicate) Push up batch 3 of playlist functionality
---
src/renderer/App.js | 12 +-
src/renderer/App.vue | 6 +
.../ft-create-playlist-prompt.css | 28 ++++
.../ft-create-playlist-prompt.js | 93 +++++++++++++
.../ft-create-playlist-prompt.vue | 39 ++++++
.../components/ft-list-video/ft-list-video.js | 28 ++++
.../ft-list-video/ft-list-video.vue | 27 ++++
.../ft-playlist-add-video-prompt.js | 40 +++++-
.../ft-playlist-add-video-prompt.vue | 4 +
.../ft-playlist-selector.scss | 2 +-
.../ft-playlist-selector.vue | 2 +
src/renderer/components/ft-toast/ft-toast.css | 2 +-
.../components/playlist-info/playlist-info.js | 131 +++++++++++++++---
.../playlist-info/playlist-info.vue | 32 +++--
src/renderer/scss-partials/_ft-list-item.scss | 22 +++
src/renderer/store/modules/playlists.js | 4 +-
src/renderer/store/modules/utils.js | 27 ++++
src/renderer/views/Playlist/Playlist.css | 1 +
src/renderer/views/Playlist/Playlist.js | 121 +++++++++++++++-
src/renderer/views/Playlist/Playlist.vue | 4 +
.../views/UserPlaylists/UserPlaylists.css | 8 ++
.../views/UserPlaylists/UserPlaylists.js | 31 +++++
.../views/UserPlaylists/UserPlaylists.vue | 7 +
23 files changed, 627 insertions(+), 44 deletions(-)
create mode 100644 src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.css
create mode 100644 src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
create mode 100644 src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
diff --git a/src/renderer/App.js b/src/renderer/App.js
index 7d98ff1aa3859..b480b92d04a11 100644
--- a/src/renderer/App.js
+++ b/src/renderer/App.js
@@ -9,6 +9,8 @@ import FtPrompt from './components/ft-prompt/ft-prompt.vue'
import FtButton from './components/ft-button/ft-button.vue'
import FtToast from './components/ft-toast/ft-toast.vue'
import FtProgressBar from './components/ft-progress-bar/ft-progress-bar.vue'
+import FtPlaylistAddVideoPrompt from './components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue'
+import FtCreatePlaylistPrompt from './components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue'
import { marked } from 'marked'
import { IpcChannels } from '../constants'
import packageDetails from '../../package.json'
@@ -28,7 +30,9 @@ export default defineComponent({
FtPrompt,
FtButton,
FtToast,
- FtProgressBar
+ FtProgressBar,
+ FtPlaylistAddVideoPrompt,
+ FtCreatePlaylistPrompt,
},
data: function () {
return {
@@ -63,6 +67,12 @@ export default defineComponent({
checkForBlogPosts: function () {
return this.$store.getters.getCheckForBlogPosts
},
+ showAddToPlaylistPrompt: function () {
+ return this.$store.getters.getShowAddToPlaylistPrompt
+ },
+ showCreatePlaylistPrompt: function () {
+ return this.$store.getters.getShowCreatePlaylistPrompt
+ },
windowTitle: function () {
const routeTitle = this.$route.meta.title
if (routeTitle !== 'Channel' && routeTitle !== 'Watch' && routeTitle !== 'Hashtag') {
diff --git a/src/renderer/App.vue b/src/renderer/App.vue
index b4d7faa4ef45d..2e7ae23b9340c 100644
--- a/src/renderer/App.vue
+++ b/src/renderer/App.vue
@@ -74,6 +74,12 @@
:option-values="externalLinkOpeningPromptValues"
@click="handleExternalLinkOpeningPromptAnswer"
/>
+
+
.
+*/
+
+/*
+* Credit goes to pavelvaravko for making this css.
+* https://codepen.io/pavelvaravko/pen/qjojOr
+*/
+
+/* select starting stylings ------------------------------*/
+.center {
+ text-align: center;
+}
+
+.playlistNameInput {
+ width: 80%;
+ max-width: 600px;
+}
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
new file mode 100644
index 0000000000000..a35c622c0483c
--- /dev/null
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -0,0 +1,93 @@
+import Vue from 'vue'
+import { mapActions } from 'vuex'
+import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
+import FtPrompt from '../ft-prompt/ft-prompt.vue'
+import FtButton from '../ft-button/ft-button.vue'
+import FtInput from '../ft-input/ft-input.vue'
+import FtPlaylistSelector from '../ft-playlist-selector/ft-playlist-selector.vue'
+
+export default Vue.extend({
+ name: 'FtCreatePlaylistPrompt',
+ components: {
+ FtFlexBox,
+ FtPrompt,
+ FtButton,
+ FtInput,
+ FtPlaylistSelector
+ },
+ data: function () {
+ return {
+ playlistName: '',
+ playlistAddVideoPromptValues: [
+ 'save',
+ 'cancel'
+ ],
+ selectedPlaylists: []
+ }
+ },
+ computed: {
+ allPlaylists: function () {
+ return this.$store.getters.getAllPlaylists
+ },
+ newPlaylistVideoObject: function () {
+ return this.$store.getters.getNewPlaylistVideoObject
+ },
+ videoImportLength: function () {
+ return this.newPlaylistVideoObject.videos.length
+ }
+ },
+ mounted: function () {
+ this.playlistName = this.newPlaylistVideoObject.title
+ },
+ methods: {
+ handleCreatePlaylistPrompt: function (option) {
+ this.hideCreatePlaylistPrompt()
+ },
+
+ createNewPlaylist: function () {
+ const videosObject = this.videoImportLength > 0 ? this.newPlaylistVideoObject.videos : []
+
+ const playlistObject = {
+ playlistName: this.playlistName,
+ protected: false,
+ removeOnWatched: false,
+ description: '',
+ videos: videosObject
+ }
+
+ const nameExists = this.allPlaylists.findIndex((playlist) => {
+ return playlist.playlistName.toLowerCase() === this.playlistName.toLowerCase()
+ })
+
+ if (this.playlistName === '') {
+ this.showToast({
+ message: 'Playlist name cannot be empty. Please input a name.'
+ })
+ } else if (nameExists !== -1) {
+ this.showToast({
+ message: 'There is already a playlist with this name. Please pick a different name.'
+ })
+ } else {
+ try {
+ this.addPlaylist(playlistObject)
+ this.showToast({
+ message: `Playlist ${this.playlistName} has been successfully created.`
+ })
+ } catch (e) {
+ this.showToast({
+ message: 'There was an issue with creating the playlist.'
+ })
+ console.error(e)
+ } finally {
+ this.hideCreatePlaylistPrompt()
+ }
+ }
+ },
+
+ ...mapActions([
+ 'showToast',
+ 'addPlaylist',
+ 'hideCreatePlaylistPrompt'
+ ])
+ }
+})
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
new file mode 100644
index 0000000000000..7e859b6b8810e
--- /dev/null
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
@@ -0,0 +1,39 @@
+
+
+
+ New Playlist Name
+
+
+ playlistName = input"
+ @click="createNewPlaylist"
+ />
+
+
+ {{ videoImportLength }} video(s) will also be imported when created
+
+
+
+
+
+
+
+
+
+
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 7b0cd23873070..1f9c5a9645624 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -25,6 +25,10 @@ export default defineComponent({
type: String,
default: null
},
+ playlistType: {
+ type: String,
+ default: null
+ },
playlistIndex: {
type: Number,
default: null
@@ -101,6 +105,10 @@ export default defineComponent({
return this.$route.name === 'history'
},
+ inUserPlaylist: function () {
+ return this.$router.currentRoute.path.includes('playlist') && this.playlistType === 'user'
+ },
+
invidiousUrl: function () {
let videoUrl = `${this.currentInvidiousInstance}/watch?v=${this.id}`
// `playlistId` can be undefined
@@ -590,6 +598,26 @@ export default defineComponent({
this.removeVideo(payload)
},
+ removeVideoFromPlaylist: function () {
+ const payload = {
+ _id: this.playlistId,
+ videoId: this.id
+ }
+
+ try {
+ this.removeVideo(payload)
+ this.$emit('refresh-playlist')
+ this.showToast({
+ message: 'Video has been removed'
+ })
+ } catch (e) {
+ this.showToast({
+ message: 'There was a problem with removing this video'
+ })
+ console.error(e)
+ }
+ },
+
togglePlaylistPrompt: function () {
const videoData = {
videoId: this.id,
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 1cb53aa8b5081..3f150a669f3c9 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -63,6 +63,33 @@
:size="appearance === `watchPlaylistItem` ? 14 : 18"
@click="togglePlaylistPrompt"
/>
+
+
+
{
+ playlist.title = playlist.playlistName
+ playlist.type = 'playlist'
+ playlist.thumbnail = ''
+ playlist.channelName = ''
+ playlist.channelId = ''
+ playlist.playlistId = ''
+ playlist.videoCount = playlist.videos.length
+ return playlist
+ }).sort((a, b) => {
+ // Sort by favorites, watch later, then alphabetically
+ if (a._id === 'favorites') {
+ return -1
+ } else if (b._id === 'favorites') {
+ return 1
+ } else if (a._id === 'watchLater') {
+ return -1
+ } else if (b._id === 'watchLater') {
+ return 1
+ }
+
+ return a.title.localeCompare(b.title, this.locale)
+ })
},
selectedPlaylistsCount: function () {
return this.selectedPlaylists.length
@@ -47,7 +70,6 @@ export default Vue.extend({
},
methods: {
handleAddToPlaylistPrompt: function (option) {
- console.log(option)
this.hideAddToPlaylistPrompt()
},
@@ -77,12 +99,24 @@ export default Vue.extend({
addedPlaylists++
}
})
+
+ this.showToast({
+ message: `Video has been added to ${addedPlaylists} playlist(s).`
+ })
this.handleAddToPlaylistPrompt(null)
},
+ createNewPlaylist: function () {
+ this.showCreatePlaylistPrompt({
+ title: '',
+ videos: []
+ })
+ },
+
...mapActions([
'addVideo',
- 'hideAddToPlaylistPrompt'
+ 'hideAddToPlaylistPrompt',
+ 'showCreatePlaylistPrompt',
])
}
})
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 3cd2b8199977f..858b435852bf4 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -22,6 +22,10 @@
label="Save"
@click="addSelectedToPlaylists"
/>
+
playlist._id === this.id)
},
+ deletePlaylistPromptNames: function () {
+ return [
+ this.$t('Yes'),
+ this.$t('No')
+ ]
+ },
+
thumbnail: function () {
let baseUrl
if (this.backendPreference === 'invidious') {
@@ -118,25 +141,15 @@ export default defineComponent({
mounted: function () {
this.newTitle = this.title
this.newDescription = this.description
-
- // Causes errors if not put inside of a check
- // if (
- // typeof this.data.viewCount !== 'undefined' &&
- // !isNaN(this.data.viewCount)
- // ) {
- // this.viewCount = this.hideViews ? null : formatNumber(this.data.viewCount)
- // }
- //
- // if (
- // typeof this.data.videoCount !== 'undefined' &&
- // !isNaN(this.data.videoCount)
- // ) {
- // this.videoCount = formatNumber(this.data.videoCount)
- // }
- //
- // this.lastUpdated = this.data.lastUpdated
},
methods: {
+ copyPlaylist: function () {
+ this.showCreatePlaylistPrompt({
+ title: this.title,
+ videos: this.videos
+ })
+ },
+
savePlaylistInfo: function () {
const playlist = {
playlistName: this.newTitle,
@@ -146,8 +159,19 @@ export default defineComponent({
videos: this.selectedPlaylist.videos,
_id: this.id,
}
- this.updatePlaylist(playlist)
- this.exitEditMode()
+ try {
+ this.updatePlaylist(playlist)
+ this.showToast({
+ message: 'Playlist has been updated.'
+ })
+ } catch (e) {
+ this.showToast({
+ message: 'There was an issue with updating this playlist.'
+ })
+ console.error(e)
+ } finally {
+ this.exitEditMode()
+ }
},
enterEditMode: function () {
@@ -160,6 +184,73 @@ export default defineComponent({
this.newTitle = this.title
},
- ...mapActions(['updatePlaylist']),
+ handleRemoveVideosOnWatchPromptAnswer: function (option) {
+ console.log(this.selectedPlaylist.videos)
+ if (option === 'yes') {
+ const videosToWatch = this.selectedPlaylist.videos.filter((video) => {
+ const watchedIndex = this.historyCache.findIndex((history) => {
+ return history.videoId === video.videoId
+ })
+
+ return watchedIndex === -1
+ })
+
+ const videosRemoved = this.selectedPlaylist.videos.length - videosToWatch.length
+
+ if (videosRemoved === 0) {
+ this.showToast({
+ message: 'There were no videos to remove.'
+ })
+ this.showRemoveVideosOnWatchPrompt = false
+ return
+ }
+
+ const playlist = {
+ playlistName: this.title,
+ protected: this.selectedPlaylist.protected,
+ removeOnWatched: this.selectedPlaylist.removeOnWatched,
+ description: this.description,
+ videos: videosToWatch,
+ _id: this.id
+ }
+ try {
+ this.updatePlaylist(playlist)
+ this.showToast({
+ message: `${videosRemoved} video(s) have been removed.`
+ })
+ } catch (e) {
+ this.showToast({
+ message: 'There was an issue with updating this playlist.'
+ })
+ console.error(e)
+ }
+ }
+ this.showRemoveVideosOnWatchPrompt = false
+ },
+
+ handleDeletePlaylistPromptAnswer: function (option) {
+ if (this.selectedPlaylist.protected) {
+ this.showToast({
+ message: 'This playlist is protected and cannot be removed.'
+ })
+ } else if (option === 'yes') {
+ this.removePlaylist(this.id)
+ this.$router.push(
+ {
+ path: '/userPlaylists'
+ }
+ )
+ this.showToast({
+ message: `${this.title} has been deleted.`
+ })
+ }
+ this.showDeletePlaylistPrompt = false
+ },
+
+ ...mapActions([
+ 'showCreatePlaylistPrompt',
+ 'updatePlaylist',
+ 'removePlaylist',
+ ]),
},
})
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 6f9a5b455a3ab..db9403fb51627 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -103,16 +103,12 @@
-
-
-
-
-
-
-
-
-
-
+
@@ -140,6 +138,20 @@
:dropdown-position-y="description ? 'top' : 'bottom'"
share-target-type="Playlist"
/>
+
+
diff --git a/src/renderer/scss-partials/_ft-list-item.scss b/src/renderer/scss-partials/_ft-list-item.scss
index 03da664f69d71..633b2eac489d7 100644
--- a/src/renderer/scss-partials/_ft-list-item.scss
+++ b/src/renderer/scss-partials/_ft-list-item.scss
@@ -161,6 +161,28 @@ $watched-transition-duration: 0.5s;
opacity: $thumbnail-overlay-opacity;
}
+ .trashIcon {
+ position: absolute;
+ top: 75px;
+ right: 3px;
+ font-size: 17px;
+ opacity: $thumbnail-overlay-opacity;
+ }
+ .upArrowIcon {
+ position: absolute;
+ bottom: 40px;
+ left: 3px;
+ font-size: 17px;
+ opacity: $thumbnail-overlay-opacity;
+ }
+ .downArrowIcon {
+ position: absolute;
+ bottom: 3px;
+ left: 3px;
+ font-size: 17px;
+ opacity: $thumbnail-overlay-opacity;
+ }
+
.watchedProgressBar {
align-self: flex-end;
background-color: var(--primary-color);
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index d892ae568deeb..3aee9f97574e5 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -24,9 +24,9 @@ const state = {
const getters = {
getAllPlaylists: () => state.playlists,
- getFavorites: () => state.playlists[0],
+ getFavorites: () => state.playlists.find(playlist => playlist._id === 'favorites'),
getPlaylist: (playlistId) => state.playlists.find(playlist => playlist._id === playlistId),
- getWatchLater: () => state.playlists[1]
+ getWatchLater: () => state.playlists.find(playlist => playlist._id === 'watchLater')
}
const actions = {
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index 97850ab69e2a5..d460dad33d368 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -29,8 +29,10 @@ const state = {
cachedPlaylist: null,
showProgressBar: false,
showAddToPlaylistPrompt: false,
+ showCreatePlaylistPrompt: false,
progressBarPercentage: 0,
playlistAddVideoObject: [],
+ newPlaylistVideoObject: [],
regionNames: [],
regionValues: [],
recentBlogPosts: [],
@@ -79,10 +81,18 @@ const getters = {
return state.showAddToPlaylistPrompt
},
+ getShowCreatePlaylistPrompt () {
+ return state.showCreatePlaylistPrompt
+ },
+
getPlaylistAddVideoObject () {
return state.playlistAddVideoObject
},
+ getNewPlaylistVideoObject () {
+ return state.newPlaylistVideoObject
+ },
+
getShowProgressBar () {
return state.showProgressBar
},
@@ -255,6 +265,15 @@ const actions = {
commit('setShowAddToPlaylistPrompt', false)
},
+ showCreatePlaylistPrompt ({ commit }, videoArray) {
+ commit('setShowCreatePlaylistPrompt', true)
+ commit('setNewPlaylistVideoObject', videoArray)
+ },
+
+ hideCreatePlaylistPrompt ({ commit }) {
+ commit('setShowCreatePlaylistPrompt', false)
+ },
+
updateShowProgressBar ({ commit }, value) {
commit('setShowProgressBar', value)
},
@@ -656,10 +675,18 @@ const mutations = {
state.showAddToPlaylistPrompt = payload
},
+ setShowCreatePlaylistPrompt (state, payload) {
+ state.showCreatePlaylistPrompt = payload
+ },
+
setPlaylistAddVideoObject (state, payload) {
state.playlistAddVideoObject = payload
},
+ setNewPlaylistVideoObject (state, payload) {
+ state.newPlaylistVideoObject = payload
+ },
+
setPopularCache (state, value) {
state.popularCache = value
},
diff --git a/src/renderer/views/Playlist/Playlist.css b/src/renderer/views/Playlist/Playlist.css
index 7b2414b74014a..a3e82f26d0fd8 100644
--- a/src/renderer/views/Playlist/Playlist.css
+++ b/src/renderer/views/Playlist/Playlist.css
@@ -57,6 +57,7 @@
box-sizing: border-box;
position: relative;
top: 0;
+ z-index: 1;
height: auto;
width: 100%;
}
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index f4d5312968b4b..b7e9133314677 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -7,7 +7,7 @@ import FtListVideoLazy from '../../components/ft-list-video-lazy/ft-list-video-l
import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue'
import FtButton from '../../components/ft-button/ft-button.vue'
import { getLocalPlaylist, parseLocalPlaylistVideo } from '../../helpers/api/local'
-import { extractNumberFromString } from '../../helpers/utils'
+import { extractNumberFromString, showToast } from '../../helpers/utils'
import { invidiousGetPlaylistInfo, youtubeImageUrlToInvidious } from '../../helpers/api/invidious'
export default defineComponent({
@@ -71,6 +71,13 @@ export default defineComponent({
selectedPlaylist: function () {
return this.userPlaylists.find(playlist => playlist._id === this.playlistId)
},
+ selectedVideos: function () {
+ if (typeof (this.selectedPlaylist) !== 'undefined') {
+ return this.selectedPlaylist.videos
+ } else {
+ return []
+ }
+ },
},
watch: {
$route () {
@@ -78,7 +85,18 @@ export default defineComponent({
this.getPlaylistInfo()
},
selectedPlaylist () {
- this.getPlaylistInfo()
+ if (this.isLoading) {
+ // Ignores first time load of page
+ return
+ }
+ this.refreshPage()
+ },
+ selectedVideos () {
+ if (this.isLoading) {
+ // Ignores first time load of page
+ return
+ }
+ this.refreshPage()
},
},
mounted: function () {
@@ -170,9 +188,9 @@ export default defineComponent({
infoSource: 'invidious'
}
- this.id = result.playlistId
- this.title = result.title
- this.description = result.description
+ this.playlistId = result.playlistId
+ this.playlistTitle = result.title
+ this.playlistDescription = result.description
this.firstVideoId = result.videos[0].videoId
this.viewCount = result.viewCount
this.videoCount = result.videoCount
@@ -256,8 +274,99 @@ export default defineComponent({
})
},
+ moveVideoUp: function (videoId) {
+ const playlistItems = [].concat(this.playlistItems)
+ const videoIndex = playlistItems.findIndex((video) => {
+ return video.videoId === videoId
+ })
+
+ if (videoIndex === 0) {
+ showToast({
+ message: 'This video cannot be moved up.'
+ })
+ return
+ }
+
+ const videoObject = playlistItems[videoIndex]
+
+ playlistItems.splice(videoIndex, 1)
+ playlistItems.splice(videoIndex - 1, 0, videoObject)
+
+ const playlist = {
+ playlistName: this.playlistTitle,
+ protected: this.selectedPlaylist.protected,
+ removeOnWatched: this.selectedPlaylist.removeOnWatched,
+ description: this.playlistDescription,
+ videos: playlistItems,
+ _id: this.playlistId
+ }
+ try {
+ this.updatePlaylist(playlist)
+ this.playlistItems = playlistItems
+ } catch (e) {
+ showToast({
+ message: 'There was an issue with updating this playlist.'
+ })
+ console.error(e)
+ }
+ },
+
+ moveVideoDown: function (videoId) {
+ const playlistItems = [].concat(this.playlistItems)
+ const videoIndex = playlistItems.findIndex((video) => {
+ return video.videoId === videoId
+ })
+
+ if (videoIndex + 1 === playlistItems.length || videoIndex + 1 > playlistItems.length) {
+ showToast({
+ message: 'This video cannot be moved down.'
+ })
+ return
+ }
+
+ const videoObject = playlistItems[videoIndex]
+
+ playlistItems.splice(videoIndex, 1)
+ playlistItems.splice(videoIndex + 1, 0, videoObject)
+
+ const playlist = {
+ playlistName: this.playlistTitle,
+ protected: this.selectedPlaylist.protected,
+ removeOnWatched: this.selectedPlaylist.removeOnWatched,
+ description: this.playlistDescription,
+ videos: playlistItems,
+ _id: this.playlistId
+ }
+ try {
+ this.updatePlaylist(playlist)
+ this.playlistItems = playlistItems
+ } catch (e) {
+ showToast({
+ message: 'There was an issue with updating this playlist.'
+ })
+ console.error(e)
+ }
+ },
+
+ refreshPage: function () {
+ this.getPlaylistInfo()
+ // The list of videos within a playlist do not refresh properly if a video
+ // is removed, so the timeout forces the view to refresh. This is kinda hacky
+ // and has to do with a quirk of Vue. I don't really like this solution but this
+ // was the only way I could get it to update properly
+ const yOffset = window.scrollY
+ this.isLoading = true
+ window.setTimeout(() => {
+ this.isLoading = false
+ window.setTimeout(() => {
+ window.scrollTo(0, yOffset)
+ }, 100)
+ }, 100)
+ },
+
...mapActions([
- 'updateSubscriptionDetails'
+ 'updateSubscriptionDetails',
+ 'updatePlaylist',
]),
...mapMutations([
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index db1abb3ae4aaf..cb8853ad5ff0c 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -16,6 +16,7 @@
:last-updated="lastUpdated"
:description="playlistDescription"
:video-count="videoCount"
+ :videos="playlistItems"
:view-count="viewCount"
:info-source="infoSource"
class="playlistInfo"
@@ -41,9 +42,12 @@
{
+ // Sort by favorites, watch later, then alphabetically
+ if (a._id === 'favorites') {
+ return -1
+ } else if (b._id === 'favorites') {
+ return 1
+ } else if (a._id === 'watchLater') {
+ return -1
+ } else if (b._id === 'watchLater') {
+ return 1
+ }
+
+ return a.title.localeCompare(b.title, this.locale)
})
},
@@ -126,5 +146,16 @@ export default defineComponent({
// this.activeData = filteredQuery.length < this.searchDataLimit ? filteredQuery : filteredQuery.slice(0, this.searchDataLimit)
// }
},
+
+ createNewPlaylist: function () {
+ this.showCreatePlaylistPrompt({
+ title: '',
+ videos: []
+ })
+ },
+
+ ...mapActions([
+ 'showCreatePlaylistPrompt'
+ ])
}
})
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index d2f8660a2491c..8cfbedf1a48a5 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -11,6 +11,13 @@
{{ $t("User Playlists.Your Playlists") }}
+
Date: Tue, 16 May 2023 17:19:56 +0800
Subject: [PATCH 004/236] ! Fix small stuff, errors on app boot
---
src/renderer/store/modules/playlists.js | 28 ++++++++++++-------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 3aee9f97574e5..110de0c50bded 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -79,9 +79,7 @@ const actions = {
async grabAllPlaylists({ commit, dispatch, state }) {
try {
- const payload = await DBPlaylistHandlers.find()
- console.log('grabAllPlaylists >>')
- console.log({ payload })
+ const payload = (await DBPlaylistHandlers.find()).filter((e) => e != null)
if (payload.length === 0) {
dispatch('addPlaylists', state.defaultPlaylists)
} else {
@@ -93,8 +91,8 @@ const actions = {
})
if (findFavorites.length === 0) {
- dispatch('addPlaylist', state.playlists[0])
- payload.push(state.playlists[0])
+ dispatch('addPlaylist', state.defaultPlaylists.find((e) => e._id === 'favorites'))
+ payload.push(state.defaultPlaylists[0])
} else {
const favoritesPlaylist = findFavorites[0]
@@ -107,14 +105,14 @@ const actions = {
}
if (findWatchLater.length === 0) {
- dispatch('addPlaylist', state.playlists[1])
- payload.push(state.playlists[1])
+ dispatch('addPlaylist', state.defaultPlaylists.find((e) => e._id === 'watchLater'))
+ payload.push(state.defaultPlaylists[1])
} else {
- const watchLaterPlaylist = findFavorites[0]
+ const watchLaterPlaylist = findWatchLater[0]
- if (watchLaterPlaylist._id !== 'favorites') {
+ if (watchLaterPlaylist._id !== 'watchLater') {
const oldId = watchLaterPlaylist._id
- watchLaterPlaylist._id = 'favorites'
+ watchLaterPlaylist._id = 'watchLater'
dispatch('addPlaylist', watchLaterPlaylist)
dispatch('removePlaylist', oldId)
}
@@ -231,15 +229,15 @@ const mutations = {
},
removeVideo(state, payload) {
- const playlist = state.playlists.findIndex(playlist => playlist._id === payload._id)
- if (playlist !== -1) {
- state.playlists[playlist].videos = state.playlists[playlist].videos.filter(video => video.videoId !== payload.videoId)
+ const playlist = state.playlists.find(playlist => playlist._id === payload._id)
+ if (playlist) {
+ playlist.videos = playlist.videos.filter(video => video.videoId !== payload.videoId)
}
},
removeVideos(state, payload) {
- const playlist = state.playlists.findIndex(playlist => playlist._id === payload.playlistId)
- if (playlist !== -1) {
+ const playlist = state.playlists.find(playlist => playlist._id === payload.playlistId)
+ if (playlist) {
playlist.videos = playlist.videos.filter(video => payload.videoId.indexOf(video) === -1)
}
},
From 0db44904491b77b2a5adb8d01b1628061ba9044e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 09:25:20 +0800
Subject: [PATCH 005/236] ! Fix outdated code in data fetching
---
src/renderer/views/Playlist/Playlist.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index b7e9133314677..e865e5cb38d14 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -138,7 +138,7 @@ export default defineComponent({
}
this.playlistId = result.id
- this.playlistTitle = result.title
+ this.playlistTitle = result.info.title
this.playlistDescription = result.info.description ?? ''
this.firstVideoId = result.items[0].id
this.viewCount = extractNumberFromString(result.info.views)
From 5250f8a0001d96dfbcbbe9828cf16992e977de61 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 09:25:30 +0800
Subject: [PATCH 006/236] ! Fix icons
---
.../components/ft-list-video/ft-list-video.vue | 8 ++++----
.../ft-playlist-selector/ft-playlist-selector.vue | 4 ++--
.../components/playlist-info/playlist-info.vue | 12 ++++++------
src/renderer/main.js | 12 +++++++++++-
src/renderer/views/UserPlaylists/UserPlaylists.vue | 2 +-
5 files changed, 24 insertions(+), 14 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 3f150a669f3c9..08423d4e6626e 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -57,7 +57,7 @@
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index db9403fb51627..9972d19805c98 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -89,13 +89,13 @@
>
@@ -105,28 +105,28 @@
>
diff --git a/src/renderer/main.js b/src/renderer/main.js
index 06a7999dd94cb..6f8aee84c2945 100644
--- a/src/renderer/main.js
+++ b/src/renderer/main.js
@@ -20,12 +20,14 @@ import {
faCommentDots,
faCopy,
faDownload,
+ faEdit,
faEllipsisH,
faEllipsisV,
faEnvelope,
faExchangeAlt,
faExclamationCircle,
faExternalLinkAlt,
+ faEyeSlash,
faFileDownload,
faFileVideo,
faFilter,
@@ -38,11 +40,13 @@ import {
faList,
faNewspaper,
faPlay,
+ faPlus,
faQuestionCircle,
faRandom,
faRetweet,
faRss,
faSatelliteDish,
+ faSave,
faSearch,
faShareAlt,
faSlidersH,
@@ -56,7 +60,8 @@ import {
faThumbtack,
faTimes,
faTimesCircle,
- faUsers
+ faTrash,
+ faUsers,
} from '@fortawesome/free-solid-svg-icons'
import {
faBitcoin,
@@ -86,12 +91,14 @@ library.add(
faCommentDots,
faCopy,
faDownload,
+ faEdit,
faEllipsisH,
faEllipsisV,
faEnvelope,
faExchangeAlt,
faExclamationCircle,
faExternalLinkAlt,
+ faEyeSlash,
faFileDownload,
faFileVideo,
faFilter,
@@ -104,11 +111,13 @@ library.add(
faList,
faNewspaper,
faPlay,
+ faPlus,
faQuestionCircle,
faRandom,
faRetweet,
faRss,
faSatelliteDish,
+ faSave,
faSearch,
faShareAlt,
faSlidersH,
@@ -122,6 +131,7 @@ library.add(
faThumbtack,
faTimes,
faTimesCircle,
+ faTrash,
faUsers,
// brand icons
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index 8cfbedf1a48a5..01ff187d3781c 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -13,7 +13,7 @@
Date: Wed, 17 May 2023 09:36:25 +0800
Subject: [PATCH 007/236] * Comment code that seems to be causing strange
bahaviour on load for remote playlist
Could be outdated code
---
src/renderer/views/Playlist/Playlist.js | 28 ++++++++++++-------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index e865e5cb38d14..64d61fb134e5c 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -84,20 +84,20 @@ export default defineComponent({
// react to route changes...
this.getPlaylistInfo()
},
- selectedPlaylist () {
- if (this.isLoading) {
- // Ignores first time load of page
- return
- }
- this.refreshPage()
- },
- selectedVideos () {
- if (this.isLoading) {
- // Ignores first time load of page
- return
- }
- this.refreshPage()
- },
+ // selectedPlaylist () {
+ // if (this.isLoading) {
+ // // Ignores first time load of page
+ // return
+ // }
+ // this.refreshPage()
+ // },
+ // selectedVideos () {
+ // if (this.isLoading) {
+ // // Ignores first time load of page
+ // return
+ // }
+ // this.refreshPage()
+ // },
},
mounted: function () {
this.getPlaylistInfo()
From 3748174f1974154371099dff9a1001fc1ac72c6e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 09:37:23 +0800
Subject: [PATCH 008/236] ! Stop assigning playlist ID from remote result (we
already have)
---
src/renderer/views/Playlist/Playlist.js | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 64d61fb134e5c..442b9070a6738 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -137,7 +137,6 @@ export default defineComponent({
infoSource: 'local'
}
- this.playlistId = result.id
this.playlistTitle = result.info.title
this.playlistDescription = result.info.description ?? ''
this.firstVideoId = result.items[0].id
@@ -188,7 +187,6 @@ export default defineComponent({
infoSource: 'invidious'
}
- this.playlistId = result.playlistId
this.playlistTitle = result.title
this.playlistDescription = result.description
this.firstVideoId = result.videos[0].videoId
From 25968335ad1f86093093e5282de5c3ec96157d1a Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 10:14:37 +0800
Subject: [PATCH 009/236] ! Fix outdated usage of `showToast`
---
.../ft-create-playlist-prompt.js | 19 ++++-------
.../components/ft-list-video/ft-list-video.js | 8 ++---
.../ft-playlist-add-video-prompt.js | 7 ++--
.../components/playlist-info/playlist-info.js | 32 ++++++-------------
src/renderer/views/Playlist/Playlist.js | 16 +++-------
5 files changed, 27 insertions(+), 55 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index a35c622c0483c..2bfabc5e0c130 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -5,6 +5,9 @@ import FtPrompt from '../ft-prompt/ft-prompt.vue'
import FtButton from '../ft-button/ft-button.vue'
import FtInput from '../ft-input/ft-input.vue'
import FtPlaylistSelector from '../ft-playlist-selector/ft-playlist-selector.vue'
+import {
+ showToast,
+} from '../../helpers/utils'
export default Vue.extend({
name: 'FtCreatePlaylistPrompt',
@@ -60,23 +63,15 @@ export default Vue.extend({
})
if (this.playlistName === '') {
- this.showToast({
- message: 'Playlist name cannot be empty. Please input a name.'
- })
+ showToast('Playlist name cannot be empty. Please input a name.')
} else if (nameExists !== -1) {
- this.showToast({
- message: 'There is already a playlist with this name. Please pick a different name.'
- })
+ showToast('There is already a playlist with this name. Please pick a different name.')
} else {
try {
this.addPlaylist(playlistObject)
- this.showToast({
- message: `Playlist ${this.playlistName} has been successfully created.`
- })
+ showToast(`Playlist ${this.playlistName} has been successfully created.`)
} catch (e) {
- this.showToast({
- message: 'There was an issue with creating the playlist.'
- })
+ showToast('There was an issue with creating the playlist.')
console.error(e)
} finally {
this.hideCreatePlaylistPrompt()
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 1f9c5a9645624..a023296a50f81 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -607,13 +607,9 @@ export default defineComponent({
try {
this.removeVideo(payload)
this.$emit('refresh-playlist')
- this.showToast({
- message: 'Video has been removed'
- })
+ showToast('Video has been removed')
} catch (e) {
- this.showToast({
- message: 'There was a problem with removing this video'
- })
+ showToast('There was a problem with removing this video')
console.error(e)
}
},
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 42a94ed2a1c31..f03c9779649a1 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -4,6 +4,9 @@ import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
import FtPrompt from '../ft-prompt/ft-prompt.vue'
import FtButton from '../ft-button/ft-button.vue'
import FtPlaylistSelector from '../ft-playlist-selector/ft-playlist-selector.vue'
+import {
+ showToast,
+} from '../../helpers/utils'
export default Vue.extend({
name: 'FtPlaylistAddVideoPrompt',
@@ -100,9 +103,7 @@ export default Vue.extend({
}
})
- this.showToast({
- message: `Video has been added to ${addedPlaylists} playlist(s).`
- })
+ showToast(`Video has been added to ${addedPlaylists} playlist(s).`)
this.handleAddToPlaylistPrompt(null)
},
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 8ea798aab2a93..50195c2c9005b 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -5,6 +5,9 @@ import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
import FtInput from '../ft-input/ft-input.vue'
import FtPrompt from '../ft-prompt/ft-prompt.vue'
+import {
+ showToast,
+} from '../../helpers/utils'
export default defineComponent({
name: 'PlaylistInfo',
@@ -161,13 +164,9 @@ export default defineComponent({
}
try {
this.updatePlaylist(playlist)
- this.showToast({
- message: 'Playlist has been updated.'
- })
+ showToast('Playlist has been updated.')
} catch (e) {
- this.showToast({
- message: 'There was an issue with updating this playlist.'
- })
+ showToast('There was an issue with updating this playlist.')
console.error(e)
} finally {
this.exitEditMode()
@@ -185,7 +184,6 @@ export default defineComponent({
},
handleRemoveVideosOnWatchPromptAnswer: function (option) {
- console.log(this.selectedPlaylist.videos)
if (option === 'yes') {
const videosToWatch = this.selectedPlaylist.videos.filter((video) => {
const watchedIndex = this.historyCache.findIndex((history) => {
@@ -198,9 +196,7 @@ export default defineComponent({
const videosRemoved = this.selectedPlaylist.videos.length - videosToWatch.length
if (videosRemoved === 0) {
- this.showToast({
- message: 'There were no videos to remove.'
- })
+ showToast('There were no videos to remove.')
this.showRemoveVideosOnWatchPrompt = false
return
}
@@ -215,13 +211,9 @@ export default defineComponent({
}
try {
this.updatePlaylist(playlist)
- this.showToast({
- message: `${videosRemoved} video(s) have been removed.`
- })
+ showToast(`${videosRemoved} video(s) have been removed.`)
} catch (e) {
- this.showToast({
- message: 'There was an issue with updating this playlist.'
- })
+ showToast('There was an issue with updating this playlist.')
console.error(e)
}
}
@@ -230,9 +222,7 @@ export default defineComponent({
handleDeletePlaylistPromptAnswer: function (option) {
if (this.selectedPlaylist.protected) {
- this.showToast({
- message: 'This playlist is protected and cannot be removed.'
- })
+ showToast('This playlist is protected and cannot be removed.')
} else if (option === 'yes') {
this.removePlaylist(this.id)
this.$router.push(
@@ -240,9 +230,7 @@ export default defineComponent({
path: '/userPlaylists'
}
)
- this.showToast({
- message: `${this.title} has been deleted.`
- })
+ showToast(`${this.title} has been deleted.`)
}
this.showDeletePlaylistPrompt = false
},
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 442b9070a6738..9b7357933caea 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -279,9 +279,7 @@ export default defineComponent({
})
if (videoIndex === 0) {
- showToast({
- message: 'This video cannot be moved up.'
- })
+ showToast('This video cannot be moved up.')
return
}
@@ -302,9 +300,7 @@ export default defineComponent({
this.updatePlaylist(playlist)
this.playlistItems = playlistItems
} catch (e) {
- showToast({
- message: 'There was an issue with updating this playlist.'
- })
+ showToast('There was an issue with updating this playlist.')
console.error(e)
}
},
@@ -316,9 +312,7 @@ export default defineComponent({
})
if (videoIndex + 1 === playlistItems.length || videoIndex + 1 > playlistItems.length) {
- showToast({
- message: 'This video cannot be moved down.'
- })
+ showToast('This video cannot be moved down.')
return
}
@@ -339,9 +333,7 @@ export default defineComponent({
this.updatePlaylist(playlist)
this.playlistItems = playlistItems
} catch (e) {
- showToast({
- message: 'There was an issue with updating this playlist.'
- })
+ showToast('There was an issue with updating this playlist.')
console.error(e)
}
},
From e152d3aaba9804a001cfbe5460077fee364838bf Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 10:41:40 +0800
Subject: [PATCH 010/236] * Ensure local playlist has internal ID
Though on restart the internal IDs in saved playlists are present
---
src/renderer/store/modules/playlists.js | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 110de0c50bded..ee9ac3c218930 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -1,5 +1,9 @@
import { DBPlaylistHandlers } from '../../../datastores/handlers/index'
+function generateRandomPlaylistId() {
+ return `${Date.now()}-${Math.floor(Math.random() * 10000)}`
+}
+
const state = {
playlists: [],
defaultPlaylists: [
@@ -31,6 +35,12 @@ const getters = {
const actions = {
async addPlaylist({ commit }, payload) {
+ // In case internal id is forgotten, generate one (instead of relying on caller and have a chance to cause data corruption)
+ if (payload._id == null) {
+ // {Time now in unix time}-{0-9999}
+ payload._id = generateRandomPlaylistId()
+ }
+
try {
await DBPlaylistHandlers.create(payload)
commit('addPlaylist', payload)
@@ -83,6 +93,17 @@ const actions = {
if (payload.length === 0) {
dispatch('addPlaylists', state.defaultPlaylists)
} else {
+ payload.forEach((playlist) => {
+ // Assign generated playlist ID in case DB data corrupted
+ // Especially during dev
+ if (playlist._id == null) {
+ // {Time now in unix time}-{0-9999}
+ playlist._id = generateRandomPlaylistId()
+ }
+ // Save updated playlist object
+ commit('upsertPlaylistToList', playlist)
+ })
+
const findFavorites = payload.filter((playlist) => {
return playlist.playlistName === 'Favorites' || playlist._id === 'favorites'
})
From 963bdd9682b34b85b51ba37e25580ef173ed441f Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 10:46:56 +0800
Subject: [PATCH 011/236] ! Fix user playlist data parsing
---
src/renderer/components/ft-list-playlist/ft-list-playlist.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.js b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
index 6788a69759531..64c857739f17b 100644
--- a/src/renderer/components/ft-list-playlist/ft-list-playlist.js
+++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
@@ -97,6 +97,8 @@ export default defineComponent({
this.thumbnail = 'https://i.ytimg.com/vi/aaaaaa/mqdefault.jpg'
}
this.channelName = ''
+ this.channelId = ''
+ this.playlistId = this.data._id
this.videoCount = this.data.videoCount
},
From 5fc1520b33df06b4451ad29b5269d19a7a31c5f7 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 11:12:07 +0800
Subject: [PATCH 012/236] ! Fix playlist button alignment
---
.../playlist-info/playlist-info.scss | 9 +++++-
.../playlist-info/playlist-info.vue | 32 ++++++++-----------
2 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.scss b/src/renderer/components/playlist-info/playlist-info.scss
index f06dca68fe2e3..f9945b74fb93e 100644
--- a/src/renderer/components/playlist-info/playlist-info.scss
+++ b/src/renderer/components/playlist-info/playlist-info.scss
@@ -58,5 +58,12 @@
.channelShareWrapper {
column-gap: 8px;
display: grid;
- grid-template-columns: 1fr auto;
+ grid-template-columns: auto minmax(min-content, 1fr);
+}
+
+.playlistOptions {
+ display: grid;
+ grid-auto-flow: column;
+ column-gap: 8px;
+ justify-content: flex-end;
}
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 9972d19805c98..7385d1cbc1b33 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -83,61 +83,57 @@
-
-
+
-
-
-
+
+
-
Date: Wed, 17 May 2023 11:18:01 +0800
Subject: [PATCH 013/236] ! Fix copy & paste mistake
---
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 50195c2c9005b..06a9b7aedb5af 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -180,7 +180,7 @@ export default defineComponent({
},
exitEditMode: function () {
- this.newTitle = this.title
+ this.editMode = false
},
handleRemoveVideosOnWatchPromptAnswer: function (option) {
From 5c94b7aeedd2666f018b07caf105fc4440372d38 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 11:41:34 +0800
Subject: [PATCH 014/236] * Make playlist update visible immediately (title &
description)
---
.../playlist-info/playlist-info.vue | 10 ++---
src/renderer/store/modules/playlists.js | 16 ++++++-
src/renderer/views/Playlist/Playlist.js | 45 +++++++++++--------
3 files changed, 45 insertions(+), 26 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 7385d1cbc1b33..09a76540c1c22 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -37,13 +37,11 @@
- {{ viewCount }} {{ $t("Playlist.Views") }}
-
- -
-
- {{ $t("Playlist.Last Updated On") }}
-
- {{ lastUpdated }}
+ -
+
+ {{ $t("Playlist.Last Updated On") }}
+ {{ lastUpdated }}
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index ee9ac3c218930..4fb17b0a302a2 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -59,6 +59,9 @@ const actions = {
},
async updatePlaylist({ commit }, playlist) {
+ // Caller no need to assign last updated time
+ playlist.lastUpdatedAt = Date.now()
+
try {
await DBPlaylistHandlers.upsert(playlist)
commit('upsertPlaylistToList', playlist)
@@ -94,14 +97,25 @@ const actions = {
dispatch('addPlaylists', state.defaultPlaylists)
} else {
payload.forEach((playlist) => {
+ let anythingUpdated = false
// Assign generated playlist ID in case DB data corrupted
// Especially during dev
if (playlist._id == null) {
// {Time now in unix time}-{0-9999}
playlist._id = generateRandomPlaylistId()
+ anythingUpdated = true
+ }
+ // Assign current time as last updated time in case DB data corrupted
+ // Especially during dev
+ if (playlist.lastUpdatedAt == null) {
+ // Time now in unix time, in ms
+ playlist.lastUpdatedAt = Date.now()
+ anythingUpdated = true
}
// Save updated playlist object
- commit('upsertPlaylistToList', playlist)
+ if (anythingUpdated) {
+ commit('upsertPlaylistToList', playlist)
+ }
})
const findFavorites = payload.filter((playlist) => {
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 9b7357933caea..fd5654eb587e5 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -68,12 +68,17 @@ export default defineComponent({
userPlaylists: function () {
return this.$store.getters.getAllPlaylists
},
- selectedPlaylist: function () {
+ selectedUserPlaylist: function () {
+ if (this.playlistId == null) { return null }
+
return this.userPlaylists.find(playlist => playlist._id === this.playlistId)
},
- selectedVideos: function () {
- if (typeof (this.selectedPlaylist) !== 'undefined') {
- return this.selectedPlaylist.videos
+ selectedUserPlaylistLastUpdatedAt: function () {
+ return this.selectedUserPlaylist?.lastUpdatedAt
+ },
+ selectedUserPlaylistVideos: function () {
+ if (typeof (this.selectedUserPlaylist) !== 'undefined') {
+ return this.selectedUserPlaylist.videos
} else {
return []
}
@@ -84,14 +89,15 @@ export default defineComponent({
// react to route changes...
this.getPlaylistInfo()
},
- // selectedPlaylist () {
- // if (this.isLoading) {
- // // Ignores first time load of page
- // return
- // }
- // this.refreshPage()
- // },
- // selectedVideos () {
+ selectedUserPlaylist () {
+ // Fetch from local store when current user playlist changed
+ this.getPlaylistInfo()
+ },
+ selectedUserPlaylistLastUpdatedAt () {
+ // Re-fetch from local store when current user playlist updated
+ this.getPlaylistInfo()
+ },
+ // selectedUserPlaylistVideos () {
// if (this.isLoading) {
// // Ignores first time load of page
// return
@@ -107,8 +113,8 @@ export default defineComponent({
this.isLoading = true
this.playlistId = this.$route.params.id
- if (this.selectedPlaylist != null) {
- this.parseUserPlaylist(this.selectedPlaylist)
+ if (this.selectedUserPlaylist != null) {
+ this.parseUserPlaylist(this.selectedUserPlaylist)
return
}
@@ -233,7 +239,8 @@ export default defineComponent({
}
this.viewCount = 0
this.videoCount = playlist.videoCount ? playlist.videoCount : playlist.videos.length
- this.lastUpdated = undefined
+ const dateString = new Date(playlist.lastUpdatedAt)
+ this.lastUpdated = dateString.toLocaleDateString(this.currentLocale, { year: 'numeric', month: 'short', day: 'numeric' })
this.channelName = playlist.author ? playlist.author.name : ''
this.channelThumbnail = playlist.author ? playlist.author.bestAvatar.url : ''
this.channelId = playlist.author ? playlist.author.channelID : ''
@@ -290,8 +297,8 @@ export default defineComponent({
const playlist = {
playlistName: this.playlistTitle,
- protected: this.selectedPlaylist.protected,
- removeOnWatched: this.selectedPlaylist.removeOnWatched,
+ protected: this.selectedUserPlaylist.protected,
+ removeOnWatched: this.selectedUserPlaylist.removeOnWatched,
description: this.playlistDescription,
videos: playlistItems,
_id: this.playlistId
@@ -323,8 +330,8 @@ export default defineComponent({
const playlist = {
playlistName: this.playlistTitle,
- protected: this.selectedPlaylist.protected,
- removeOnWatched: this.selectedPlaylist.removeOnWatched,
+ protected: this.selectedUserPlaylist.protected,
+ removeOnWatched: this.selectedUserPlaylist.removeOnWatched,
description: this.playlistDescription,
videos: playlistItems,
_id: this.playlistId
From b7007b5d67f6c457ee85cacb6a0fc5f8d345f833 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 11:43:41 +0800
Subject: [PATCH 015/236] * Update user playlist parsing to just return empty
string for channel stuff
---
src/renderer/views/Playlist/Playlist.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index fd5654eb587e5..aa19c78dcf4c6 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -241,9 +241,9 @@ export default defineComponent({
this.videoCount = playlist.videoCount ? playlist.videoCount : playlist.videos.length
const dateString = new Date(playlist.lastUpdatedAt)
this.lastUpdated = dateString.toLocaleDateString(this.currentLocale, { year: 'numeric', month: 'short', day: 'numeric' })
- this.channelName = playlist.author ? playlist.author.name : ''
- this.channelThumbnail = playlist.author ? playlist.author.bestAvatar.url : ''
- this.channelId = playlist.author ? playlist.author.channelID : ''
+ this.channelName = ''
+ this.channelThumbnail = ''
+ this.channelId = ''
this.infoSource = 'user'
this.playlistItems = playlist.videos
From 133bd042b3f66d99d0e885392a723c4a1465b5fd Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 11:48:45 +0800
Subject: [PATCH 016/236] * Don't display protected playlist prompt when user
press No
---
.../components/playlist-info/playlist-info.js | 22 ++++++++++---------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 06a9b7aedb5af..b495996c34cb2 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -221,16 +221,18 @@ export default defineComponent({
},
handleDeletePlaylistPromptAnswer: function (option) {
- if (this.selectedPlaylist.protected) {
- showToast('This playlist is protected and cannot be removed.')
- } else if (option === 'yes') {
- this.removePlaylist(this.id)
- this.$router.push(
- {
- path: '/userPlaylists'
- }
- )
- showToast(`${this.title} has been deleted.`)
+ if (option === 'yes') {
+ if (this.selectedPlaylist.protected) {
+ showToast('This playlist is protected and cannot be removed.')
+ } else {
+ this.removePlaylist(this.id)
+ this.$router.push(
+ {
+ path: '/userPlaylists'
+ }
+ )
+ showToast(`${this.title} has been deleted.`)
+ }
}
this.showDeletePlaylistPrompt = false
},
From fa5370879bce33a97138dde528111769d5b0ba81 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 11:56:32 +0800
Subject: [PATCH 017/236] ! Fix code inconsistency
---
src/renderer/store/modules/playlists.js | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 4fb17b0a302a2..ef762463faf8a 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -126,8 +126,9 @@ const actions = {
})
if (findFavorites.length === 0) {
- dispatch('addPlaylist', state.defaultPlaylists.find((e) => e._id === 'favorites'))
- payload.push(state.defaultPlaylists[0])
+ const favoritesPlaylist = state.defaultPlaylists.find((e) => e._id === 'favorites')
+ dispatch('addPlaylist', favoritesPlaylist)
+ payload.push(favoritesPlaylist)
} else {
const favoritesPlaylist = findFavorites[0]
@@ -140,8 +141,9 @@ const actions = {
}
if (findWatchLater.length === 0) {
- dispatch('addPlaylist', state.defaultPlaylists.find((e) => e._id === 'watchLater'))
- payload.push(state.defaultPlaylists[1])
+ const watchLaterPlaylist = state.defaultPlaylists.find((e) => e._id === 'watchLater')
+ dispatch('addPlaylist', watchLaterPlaylist)
+ payload.push(watchLaterPlaylist)
} else {
const watchLaterPlaylist = findWatchLater[0]
From 07150d1edac5a9cc47946a8fed19b7f7543d6548 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 12:06:26 +0800
Subject: [PATCH 018/236] * Ensure default playlists are protected
---
src/renderer/store/modules/playlists.js | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index ef762463faf8a..182ddfe1cf3a8 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -132,11 +132,12 @@ const actions = {
} else {
const favoritesPlaylist = findFavorites[0]
- if (favoritesPlaylist._id !== 'favorites') {
+ if (favoritesPlaylist._id !== 'favorites' || !favoritesPlaylist.protected) {
const oldId = favoritesPlaylist._id
favoritesPlaylist._id = 'favorites'
- dispatch('addPlaylist', favoritesPlaylist)
+ favoritesPlaylist.protected = true
dispatch('removePlaylist', oldId)
+ dispatch('addPlaylist', favoritesPlaylist)
}
}
@@ -150,8 +151,9 @@ const actions = {
if (watchLaterPlaylist._id !== 'watchLater') {
const oldId = watchLaterPlaylist._id
watchLaterPlaylist._id = 'watchLater'
- dispatch('addPlaylist', watchLaterPlaylist)
+ watchLaterPlaylist.protected = true
dispatch('removePlaylist', oldId)
+ dispatch('addPlaylist', watchLaterPlaylist)
}
}
From 8af55cdda6c3b5510f1b43dfb783f4e3fdd9df10 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 14:23:25 +0800
Subject: [PATCH 019/236] * Ensure new playlists are added with last updated
time too
---
src/renderer/store/modules/playlists.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 182ddfe1cf3a8..1548dd6401442 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -40,6 +40,7 @@ const actions = {
// {Time now in unix time}-{0-9999}
payload._id = generateRandomPlaylistId()
}
+ payload.lastUpdatedAt = Date.now()
try {
await DBPlaylistHandlers.create(payload)
From f19b8c7a001988fac5c6803778cfe9cfbd3b91d5 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 14:25:21 +0800
Subject: [PATCH 020/236] * Hide playlist delete button on protected playlists
---
src/renderer/components/playlist-info/playlist-info.js | 9 +++++++++
src/renderer/components/playlist-info/playlist-info.vue | 2 +-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index b495996c34cb2..2ff08948a9f7a 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -140,6 +140,15 @@ export default defineComponent({
return `${baseUrl}/vi/${this.firstVideoId}/mqdefault.jpg`
}
},
+
+ deletePlaylistButtonVisible: function() {
+ if (this.infoSource !== 'user') { return false }
+ // Cannot delete during edit
+ if (this.editMode) { return false }
+
+ // Cannot delete protected playlist
+ return !this.selectedPlaylist.protected
+ },
},
mounted: function () {
this.newTitle = this.title
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 09a76540c1c22..9fa134e4abb65 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -118,7 +118,7 @@
@click="showRemoveVideosOnWatchPrompt = true"
/>
Date: Wed, 17 May 2023 14:28:23 +0800
Subject: [PATCH 021/236] * Hide share button for user playlist
It CANNOT be used
---
src/renderer/components/playlist-info/playlist-info.js | 8 ++++++++
src/renderer/components/playlist-info/playlist-info.vue | 2 +-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 2ff08948a9f7a..68d34d5d956dd 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -149,6 +149,14 @@ export default defineComponent({
// Cannot delete protected playlist
return !this.selectedPlaylist.protected
},
+
+ sharePlaylistButtonVisible: function() {
+ // Only online playlists can be shared
+ if (this.infoSource === 'user') { return false }
+
+ // Cannot delete protected playlist
+ return !this.hideSharingActions
+ },
},
mounted: function () {
this.newTitle = this.title
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 9fa134e4abb65..16f908bff999c 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -125,7 +125,7 @@
@click="showDeletePlaylistPrompt = true"
/>
Date: Wed, 17 May 2023 14:34:02 +0800
Subject: [PATCH 022/236] ! Fix playlist info caching code
---
src/renderer/views/Playlist/Playlist.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index aa19c78dcf4c6..4616d7808f384 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -24,11 +24,11 @@ export default defineComponent({
if (!this.isLoading && to.path.startsWith('/watch') && to.query.playlistId === this.playlistId) {
this.setCachedPlaylist({
id: this.playlistId,
- title: this.infoData.title,
- channelName: this.infoData.channelName,
- channelId: this.infoData.channelId,
+ title: this.playlistTitle,
+ channelName: this.channelName,
+ channelId: this.channelId,
items: this.playlistItems,
- continuationData: this.continuationData
+ continuationData: this.continuationData,
})
}
next()
From 51b521d7bafae32655de2a2890abb606affa945d Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 15:17:52 +0800
Subject: [PATCH 023/236] ! Fix add/removing videos from favourite list
---
src/renderer/components/data-settings/data-settings.js | 2 +-
src/renderer/components/ft-list-video/ft-list-video.js | 8 ++++----
.../ft-playlist-add-video-prompt.js | 2 +-
.../components/watch-video-info/watch-video-info.js | 8 ++++----
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index f9647bba466fa..445153265aaf0 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -947,7 +947,7 @@ export default defineComponent({
if (!videoExists) {
const payload = {
playlistName: existingPlaylist.playlistName,
- videoData: video
+ videoData: video,
}
this.addVideo(payload)
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 a023296a50f81..80fd1f2a63f6f 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -583,7 +583,7 @@ export default defineComponent({
const payload = {
_id: 'favorites',
- videoData: videoData
+ videoData: videoData,
}
this.addVideo(payload)
@@ -591,8 +591,8 @@ export default defineComponent({
removeFromFavorites: function () {
const payload = {
- playlistName: 'Favorites',
- videoId: this.id
+ _id: 'favorites',
+ videoId: this.id,
}
this.removeVideo(payload)
@@ -601,7 +601,7 @@ export default defineComponent({
removeVideoFromPlaylist: function () {
const payload = {
_id: this.playlistId,
- videoId: this.id
+ videoId: this.id,
}
try {
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index f03c9779649a1..1d1a36ad18a7c 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -96,7 +96,7 @@ export default Vue.extend({
if (findVideo === -1) {
const payload = {
_id: playlist._id,
- videoData: this.playlistAddVideoObject
+ videoData: this.playlistAddVideoObject,
}
this.addVideo(payload)
addedPlaylists++
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index 58118ec47f77c..2875c88dfd356 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -336,8 +336,8 @@ export default defineComponent({
}
const payload = {
- playlistName: 'Favorites',
- videoData: videoData
+ _id: 'favorites',
+ videoData: videoData,
}
this.addVideo(payload)
@@ -347,8 +347,8 @@ export default defineComponent({
removeFromPlaylist: function () {
const payload = {
- playlistName: 'Favorites',
- videoId: this.id
+ _id: 'favorites',
+ videoId: this.id,
}
this.removeVideo(payload)
From 63066eac3b94675b640e45ff93f198714281d8b2 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 15:35:24 +0800
Subject: [PATCH 024/236] ! Fix playlist type not passed into video list item
component
---
.../components/ft-list-video-lazy/ft-list-video-lazy.js | 4 ++++
.../components/ft-list-video-lazy/ft-list-video-lazy.vue | 1 +
src/renderer/views/Playlist/Playlist.js | 7 ++++---
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
index 2ac01ba81357a..9bb225829018a 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
@@ -15,6 +15,10 @@ export default defineComponent({
type: String,
default: null
},
+ playlistType: {
+ type: String,
+ default: null
+ },
playlistIndex: {
type: Number,
default: null
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
index 590ca9e78e76a..eaebd426889e9 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
@@ -9,6 +9,7 @@
v-if="visible"
:data="data"
:playlist-id="playlistId"
+ :playlist-type="playlistType"
:playlist-index="playlistIndex"
:playlist-reverse="playlistReverse"
:playlist-shuffle="playlistShuffle"
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 4616d7808f384..f1da7ac05cdc9 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -36,7 +36,6 @@ export default defineComponent({
data: function () {
return {
isLoading: false,
- playlistId: '',
playlistTitle: '',
playlistDescription: '',
firstVideoId: '',
@@ -65,11 +64,15 @@ export default defineComponent({
currentLocale: function () {
return this.$i18n.locale.replace('_', '-')
},
+ playlistId: function() {
+ return this.$route.params.id
+ },
userPlaylists: function () {
return this.$store.getters.getAllPlaylists
},
selectedUserPlaylist: function () {
if (this.playlistId == null) { return null }
+ if (this.playlistId === '') { return null }
return this.userPlaylists.find(playlist => playlist._id === this.playlistId)
},
@@ -111,7 +114,6 @@ export default defineComponent({
methods: {
getPlaylistInfo: function () {
this.isLoading = true
- this.playlistId = this.$route.params.id
if (this.selectedUserPlaylist != null) {
this.parseUserPlaylist(this.selectedUserPlaylist)
@@ -228,7 +230,6 @@ export default defineComponent({
},
parseUserPlaylist: function (playlist) {
- this.playlistId = playlist._id
this.playlistTitle = playlist.title ? playlist.title : playlist.playlistName
this.playlistDescription = playlist.description ? playlist.description : ''
From de9d5db903dcf3fde49007529012f3c112422853 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 16:40:52 +0800
Subject: [PATCH 025/236] ! Fix playlist data loading issue on new windows
---
.../components/playlist-info/playlist-info.js | 26 +++++-------
.../watch-video-playlist.js | 41 ++++++++++++-------
src/renderer/store/modules/playlists.js | 16 +++++++-
src/renderer/views/Playlist/Playlist.js | 25 +++++++----
4 files changed, 69 insertions(+), 39 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 68d34d5d956dd..c3874a8cc21c5 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -106,12 +106,8 @@ export default defineComponent({
return this.$store.getters.getHideVideoViews
},
- userPlaylists: function () {
- return this.$store.getters.getAllPlaylists
- },
-
- selectedPlaylist: function () {
- return this.userPlaylists.find((playlist) => playlist._id === this.id)
+ selectedUserPlaylist: function () {
+ return this.$store.getters.getPlaylist(this.id)
},
deletePlaylistPromptNames: function () {
@@ -147,7 +143,7 @@ export default defineComponent({
if (this.editMode) { return false }
// Cannot delete protected playlist
- return !this.selectedPlaylist.protected
+ return !this.selectedUserPlaylist.protected
},
sharePlaylistButtonVisible: function() {
@@ -173,10 +169,10 @@ export default defineComponent({
savePlaylistInfo: function () {
const playlist = {
playlistName: this.newTitle,
- protected: this.selectedPlaylist.protected,
- removeOnWatched: this.selectedPlaylist.removeOnWatched,
+ protected: this.selectedUserPlaylist.protected,
+ removeOnWatched: this.selectedUserPlaylist.removeOnWatched,
description: this.newDescription,
- videos: this.selectedPlaylist.videos,
+ videos: this.selectedUserPlaylist.videos,
_id: this.id,
}
try {
@@ -202,7 +198,7 @@ export default defineComponent({
handleRemoveVideosOnWatchPromptAnswer: function (option) {
if (option === 'yes') {
- const videosToWatch = this.selectedPlaylist.videos.filter((video) => {
+ const videosToWatch = this.selectedUserPlaylist.videos.filter((video) => {
const watchedIndex = this.historyCache.findIndex((history) => {
return history.videoId === video.videoId
})
@@ -210,7 +206,7 @@ export default defineComponent({
return watchedIndex === -1
})
- const videosRemoved = this.selectedPlaylist.videos.length - videosToWatch.length
+ const videosRemoved = this.selectedUserPlaylist.videos.length - videosToWatch.length
if (videosRemoved === 0) {
showToast('There were no videos to remove.')
@@ -220,8 +216,8 @@ export default defineComponent({
const playlist = {
playlistName: this.title,
- protected: this.selectedPlaylist.protected,
- removeOnWatched: this.selectedPlaylist.removeOnWatched,
+ protected: this.selectedUserPlaylist.protected,
+ removeOnWatched: this.selectedUserPlaylist.removeOnWatched,
description: this.description,
videos: videosToWatch,
_id: this.id
@@ -239,7 +235,7 @@ export default defineComponent({
handleDeletePlaylistPromptAnswer: function (option) {
if (option === 'yes') {
- if (this.selectedPlaylist.protected) {
+ if (this.selectedUserPlaylist.protected) {
showToast('This playlist is protected and cannot be removed.')
} else {
this.removePlaylist(this.id)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index 28b0cd9b1fd34..1f06c717edfc2 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -30,7 +30,7 @@ export default defineComponent({
},
data: function () {
return {
- isLoading: false,
+ isLoading: true,
shuffleEnabled: false,
loopEnabled: false,
reversePlaylist: false,
@@ -50,12 +50,14 @@ export default defineComponent({
return this.$store.getters.getBackendFallback
},
- userPlaylists: function () {
- return this.$store.getters.getAllPlaylists
+ userPlaylistsReady: function () {
+ return this.$store.getters.getPlaylistsReady
},
+ selectedUserPlaylist: function () {
+ if (this.playlistId == null) { return null }
+ if (this.playlistId === '') { return null }
- selectedPlaylist: function () {
- return this.userPlaylists.find(playlist => playlist._id === this.playlistId)
+ return this.$store.getters.getPlaylist(this.playlistId)
},
currentVideoIndex: function () {
@@ -102,6 +104,9 @@ export default defineComponent({
},
},
watch: {
+ userPlaylistsReady: function() {
+ this.getPlaylistInfoWithDelay()
+ },
videoId: function (newId, oldId) {
// Check if next video is from the shuffled list or if the user clicked a different video
if (this.shuffleEnabled) {
@@ -140,15 +145,10 @@ export default defineComponent({
},
mounted: function () {
const cachedPlaylist = this.$store.getters.getCachedPlaylist
-
if (cachedPlaylist?.id === this.playlistId) {
this.loadCachedPlaylistInformation(cachedPlaylist)
- } else if (this.selectedPlaylist != null) {
- this.parseUserPlaylist(this.selectedPlaylist)
- } else if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
- this.getPlaylistInformationInvidious()
} else {
- this.getPlaylistInformationLocal()
+ this.getPlaylistInfoWithDelay()
}
if ('mediaSession' in navigator) {
@@ -163,6 +163,19 @@ export default defineComponent({
}
},
methods: {
+ getPlaylistInfoWithDelay: function () {
+ this.isLoading = true
+ if (!this.userPlaylistsReady) { return }
+
+ if (this.selectedUserPlaylist != null) {
+ this.parseUserPlaylist(this.selectedUserPlaylist)
+ } else if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
+ this.getPlaylistInformationInvidious()
+ } else {
+ this.getPlaylistInformationLocal()
+ }
+ },
+
toggleLoop: function () {
if (this.loopEnabled) {
this.loopEnabled = false
@@ -403,9 +416,9 @@ export default defineComponent({
parseUserPlaylist: function (playlist) {
this.playlistTitle = playlist.title
this.videoCount = playlist.videoCount
- this.channelName = playlist.author ? playlist.author.name : ''
- this.channelThumbnail = playlist.author ? playlist.author.bestAvatar.url : ''
- this.channelId = playlist.author ? playlist.author.channelID : ''
+ this.channelName = ''
+ this.channelThumbnail = ''
+ this.channelId = ''
this.playlistItems = playlist.videos
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 1548dd6401442..6baa874b6baca 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -5,6 +5,10 @@ function generateRandomPlaylistId() {
}
const state = {
+ // Playlist loading takes time on app load (new windows)
+ // This is necessary to let components to know when to start data loading
+ // which depends on playlist data being ready
+ playlistsReady: false,
playlists: [],
defaultPlaylists: [
{
@@ -27,9 +31,12 @@ const state = {
}
const getters = {
+ getPlaylistsReady: () => state.playlistsReady,
getAllPlaylists: () => state.playlists,
getFavorites: () => state.playlists.find(playlist => playlist._id === 'favorites'),
- getPlaylist: (playlistId) => state.playlists.find(playlist => playlist._id === playlistId),
+ getPlaylist: (state) => (playlistId) => {
+ return state.playlists.find(playlist => playlist._id === playlistId)
+ },
getWatchLater: () => state.playlists.find(playlist => playlist._id === 'watchLater')
}
@@ -159,6 +166,7 @@ const actions = {
}
commit('setAllPlaylists', payload)
+ commit('setPlaylistsReady', true)
}
} catch (errMessage) {
console.error(errMessage)
@@ -288,7 +296,11 @@ const mutations = {
setAllPlaylists(state, payload) {
state.playlists = payload
- }
+ },
+
+ setPlaylistsReady(state, payload) {
+ state.playlistsReady = payload
+ },
}
export default {
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index f1da7ac05cdc9..78136740da6e1 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -1,5 +1,6 @@
import { defineComponent } from 'vue'
import { mapActions, mapMutations } from 'vuex'
+import debounce from 'lodash.debounce'
import FtLoader from '../../components/ft-loader/ft-loader.vue'
import FtCard from '../../components/ft-card/ft-card.vue'
import PlaylistInfo from '../../components/playlist-info/playlist-info.vue'
@@ -35,7 +36,7 @@ export default defineComponent({
},
data: function () {
return {
- isLoading: false,
+ isLoading: true,
playlistTitle: '',
playlistDescription: '',
firstVideoId: '',
@@ -49,6 +50,7 @@ export default defineComponent({
playlistItems: [],
continuationData: null,
isLoadingMore: false,
+ getPlaylistInfoDebounce: function() {},
}
},
computed: {
@@ -67,14 +69,14 @@ export default defineComponent({
playlistId: function() {
return this.$route.params.id
},
- userPlaylists: function () {
- return this.$store.getters.getAllPlaylists
+ userPlaylistsReady: function () {
+ return this.$store.getters.getPlaylistsReady
},
selectedUserPlaylist: function () {
if (this.playlistId == null) { return null }
if (this.playlistId === '') { return null }
- return this.userPlaylists.find(playlist => playlist._id === this.playlistId)
+ return this.$store.getters.getPlaylist(this.playlistId)
},
selectedUserPlaylistLastUpdatedAt: function () {
return this.selectedUserPlaylist?.lastUpdatedAt
@@ -90,15 +92,19 @@ export default defineComponent({
watch: {
$route () {
// react to route changes...
- this.getPlaylistInfo()
+ this.getPlaylistInfoDebounce()
+ },
+ userPlaylistsReady () {
+ // Fetch from local store when playlist data ready
+ this.getPlaylistInfoDebounce()
},
selectedUserPlaylist () {
// Fetch from local store when current user playlist changed
- this.getPlaylistInfo()
+ this.getPlaylistInfoDebounce()
},
selectedUserPlaylistLastUpdatedAt () {
// Re-fetch from local store when current user playlist updated
- this.getPlaylistInfo()
+ this.getPlaylistInfoDebounce()
},
// selectedUserPlaylistVideos () {
// if (this.isLoading) {
@@ -109,11 +115,14 @@ export default defineComponent({
// },
},
mounted: function () {
- this.getPlaylistInfo()
+ this.getPlaylistInfoDebounce = debounce(this.getPlaylistInfo, 100)
+ this.getPlaylistInfoDebounce()
},
methods: {
getPlaylistInfo: function () {
this.isLoading = true
+ // `selectedUserPlaylist` result accuracy relies on data being ready
+ if (!this.userPlaylistsReady) { return }
if (this.selectedUserPlaylist != null) {
this.parseUserPlaylist(this.selectedUserPlaylist)
From 86b7a924411e149eb552c48d87099820cdde2b10 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 17 May 2023 16:41:07 +0800
Subject: [PATCH 026/236] ! Fix user playlist data parsing
---
.../components/watch-video-playlist/watch-video-playlist.js | 2 +-
src/renderer/views/Playlist/Playlist.js | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index 1f06c717edfc2..a908f2e86f49b 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -414,7 +414,7 @@ export default defineComponent({
},
parseUserPlaylist: function (playlist) {
- this.playlistTitle = playlist.title
+ this.playlistTitle = playlist.playlistName
this.videoCount = playlist.videoCount
this.channelName = ''
this.channelThumbnail = ''
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 78136740da6e1..f7c73a4f6e590 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -239,8 +239,8 @@ export default defineComponent({
},
parseUserPlaylist: function (playlist) {
- this.playlistTitle = playlist.title ? playlist.title : playlist.playlistName
- this.playlistDescription = playlist.description ? playlist.description : ''
+ this.playlistTitle = playlist.playlistName
+ this.playlistDescription = playlist.description ?? ''
if (playlist.videos.length > 0) {
this.firstVideoId = playlist.videos[0].videoId
From 6b8db22a563a9a2a33657b894b40cd20e0a3a46b Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 18 May 2023 09:26:23 +0800
Subject: [PATCH 027/236] * Ensure playlist view rerender on video additonal
removal for displayed playlist
---
src/renderer/views/Playlist/Playlist.js | 27 ++++---------------------
1 file changed, 4 insertions(+), 23 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index f7c73a4f6e590..26040aaa3951d 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -106,13 +106,10 @@ export default defineComponent({
// Re-fetch from local store when current user playlist updated
this.getPlaylistInfoDebounce()
},
- // selectedUserPlaylistVideos () {
- // if (this.isLoading) {
- // // Ignores first time load of page
- // return
- // }
- // this.refreshPage()
- // },
+ selectedUserPlaylistVideos () {
+ // Re-fetch from local store when current user playlist videos updated
+ this.getPlaylistInfoDebounce()
+ },
},
mounted: function () {
this.getPlaylistInfoDebounce = debounce(this.getPlaylistInfo, 100)
@@ -355,22 +352,6 @@ export default defineComponent({
}
},
- refreshPage: function () {
- this.getPlaylistInfo()
- // The list of videos within a playlist do not refresh properly if a video
- // is removed, so the timeout forces the view to refresh. This is kinda hacky
- // and has to do with a quirk of Vue. I don't really like this solution but this
- // was the only way I could get it to update properly
- const yOffset = window.scrollY
- this.isLoading = true
- window.setTimeout(() => {
- this.isLoading = false
- window.setTimeout(() => {
- window.scrollTo(0, yOffset)
- }, 100)
- }, 100)
- },
-
...mapActions([
'updateSubscriptionDetails',
'updatePlaylist',
From 2474b57f419d9209c3d3bf7b035261428f628930 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 18 May 2023 09:38:29 +0800
Subject: [PATCH 028/236] ! Fix icons & moving videos up/down in user playlist
---
.../ft-list-video-lazy/ft-list-video-lazy.vue | 2 +
.../components/ft-list-video/ft-list-video.js | 37 ++++----
.../ft-list-video/ft-list-video.vue | 94 ++++++++++---------
src/renderer/main.js | 2 +
src/renderer/scss-partials/_ft-list-item.scss | 31 ++----
src/renderer/views/Playlist/Playlist.vue | 2 +-
6 files changed, 80 insertions(+), 88 deletions(-)
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
index eaebd426889e9..bcffc860c41a6 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
@@ -17,6 +17,8 @@
:force-list-type="forceListType"
:appearance="appearance"
@pause-player="$emit('pause-player')"
+ @move-video-up="(id) => $emit('move-video-up', id)"
+ @move-video-down="(id) => $emit('move-video-down', id)"
/>
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 80fd1f2a63f6f..0859c57ff4343 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -355,24 +355,24 @@ export default defineComponent({
}
},
- addToPlaylist: function () {
- const videoData = {
- videoId: this.id,
- title: this.title,
- author: this.channelName,
- authorId: this.channelId,
- published: '',
- description: this.description,
- viewCount: this.viewCount,
- lengthSeconds: this.data.lengthSeconds,
- timeAdded: new Date().getTime(),
- isLive: false,
- paid: false,
- type: 'video'
- }
-
- this.$emit('add-to-playlist', videoData)
- },
+ // addToPlaylist: function () {
+ // const videoData = {
+ // videoId: this.id,
+ // title: this.title,
+ // author: this.channelName,
+ // authorId: this.channelId,
+ // published: '',
+ // description: this.description,
+ // viewCount: this.viewCount,
+ // lengthSeconds: this.data.lengthSeconds,
+ // timeAdded: new Date().getTime(),
+ // isLive: false,
+ // paid: false,
+ // type: 'video'
+ // }
+ //
+ // this.$emit('add-to-playlist', videoData)
+ // },
toggleFavorite: function () {
if (this.inFavoritesPlaylist) {
@@ -606,7 +606,6 @@ export default defineComponent({
try {
this.removeVideo(payload)
- this.$emit('refresh-playlist')
showToast('Video has been removed')
} catch (e) {
showToast('There was a problem with removing this video')
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 08423d4e6626e..d57f8142a1cb2 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -44,52 +44,54 @@
:size="appearance === `watchPlaylistItem` ? 12 : 16"
@click="handleExternalPlayer"
/>
-
-
-
-
-
+
+
+
+
+
+
+
Date: Thu, 18 May 2023 09:57:13 +0800
Subject: [PATCH 029/236] * Don't show move up/down buttons when cannot be done
---
.../components/ft-list-video-lazy/ft-list-video-lazy.js | 8 ++++++++
.../components/ft-list-video-lazy/ft-list-video-lazy.vue | 2 ++
src/renderer/components/ft-list-video/ft-list-video.js | 8 ++++++++
src/renderer/components/ft-list-video/ft-list-video.vue | 4 ++--
src/renderer/views/Playlist/Playlist.vue | 2 ++
5 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
index 9bb225829018a..4dea31f027d52 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
@@ -47,6 +47,14 @@ export default defineComponent({
type: Boolean,
default: false,
},
+ canMoveVideoUp: {
+ type: Boolean,
+ default: false,
+ },
+ canMoveVideoDown: {
+ type: Boolean,
+ default: false,
+ },
},
data: function () {
return {
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
index bcffc860c41a6..cdfe5ab6b209c 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
@@ -16,6 +16,8 @@
:playlist-loop="playlistLoop"
:force-list-type="forceListType"
:appearance="appearance"
+ :can-move-video-up="canMoveVideoUp"
+ :can-move-video-down="canMoveVideoDown"
@pause-player="$emit('pause-player')"
@move-video-up="(id) => $emit('move-video-up', id)"
@move-video-down="(id) => $emit('move-video-down', id)"
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 0859c57ff4343..83910ec247f81 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -57,6 +57,14 @@ export default defineComponent({
type: Boolean,
default: false
},
+ canMoveVideoUp: {
+ type: Boolean,
+ default: false,
+ },
+ canMoveVideoDown: {
+ type: Boolean,
+ default: false,
+ },
},
data: function () {
return {
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 d57f8142a1cb2..234a2b24dff68 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -74,7 +74,7 @@
@click="removeVideoFromPlaylist"
/>
From 44638ab9b7cfe14b723f058e5efc5982a03c4e02 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 18 May 2023 10:49:37 +0800
Subject: [PATCH 030/236] * Make user playlist view filtering function now
works for filtering playlists
---
.../ft-element-list/ft-element-list.vue | 2 +-
.../views/UserPlaylists/UserPlaylists.js | 48 ++++++++-----------
2 files changed, 22 insertions(+), 28 deletions(-)
diff --git a/src/renderer/components/ft-element-list/ft-element-list.vue b/src/renderer/components/ft-element-list/ft-element-list.vue
index 28bd9be83a0c5..ba4a0ddb65650 100644
--- a/src/renderer/components/ft-element-list/ft-element-list.vue
+++ b/src/renderer/components/ft-element-list/ft-element-list.vue
@@ -4,7 +4,7 @@
>
{
- // if (typeof (video.title) !== 'string' || typeof (video.author) !== 'string') {
- // return false
- // } else {
- // return video.title.toLowerCase().includes(lowerCaseQuery) || video.author.toLowerCase().includes(lowerCaseQuery)
- // }
- // }).sort((a, b) => {
- // return b.timeAdded - a.timeAdded
- // })
- // if (filteredQuery.length <= this.searchDataLimit) {
- // this.showLoadMoreButton = false
- // } else {
- // this.showLoadMoreButton = true
- // }
- // this.activeData = filteredQuery.length < this.searchDataLimit ? filteredQuery : filteredQuery.slice(0, this.searchDataLimit)
- // }
+ if (this.lowerCaseQuery === '') {
+ this.activeData = this.fullData
+ this.showLoadMoreButton = this.allPlaylists.length > this.activeData.length
+ } else {
+ const filteredPlaylists = this.allPlaylists.filter((playlist) => {
+ if (typeof (playlist.playlistName) !== 'string') { return false }
+
+ return playlist.playlistName.toLowerCase().includes(this.lowerCaseQuery)
+ }).sort((a, b) => {
+ // Latest updated first
+ return b.lastUpdatedAt - a.lastUpdatedAt
+ })
+ this.showLoadMoreButton = filteredPlaylists.length > this.searchDataLimit
+ this.activeData = filteredPlaylists.length < this.searchDataLimit ? filteredPlaylists : filteredPlaylists.slice(0, this.searchDataLimit)
+ }
},
createNewPlaylist: function () {
From 2d01092af827f7633c23cb2fc7061a7ec99a95bd Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 18 May 2023 10:55:04 +0800
Subject: [PATCH 031/236] ! Fix style of prompt from any button within
playlist-info component
---
src/renderer/views/Playlist/Playlist.css | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/renderer/views/Playlist/Playlist.css b/src/renderer/views/Playlist/Playlist.css
index a3e82f26d0fd8..ec22bb9790dc2 100644
--- a/src/renderer/views/Playlist/Playlist.css
+++ b/src/renderer/views/Playlist/Playlist.css
@@ -11,6 +11,8 @@
padding: 10px;
position: sticky;
top: 96px;
+ /* This is needed to make prompt always above video entries */
+ z-index: 1;
width: 30%;
}
From 1682543c0da79e3b2110c6bed21599aca2aa1f58 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 18 May 2023 10:58:33 +0800
Subject: [PATCH 032/236] $ Refactor a function to use early return style
---
.../ft-create-playlist-prompt.js | 42 ++++++++++---------
1 file changed, 22 insertions(+), 20 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index 2bfabc5e0c130..1f498e5fc3a63 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -48,34 +48,36 @@ export default Vue.extend({
},
createNewPlaylist: function () {
- const videosObject = this.videoImportLength > 0 ? this.newPlaylistVideoObject.videos : []
+ if (this.playlistName === '') {
+ showToast('Playlist name cannot be empty. Please input a name.')
+ return
+ }
+
+ const nameExists = this.allPlaylists.findIndex((playlist) => {
+ return playlist.playlistName.toLowerCase() === this.playlistName.toLowerCase()
+ })
+ if (nameExists !== -1) {
+ showToast('There is already a playlist with this name. Please pick a different name.')
+ return
+ }
+ const videosObject = this.videoImportLength > 0 ? this.newPlaylistVideoObject.videos : []
const playlistObject = {
playlistName: this.playlistName,
protected: false,
removeOnWatched: false,
description: '',
- videos: videosObject
+ videos: videosObject,
}
- const nameExists = this.allPlaylists.findIndex((playlist) => {
- return playlist.playlistName.toLowerCase() === this.playlistName.toLowerCase()
- })
-
- if (this.playlistName === '') {
- showToast('Playlist name cannot be empty. Please input a name.')
- } else if (nameExists !== -1) {
- showToast('There is already a playlist with this name. Please pick a different name.')
- } else {
- try {
- this.addPlaylist(playlistObject)
- showToast(`Playlist ${this.playlistName} has been successfully created.`)
- } catch (e) {
- showToast('There was an issue with creating the playlist.')
- console.error(e)
- } finally {
- this.hideCreatePlaylistPrompt()
- }
+ try {
+ this.addPlaylist(playlistObject)
+ showToast(`Playlist ${this.playlistName} has been successfully created.`)
+ } catch (e) {
+ showToast('There was an issue with creating the playlist.')
+ console.error(e)
+ } finally {
+ this.hideCreatePlaylistPrompt()
}
},
From 38dbcb6a04df884364ef7c506a97785a9f8ee749 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 18 May 2023 11:00:53 +0800
Subject: [PATCH 033/236] * Disallow empty playlist name when saving in
playlist edit mode
---
src/renderer/components/playlist-info/playlist-info.js | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index c3874a8cc21c5..a0fa8961acdd3 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -167,6 +167,11 @@ export default defineComponent({
},
savePlaylistInfo: function () {
+ if (this.newTitle === '') {
+ showToast('Playlist name cannot be empty. Please input a name.')
+ return
+ }
+
const playlist = {
playlistName: this.newTitle,
protected: this.selectedUserPlaylist.protected,
From e2c93ba94f2663f41de3820e5e53a19ccd34636e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 18 May 2023 15:16:47 +0800
Subject: [PATCH 034/236] * Update add video to playlist prompt to have simple
filtering like user playlist view
---
.../ft-playlist-add-video-prompt.js | 39 ++++++++++++++++---
.../ft-playlist-add-video-prompt.vue | 13 ++++++-
2 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 1d1a36ad18a7c..f19cc8c2c12d2 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -1,9 +1,11 @@
import Vue from 'vue'
import { mapActions } from 'vuex'
+import debounce from 'lodash.debounce'
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
import FtPrompt from '../ft-prompt/ft-prompt.vue'
import FtButton from '../ft-button/ft-button.vue'
import FtPlaylistSelector from '../ft-playlist-selector/ft-playlist-selector.vue'
+import FtInput from '../../components/ft-input/ft-input.vue'
import {
showToast,
} from '../../helpers/utils'
@@ -11,10 +13,11 @@ import {
export default Vue.extend({
name: 'FtPlaylistAddVideoPrompt',
components: {
- FtFlexBox,
- FtPrompt,
- FtButton,
- FtPlaylistSelector,
+ 'ft-flex-box': FtFlexBox,
+ 'ft-prompt': FtPrompt,
+ 'ft-button': FtButton,
+ 'ft-playlist-selector': FtPlaylistSelector,
+ 'ft-input': FtInput,
},
data: function () {
return {
@@ -22,7 +25,9 @@ export default Vue.extend({
'save',
'cancel'
],
- selectedPlaylists: []
+ selectedPlaylists: [],
+ query: '',
+ updateQueryDebounce: function() {},
}
},
computed: {
@@ -66,10 +71,28 @@ export default Vue.extend({
'Save',
'Cancel'
]
- }
+ },
+
+ processedQuery: function() {
+ return this.query.trim().toLowerCase()
+ },
+ activePlaylists: function() {
+ // Very rare that a playlist name only has 1 char
+ if (this.processedQuery.length === 0) { return this.allPlaylists }
+
+ return this.allPlaylists.filter((playlist) => {
+ if (typeof (playlist.playlistName) !== 'string') { return false }
+
+ return playlist.playlistName.toLowerCase().includes(this.processedQuery)
+ }).sort((a, b) => {
+ // Latest updated first
+ return b.lastUpdatedAt - a.lastUpdatedAt
+ })
+ },
},
mounted: function () {
// this.parseUserData()
+ this.updateQueryDebounce = debounce(this.updateQuery, 500)
},
methods: {
handleAddToPlaylistPrompt: function (option) {
@@ -114,6 +137,10 @@ export default Vue.extend({
})
},
+ updateQuery: function(query) {
+ this.query = query
+ },
+
...mapActions([
'addVideo',
'hideAddToPlaylistPrompt',
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 858b435852bf4..0d98d4e4f7e60 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -8,10 +8,19 @@
{{ selectedPlaylistsCount }} Selected
+ updateQueryDebounce(input)"
+ @clear="updateQueryDebounce('')"
+ />
Date: Sat, 20 May 2023 11:36:48 +0800
Subject: [PATCH 035/236] * Update playlist view to only show video
reorder/remove buttons in edit mode
With notice message
---
.../components/ft-list-video-lazy/ft-list-video-lazy.js | 4 ++++
.../components/ft-list-video-lazy/ft-list-video-lazy.vue | 1 +
src/renderer/components/ft-list-video/ft-list-video.js | 4 ++++
src/renderer/components/ft-list-video/ft-list-video.vue | 2 +-
src/renderer/components/playlist-info/playlist-info.js | 4 ++++
src/renderer/components/playlist-info/playlist-info.vue | 8 ++++++++
src/renderer/views/Playlist/Playlist.js | 1 +
src/renderer/views/Playlist/Playlist.vue | 7 +++++--
8 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
index 4dea31f027d52..cdb10621c9554 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
@@ -55,6 +55,10 @@ export default defineComponent({
type: Boolean,
default: false,
},
+ canRemoveFromPlaylist: {
+ type: Boolean,
+ default: false,
+ },
},
data: function () {
return {
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
index cdfe5ab6b209c..32a42ab55db08 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
@@ -18,6 +18,7 @@
:appearance="appearance"
:can-move-video-up="canMoveVideoUp"
:can-move-video-down="canMoveVideoDown"
+ :can-remove-from-playlist="canRemoveFromPlaylist"
@pause-player="$emit('pause-player')"
@move-video-up="(id) => $emit('move-video-up', id)"
@move-video-down="(id) => $emit('move-video-down', id)"
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 83910ec247f81..8720f67319af1 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -65,6 +65,10 @@ export default defineComponent({
type: Boolean,
default: false,
},
+ canRemoveFromPlaylist: {
+ type: Boolean,
+ default: false,
+ },
},
data: function () {
return {
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 234a2b24dff68..ba899b53777ae 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -65,7 +65,7 @@
@click="togglePlaylistPrompt"
/>
+
+
+
+ Video order updates & removals are saved immediately and cannot be cancelled.
+
+
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 26040aaa3951d..54713df490a10 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -51,6 +51,7 @@ export default defineComponent({
continuationData: null,
isLoadingMore: false,
getPlaylistInfoDebounce: function() {},
+ playlistInEditMode: false,
}
},
computed: {
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index 661c23bf62430..27c878bc2b33b 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -20,6 +20,8 @@
:view-count="viewCount"
:info-source="infoSource"
class="playlistInfo"
+ @enter-edit-mode="playlistInEditMode = true"
+ @exit-edit-mode="playlistInEditMode = false"
/>
From cff9506cab3d0b1ba8f56c25f298cd79bbcb8c98 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 20 May 2023 16:22:47 +0800
Subject: [PATCH 036/236] ! Fix playlist view for remote playlist unnecessary
reload on save
---
src/renderer/views/Playlist/Playlist.js | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 54713df490a10..ea043970cc77c 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -83,31 +83,39 @@ export default defineComponent({
return this.selectedUserPlaylist?.lastUpdatedAt
},
selectedUserPlaylistVideos: function () {
- if (typeof (this.selectedUserPlaylist) !== 'undefined') {
+ if (this.selectedUserPlaylist != null) {
return this.selectedUserPlaylist.videos
} else {
return []
}
},
+ selectedUserPlaylistVideoCount: function() {
+ return this.selectedUserPlaylistVideos.length
+ }
},
watch: {
$route () {
// react to route changes...
this.getPlaylistInfoDebounce()
},
- userPlaylistsReady () {
+ userPlaylistsReady (val, oldVal) {
// Fetch from local store when playlist data ready
this.getPlaylistInfoDebounce()
},
- selectedUserPlaylist () {
+ selectedUserPlaylist (val, oldVal) {
// Fetch from local store when current user playlist changed
this.getPlaylistInfoDebounce()
},
- selectedUserPlaylistLastUpdatedAt () {
+ selectedUserPlaylistLastUpdatedAt (val, oldVal) {
// Re-fetch from local store when current user playlist updated
this.getPlaylistInfoDebounce()
},
- selectedUserPlaylistVideos () {
+ selectedUserPlaylistVideoCount (val, oldVal) {
+ // Monitoring `selectedUserPlaylistVideos` makes this function called
+ // Even when the same array object is returned
+ // So length is monitored instead
+ // Assuming in user playlist video cannot be swapped without length change
+
// Re-fetch from local store when current user playlist videos updated
this.getPlaylistInfoDebounce()
},
From 588cdcb419cd0293c78b7f6ca55a0956bced72e7 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 20 May 2023 16:34:37 +0800
Subject: [PATCH 037/236] ! Fix add to playlist prompt behaviour when some
playlists are hidden due to filtering
---
.../ft-playlist-add-video-prompt.js | 23 ++++++++++---------
.../ft-playlist-add-video-prompt.vue | 4 ++--
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index f19cc8c2c12d2..fef19d24a78b2 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -25,7 +25,7 @@ export default Vue.extend({
'save',
'cancel'
],
- selectedPlaylists: [],
+ selectedPlaylistIdSet: new Set(),
query: '',
updateQueryDebounce: function() {},
}
@@ -57,8 +57,8 @@ export default Vue.extend({
return a.title.localeCompare(b.title, this.locale)
})
},
- selectedPlaylistsCount: function () {
- return this.selectedPlaylists.length
+ selectedPlaylistIdSetCount: function () {
+ return this.selectedPlaylistIdSet.size
},
showAddToPlaylistPrompt: function () {
return this.$store.getters.getShowAddToPlaylistPrompt
@@ -99,20 +99,21 @@ export default Vue.extend({
this.hideAddToPlaylistPrompt()
},
- countSelected: function (index) {
- const indexOfVideo = this.selectedPlaylists.indexOf(index)
- if (indexOfVideo !== -1) {
- this.selectedPlaylists.splice(indexOfVideo, 1)
+ countSelected: function (playlistId) {
+ if (this.selectedPlaylistIdSet.has(playlistId)) {
+ this.selectedPlaylistIdSet.delete(playlistId)
} else {
- this.selectedPlaylists.push(index)
+ this.selectedPlaylistIdSet.add(playlistId)
}
},
addSelectedToPlaylists: function () {
let addedPlaylists = 0
- this.selectedPlaylists.forEach((index) => {
- const playlist = this.allPlaylists[index]
- const videoId = this.playlistAddVideoObject.videoId
+ const videoId = this.playlistAddVideoObject.videoId
+ this.selectedPlaylistIdSet.forEach((selectedPlaylistId) => {
+ const playlist = this.allPlaylists.find((list) => list._id === selectedPlaylistId)
+ if (playlist == null) { return }
+
const findVideo = playlist.videos.findIndex((video) => {
return video.videoId === videoId
})
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 0d98d4e4f7e60..35f2377378867 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -6,7 +6,7 @@
Select a Playlist to add your video(s) to
- {{ selectedPlaylistsCount }} Selected
+ {{ selectedPlaylistIdSetCount }} Selected
From 47b46d42af6a5c79ca244193e8bc78eee383c01b Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 22 May 2023 14:21:09 +0800
Subject: [PATCH 038/236] $ Remove unused watch function arguments
---
src/renderer/views/Playlist/Playlist.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index ea043970cc77c..98b2df06b6bd9 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -91,26 +91,26 @@ export default defineComponent({
},
selectedUserPlaylistVideoCount: function() {
return this.selectedUserPlaylistVideos.length
- }
+ },
},
watch: {
$route () {
// react to route changes...
this.getPlaylistInfoDebounce()
},
- userPlaylistsReady (val, oldVal) {
+ userPlaylistsReady () {
// Fetch from local store when playlist data ready
this.getPlaylistInfoDebounce()
},
- selectedUserPlaylist (val, oldVal) {
+ selectedUserPlaylist () {
// Fetch from local store when current user playlist changed
this.getPlaylistInfoDebounce()
},
- selectedUserPlaylistLastUpdatedAt (val, oldVal) {
+ selectedUserPlaylistLastUpdatedAt () {
// Re-fetch from local store when current user playlist updated
this.getPlaylistInfoDebounce()
},
- selectedUserPlaylistVideoCount (val, oldVal) {
+ selectedUserPlaylistVideoCount () {
// Monitoring `selectedUserPlaylistVideos` makes this function called
// Even when the same array object is returned
// So length is monitored instead
From 50be4d7729f984ed850a8e1dda3a7f591ca43866 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 23 May 2023 10:23:46 +0800
Subject: [PATCH 039/236] * Update user playlist view create new playlist
button position
---
.../views/UserPlaylists/UserPlaylists.css | 14 ++++---
.../views/UserPlaylists/UserPlaylists.vue | 40 ++++++++++---------
2 files changed, 30 insertions(+), 24 deletions(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.css b/src/renderer/views/UserPlaylists/UserPlaylists.css
index 4c4bf510e1cb7..255344bd2b8e3 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.css
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.css
@@ -6,14 +6,18 @@
margin-bottom: 60px;
}
-.message {
- color: var(--tertiary-text-color);
+.headingText {
+ display: inline-block;
}
.newPlaylistButton {
- position: absolute;
- top: 20px;
- right: 20px;
+ margin-left: 0.5em;
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.message {
+ color: var(--tertiary-text-color);
}
@media only screen and (max-width: 680px) {
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index 01ff187d3781c..6348a4437aef9 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -8,25 +8,27 @@
v-show="!isLoading"
class="card"
>
-
- {{ $t("User Playlists.Your Playlists") }}
-
-
- query = input"
- @clear="query = ''"
- />
+
+
+ {{ $t("User Playlists.Your Playlists") }}
+
+
+ query = input"
+ @clear="query = ''"
+ />
+
From eb3b38b6a80f593d2b78694bed9ac25c2e376aea Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 23 May 2023 11:00:46 +0800
Subject: [PATCH 040/236] * Update playlist view to add transitions to video
reorder/removal
---
src/renderer/views/Playlist/Playlist.css | 10 ++++++++++
src/renderer/views/Playlist/Playlist.vue | 8 +++++---
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.css b/src/renderer/views/Playlist/Playlist.css
index ec22bb9790dc2..a6456a9262c76 100644
--- a/src/renderer/views/Playlist/Playlist.css
+++ b/src/renderer/views/Playlist/Playlist.css
@@ -32,6 +32,16 @@
align-items: center;
}
+.playlistItem-move ,
+.playlistItem-enter-active,
+.playlistItem-leave-active {
+ transition: all 0.2s ease;
+}
+.playlistItem-enter, .playlistItem-leave-to {
+ opacity: 0;
+ transform: translateX(10%);
+}
+
.videoIndex {
color: var(--tertiary-text-color);
}
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index 27c878bc2b33b..ce89fe9c5fa68 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -28,12 +28,14 @@
v-if="!isLoading"
class="playlistItems"
>
-
-
+
From 3335ac614dea6f57bed5a83b9e1c8d1535b34e84 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 23 May 2023 11:22:48 +0800
Subject: [PATCH 041/236] * Allow playlist with different case to be created
---
.../ft-create-playlist-prompt/ft-create-playlist-prompt.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index 1f498e5fc3a63..b9d81ec48a98f 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -54,7 +54,7 @@ export default Vue.extend({
}
const nameExists = this.allPlaylists.findIndex((playlist) => {
- return playlist.playlistName.toLowerCase() === this.playlistName.toLowerCase()
+ return playlist.playlistName === this.playlistName
})
if (nameExists !== -1) {
showToast('There is already a playlist with this name. Please pick a different name.')
From 59fe674e3a571f8b21439bc400cb62b211caebfe Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 23 May 2023 11:30:25 +0800
Subject: [PATCH 042/236] * Update visibility of user playlist related action
components according to hide playlist settings
Only those visible on video, remote playlist are updated
---
src/renderer/components/ft-list-video/ft-list-video.js | 4 ++++
src/renderer/components/ft-list-video/ft-list-video.vue | 4 ++--
src/renderer/components/playlist-info/playlist-info.js | 4 ++++
src/renderer/components/playlist-info/playlist-info.vue | 2 +-
4 files changed, 11 insertions(+), 3 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 8720f67319af1..c76702fab4e51 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -111,6 +111,10 @@ export default defineComponent({
return this.$store.getters.getCurrentInvidiousInstance
},
+ showPlaylists: function () {
+ return !this.$store.getters.getHidePlaylists
+ },
+
inHistory: function () {
// When in the history page, showing relative dates isn't very useful.
// We want to show the exact date instead
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 ba899b53777ae..cb3fb6311147b 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -46,7 +46,7 @@
/>
Date: Tue, 23 May 2023 11:42:59 +0800
Subject: [PATCH 043/236] * Update video items to only show add to playlist
buttons on hover
---
.../components/ft-list-video/ft-list-video.vue | 4 ++--
src/renderer/scss-partials/_ft-list-item.scss | 10 ++++++++++
2 files changed, 12 insertions(+), 2 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 cb3fb6311147b..47f497492fdd7 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -49,7 +49,7 @@
v-if="showPlaylists && !isUpcoming"
:title="$t('Video.Save Video')"
:icon="['fas', 'star']"
- class="favoritesIcon"
+ class="favoritesIcon addToPlaylistIcon"
:theme="favoriteIconTheme"
:padding="appearance === `watchPlaylistItem` ? 5 : 6"
:size="appearance === `watchPlaylistItem` ? 14 : 18"
@@ -59,7 +59,7 @@
v-if="showPlaylists && !isLive"
title="Add to playlist"
:icon="['fas', 'plus']"
- class="playlistIcon"
+ class="playlistIcon addToPlaylistIcon"
:padding="appearance === `watchPlaylistItem` ? 5 : 6"
:size="appearance === `watchPlaylistItem` ? 14 : 18"
@click="togglePlaylistPrompt"
diff --git a/src/renderer/scss-partials/_ft-list-item.scss b/src/renderer/scss-partials/_ft-list-item.scss
index a51c30f47fc8a..89d5eceb5d0a9 100644
--- a/src/renderer/scss-partials/_ft-list-item.scss
+++ b/src/renderer/scss-partials/_ft-list-item.scss
@@ -170,6 +170,16 @@ $watched-transition-duration: 0.5s;
font-size: 17px;
}
+ // Show add to playlist buttons on hover only
+ .addToPlaylistIcon {
+ display: none;
+ }
+ &:hover {
+ .addToPlaylistIcon {
+ display: inherit;
+ }
+ }
+
.watchedProgressBar {
align-self: flex-end;
background-color: var(--primary-color);
From 6c4119786ac26086dfc0947c8a874db565b65606 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 23 May 2023 14:22:22 +0800
Subject: [PATCH 044/236] - Remove add to favorites button from video list item
component
---
.../components/ft-list-video/ft-list-video.js | 78 -------------------
.../ft-list-video/ft-list-video.vue | 10 ---
.../ft-playlist-selector.scss | 7 --
src/renderer/scss-partials/_ft-list-item.scss | 3 -
4 files changed, 98 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 c76702fab4e51..3a698f6aa52ab 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -271,22 +271,6 @@ export default defineComponent({
return this.watched && !this.inHistory
},
- favoritesPlaylist: function () {
- return this.$store.getters.getFavorites
- },
-
- inFavoritesPlaylist: function () {
- const index = this.favoritesPlaylist.videos.findIndex((video) => {
- return video.videoId === this.id
- })
-
- return index !== -1
- },
-
- favoriteIconTheme: function () {
- return this.inFavoritesPlaylist ? 'base favorite' : 'base'
- },
-
externalPlayer: function () {
return this.$store.getters.getExternalPlayer
},
@@ -371,35 +355,6 @@ export default defineComponent({
}
},
- // addToPlaylist: function () {
- // const videoData = {
- // videoId: this.id,
- // title: this.title,
- // author: this.channelName,
- // authorId: this.channelId,
- // published: '',
- // description: this.description,
- // viewCount: this.viewCount,
- // lengthSeconds: this.data.lengthSeconds,
- // timeAdded: new Date().getTime(),
- // isLive: false,
- // paid: false,
- // type: 'video'
- // }
- //
- // this.$emit('add-to-playlist', videoData)
- // },
-
- toggleFavorite: function () {
- if (this.inFavoritesPlaylist) {
- this.removeFromFavorites()
- showToast(this.$t('Video.Video has been removed from your saved list'))
- } else {
- this.addToFavorites()
- showToast(this.$t('Video.Video has been saved'))
- }
- },
-
handleOptionsClick: function (option) {
switch (option) {
case 'history':
@@ -581,39 +536,6 @@ export default defineComponent({
this.watchProgress = 0
},
- addToFavorites: function () {
- const videoData = {
- videoId: this.id,
- title: this.title,
- author: this.channelName,
- authorId: this.channelId,
- published: '',
- description: this.description,
- viewCount: this.viewCount,
- lengthSeconds: this.data.lengthSeconds,
- timeAdded: new Date().getTime(),
- isLive: false,
- paid: false,
- type: 'video'
- }
-
- const payload = {
- _id: 'favorites',
- videoData: videoData,
- }
-
- this.addVideo(payload)
- },
-
- removeFromFavorites: function () {
- const payload = {
- _id: 'favorites',
- videoId: this.id,
- }
-
- this.removeVideo(payload)
- },
-
removeVideoFromPlaylist: function () {
const payload = {
_id: this.playlistId,
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 47f497492fdd7..39326cbd5fd11 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -45,16 +45,6 @@
@click="handleExternalPlayer"
/>
-
Date: Tue, 23 May 2023 14:30:10 +0800
Subject: [PATCH 045/236] * Update watch-video-info component to add "add to
playlist" button
---
.../watch-video-info/watch-video-info.js | 26 ++++++++++++++++++-
.../watch-video-info/watch-video-info.vue | 8 ++++++
2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index 2875c88dfd356..25f2fb4804b79 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -125,6 +125,10 @@ export default defineComponent({
return this.$store.getters.getHideVideoViews
},
+ showPlaylists: function () {
+ return !this.$store.getters.getHidePlaylists
+ },
+
favoritesPlaylist: function () {
return this.$store.getters.getFavorites
},
@@ -356,11 +360,31 @@ export default defineComponent({
showToast(this.$t('Video.Video has been removed from your saved list'))
},
+ togglePlaylistPrompt: function () {
+ const videoData = {
+ videoId: this.id,
+ title: this.title,
+ author: this.channelName,
+ authorId: this.channelId,
+ published: '',
+ description: this.description,
+ viewCount: this.viewCount,
+ lengthSeconds: this.lengthSeconds,
+ timeAdded: new Date().getTime(),
+ isLive: false,
+ paid: false,
+ type: 'video',
+ }
+
+ this.showAddToPlaylistPrompt(videoData)
+ },
+
...mapActions([
'openInExternalPlayer',
'addVideo',
'removeVideo',
- 'downloadMedia'
+ 'downloadMedia',
+ 'showAddToPlaylistPrompt',
])
}
})
diff --git a/src/renderer/components/watch-video-info/watch-video-info.vue b/src/renderer/components/watch-video-info/watch-video-info.vue
index c28b1811299aa..af02552cda451 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.vue
+++ b/src/renderer/components/watch-video-info/watch-video-info.vue
@@ -89,6 +89,14 @@
:theme="favoriteIconTheme"
@click="toggleSave"
/>
+
Date: Tue, 23 May 2023 14:32:58 +0800
Subject: [PATCH 046/236] * Update watch-video-info component to remove "add to
favourite" button
---
.../watch-video-info/watch-video-info.js | 61 -------------------
.../watch-video-info/watch-video-info.vue | 8 ---
2 files changed, 69 deletions(-)
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index 25f2fb4804b79..77026a3c2e4de 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -129,22 +129,6 @@ export default defineComponent({
return !this.$store.getters.getHidePlaylists
},
- favoritesPlaylist: function () {
- return this.$store.getters.getFavorites
- },
-
- inFavoritesPlaylist: function () {
- const index = this.favoritesPlaylist.videos.findIndex((video) => {
- return video.videoId === this.id
- })
-
- return index !== -1
- },
-
- favoriteIconTheme: function () {
- return this.inFavoritesPlaylist ? 'base favorite' : 'base'
- },
-
downloadLinkOptions: function () {
return this.downloadLinks.map((download) => {
return {
@@ -275,14 +259,6 @@ export default defineComponent({
})
},
- toggleSave: function () {
- if (this.inFavoritesPlaylist) {
- this.removeFromPlaylist()
- } else {
- this.addToPlaylist()
- }
- },
-
handleFormatChange: function (format) {
switch (format) {
case 'dash':
@@ -323,43 +299,6 @@ export default defineComponent({
return group[1]
},
- addToPlaylist: function () {
- const videoData = {
- videoId: this.id,
- title: this.title,
- author: this.channelName,
- authorId: this.channelId,
- published: '',
- description: this.description,
- viewCount: this.viewCount,
- lengthSeconds: this.lengthSeconds,
- timeAdded: new Date().getTime(),
- isLive: false,
- paid: false,
- type: 'video'
- }
-
- const payload = {
- _id: 'favorites',
- videoData: videoData,
- }
-
- this.addVideo(payload)
-
- showToast(this.$t('Video.Video has been saved'))
- },
-
- removeFromPlaylist: function () {
- const payload = {
- _id: 'favorites',
- videoId: this.id,
- }
-
- this.removeVideo(payload)
-
- showToast(this.$t('Video.Video has been removed from your saved list'))
- },
-
togglePlaylistPrompt: function () {
const videoData = {
videoId: this.id,
diff --git a/src/renderer/components/watch-video-info/watch-video-info.vue b/src/renderer/components/watch-video-info/watch-video-info.vue
index af02552cda451..2e5eee4464521 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.vue
+++ b/src/renderer/components/watch-video-info/watch-video-info.vue
@@ -81,14 +81,6 @@
-->
-
Date: Tue, 23 May 2023 14:41:06 +0800
Subject: [PATCH 047/236] * Ensure video thumbnail image displayed in 16/9
aspect ratio
Mainly due to YT missing video thumbnail image got different aspect ratio 4/3
---
.../components/ft-playlist-selector/ft-playlist-selector.scss | 2 ++
src/renderer/components/playlist-info/playlist-info.scss | 2 ++
src/renderer/scss-partials/_ft-list-item.scss | 2 ++
3 files changed, 6 insertions(+)
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
index 5d8a2a825e82f..a451fdc3eb23c 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
@@ -222,6 +222,8 @@ $watched-transition-duration: 0.5s;
.thumbnailImage {
width: 100%;
+ // Ensure placeholder image displayed at same aspect ratio as most other images
+ aspect-ratio: 16/9;
}
}
.title {
diff --git a/src/renderer/components/playlist-info/playlist-info.scss b/src/renderer/components/playlist-info/playlist-info.scss
index f9945b74fb93e..c44e0db733fb4 100644
--- a/src/renderer/components/playlist-info/playlist-info.scss
+++ b/src/renderer/components/playlist-info/playlist-info.scss
@@ -5,6 +5,8 @@
.playlistThumbnail img {
cursor: pointer;
width: 100%;
+ // Ensure placeholder image displayed at same aspect ratio as most other images
+ aspect-ratio: 16/9;
@media only screen and (max-width: 800px) {
display: none;
diff --git a/src/renderer/scss-partials/_ft-list-item.scss b/src/renderer/scss-partials/_ft-list-item.scss
index 60582f9e86e0c..661071b2a3ddc 100644
--- a/src/renderer/scss-partials/_ft-list-item.scss
+++ b/src/renderer/scss-partials/_ft-list-item.scss
@@ -309,6 +309,8 @@ $watched-transition-duration: 0.5s;
.thumbnailImage {
width: 100%;
+ // Ensure placeholder image displayed at same aspect ratio as most other images
+ aspect-ratio: 16/9;
}
}
From b3a2b99a1b172e143afdbcfcd75e5e5ccb43e638 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 24 May 2023 08:59:45 +0800
Subject: [PATCH 048/236] * Update new buttons theme
---
.../components/playlist-info/playlist-info.vue | 13 +++++++------
src/renderer/views/UserPlaylists/UserPlaylists.vue | 2 +-
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index c683426cc0f9c..ea9f096086a3d 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -86,42 +86,43 @@
v-if="editMode"
title="Save Changes"
:icon="['fas', 'save']"
- theme="primary"
+ theme="secondary"
@click="savePlaylistInfo"
/>
+
From da71a8c9ae426697eba5cd845511456093ef9fb2 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 24 May 2023 09:27:03 +0800
Subject: [PATCH 049/236] * Put edit playlist button before copy button
---
.../components/playlist-info/playlist-info.vue | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index ea9f096086a3d..0f20044dbc9b6 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -97,13 +97,6 @@
@click="exitEditMode"
/>
-
+
Date: Wed, 24 May 2023 09:31:33 +0800
Subject: [PATCH 050/236] * Move "remove video from playlist" button to most
right
---
.../components/ft-list-video/ft-list-video.vue | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 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 39326cbd5fd11..d66a80ec75c01 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -54,15 +54,6 @@
:size="appearance === `watchPlaylistItem` ? 14 : 18"
@click="togglePlaylistPrompt"
/>
-
+
Date: Wed, 24 May 2023 09:45:28 +0800
Subject: [PATCH 051/236] * Make video reorder & remove button visible on hover
in user playlist view, regardless of "edit mode"
---
.../components/playlist-info/playlist-info.vue | 8 --------
src/renderer/scss-partials/_ft-list-item.scss | 12 +++++++++---
src/renderer/views/Playlist/Playlist.vue | 6 +++---
3 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 0f20044dbc9b6..fc59911de3146 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -148,14 +148,6 @@
@click="handleRemoveVideosOnWatchPromptAnswer"
/>
-
-
-
- Video order updates & removals are saved immediately and cannot be cancelled.
-
-
diff --git a/src/renderer/scss-partials/_ft-list-item.scss b/src/renderer/scss-partials/_ft-list-item.scss
index 661071b2a3ddc..57f97d559e915 100644
--- a/src/renderer/scss-partials/_ft-list-item.scss
+++ b/src/renderer/scss-partials/_ft-list-item.scss
@@ -167,12 +167,18 @@ $watched-transition-duration: 0.5s;
font-size: 17px;
}
- // Show add to playlist buttons on hover only
- .addToPlaylistIcon {
+ // Show some buttons on hover only
+ .addToPlaylistIcon ,
+ .trashIcon ,
+ .upArrowIcon ,
+ .downArrowIcon {
display: none;
}
&:hover {
- .addToPlaylistIcon {
+ .addToPlaylistIcon ,
+ .trashIcon ,
+ .upArrowIcon ,
+ .downArrowIcon {
display: inherit;
}
}
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index ce89fe9c5fa68..a04a01b5fbfd1 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -50,9 +50,9 @@
:playlist-index="index"
appearance="result"
force-list-type="list"
- :can-move-video-up="playlistInEditMode && index > 0"
- :can-move-video-down="playlistInEditMode && index < playlistItems.length - 1"
- :can-remove-from-playlist="playlistInEditMode"
+ :can-move-video-up="index > 0"
+ :can-move-video-down="index < playlistItems.length - 1"
+ :can-remove-from-playlist="true"
@move-video-up="moveVideoUp"
@move-video-down="moveVideoDown"
/>
From b1f043273186457fed55a257359802c2d43c90ae Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 24 May 2023 09:57:00 +0800
Subject: [PATCH 052/236] ! Fix video count parsing for user playlist
---
src/renderer/views/Playlist/Playlist.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 98b2df06b6bd9..c14a91ef75ecf 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -254,7 +254,7 @@ export default defineComponent({
this.firstVideoId = ''
}
this.viewCount = 0
- this.videoCount = playlist.videoCount ? playlist.videoCount : playlist.videos.length
+ this.videoCount = playlist.videos.length
const dateString = new Date(playlist.lastUpdatedAt)
this.lastUpdated = dateString.toLocaleDateString(this.currentLocale, { year: 'numeric', month: 'short', day: 'numeric' })
this.channelName = ''
From e079ac165f5821774eaa05f4ed249c1c116facc4 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 24 May 2023 10:58:01 +0800
Subject: [PATCH 053/236] * Update user playlist to allow duplicate video
entries (per video ID)
---
.../ft-create-playlist-prompt.js | 12 ++++++++-
.../ft-list-video-lazy/ft-list-video-lazy.vue | 5 ++--
.../components/ft-list-video/ft-list-video.js | 16 ------------
.../ft-list-video/ft-list-video.vue | 6 ++---
.../ft-playlist-add-video-prompt.js | 15 ++++-------
src/renderer/store/modules/playlists.js | 9 ++++++-
src/renderer/views/Playlist/Playlist.js | 25 ++++++++++++++++---
src/renderer/views/Playlist/Playlist.vue | 7 +++---
8 files changed, 55 insertions(+), 40 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index b9d81ec48a98f..61bb170e80af3 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -61,7 +61,17 @@ export default Vue.extend({
return
}
- const videosObject = this.videoImportLength > 0 ? this.newPlaylistVideoObject.videos : []
+ const videosObject = (this.videoImportLength > 0 ? this.newPlaylistVideoObject.videos : []).map((vobj) => {
+ if (vobj.timeAdded == null) {
+ vobj.timeAdded = new Date().getTime()
+ }
+ return Object.assign(vobj, {
+ published: '',
+ isLive: false,
+ paid: false,
+ type: 'video',
+ })
+ })
const playlistObject = {
playlistName: this.playlistName,
protected: false,
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
index 32a42ab55db08..2aa6684035965 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
@@ -20,8 +20,9 @@
:can-move-video-down="canMoveVideoDown"
:can-remove-from-playlist="canRemoveFromPlaylist"
@pause-player="$emit('pause-player')"
- @move-video-up="(id) => $emit('move-video-up', id)"
- @move-video-down="(id) => $emit('move-video-down', id)"
+ @move-video-up="$emit('move-video-up')"
+ @move-video-down="$emit('move-video-down')"
+ @remove-from-playlist="$emit('remove-from-playlist')"
/>
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 3a698f6aa52ab..c4e7947de848c 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -536,21 +536,6 @@ export default defineComponent({
this.watchProgress = 0
},
- removeVideoFromPlaylist: function () {
- const payload = {
- _id: this.playlistId,
- videoId: this.id,
- }
-
- try {
- this.removeVideo(payload)
- showToast('Video has been removed')
- } catch (e) {
- showToast('There was a problem with removing this video')
- console.error(e)
- }
- },
-
togglePlaylistPrompt: function () {
const videoData = {
videoId: this.id,
@@ -575,7 +560,6 @@ export default defineComponent({
'updateHistory',
'removeFromHistory',
'addVideo',
- 'removeVideo',
'showAddToPlaylistPrompt',
])
}
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 d66a80ec75c01..7aaa4556adb85 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -61,7 +61,7 @@
class="upArrowIcon"
:padding="appearance === `watchPlaylistItem` ? 5 : 6"
:size="appearance === `watchPlaylistItem` ? 14 : 18"
- @click="$emit('move-video-up', id)"
+ @click="$emit('move-video-up')"
/>
list._id === selectedPlaylistId)
if (playlist == null) { return }
- const findVideo = playlist.videos.findIndex((video) => {
- return video.videoId === videoId
- })
- if (findVideo === -1) {
- const payload = {
- _id: playlist._id,
- videoData: this.playlistAddVideoObject,
- }
- this.addVideo(payload)
- addedPlaylists++
+ const payload = {
+ _id: playlist._id,
+ videoData: this.playlistAddVideoObject,
}
+ this.addVideo(payload)
+ addedPlaylists++
})
showToast(`Video has been added to ${addedPlaylists} playlist(s).`)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 6baa874b6baca..d18df960d1c72 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -120,6 +120,13 @@ const actions = {
playlist.lastUpdatedAt = Date.now()
anythingUpdated = true
}
+ // Ensure all videos has `timeAdded` property
+ playlist.videos.forEach((v) => {
+ if (v.timeAdded != null) { return }
+
+ v.timeAdded = new Date().getTime()
+ anythingUpdated = true
+ })
// Save updated playlist object
if (anythingUpdated) {
commit('upsertPlaylistToList', playlist)
@@ -279,7 +286,7 @@ const mutations = {
removeVideo(state, payload) {
const playlist = state.playlists.find(playlist => playlist._id === payload._id)
if (playlist) {
- playlist.videos = playlist.videos.filter(video => video.videoId !== payload.videoId)
+ playlist.videos = playlist.videos.filter(video => video.videoId !== payload.videoId || video.timeAdded !== payload.timeAdded)
}
},
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index c14a91ef75ecf..5e4311c263cf6 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -295,10 +295,10 @@ export default defineComponent({
})
},
- moveVideoUp: function (videoId) {
+ moveVideoUp: function (videoId, timeAdded) {
const playlistItems = [].concat(this.playlistItems)
const videoIndex = playlistItems.findIndex((video) => {
- return video.videoId === videoId
+ return video.videoId === videoId && video.timeAdded === timeAdded
})
if (videoIndex === 0) {
@@ -328,10 +328,10 @@ export default defineComponent({
}
},
- moveVideoDown: function (videoId) {
+ moveVideoDown: function (videoId, timeAdded) {
const playlistItems = [].concat(this.playlistItems)
const videoIndex = playlistItems.findIndex((video) => {
- return video.videoId === videoId
+ return video.videoId === videoId && video.timeAdded === timeAdded
})
if (videoIndex + 1 === playlistItems.length || videoIndex + 1 > playlistItems.length) {
@@ -361,9 +361,26 @@ export default defineComponent({
}
},
+ removeVideoFromPlaylist: function (videoId, timeAdded) {
+ const payload = {
+ _id: this.playlistId,
+ videoId: videoId,
+ timeAdded: timeAdded,
+ }
+
+ try {
+ this.removeVideo(payload)
+ showToast('Video has been removed')
+ } catch (e) {
+ showToast('There was a problem with removing this video')
+ console.error(e)
+ }
+ },
+
...mapActions([
'updateSubscriptionDetails',
'updatePlaylist',
+ 'removeVideo',
]),
...mapMutations([
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index a04a01b5fbfd1..62c7686f3a271 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -35,7 +35,7 @@
>
Date: Wed, 24 May 2023 11:22:10 +0800
Subject: [PATCH 054/236] * Remove extra attributes assignment to video object
except `timeAdded`
Unintended change
---
.../ft-create-playlist-prompt/ft-create-playlist-prompt.js | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index 61bb170e80af3..be361558e9e12 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -65,12 +65,7 @@ export default Vue.extend({
if (vobj.timeAdded == null) {
vobj.timeAdded = new Date().getTime()
}
- return Object.assign(vobj, {
- published: '',
- isLive: false,
- paid: false,
- type: 'video',
- })
+ return vobj
})
const playlistObject = {
playlistName: this.playlistName,
From b5bbb91e01a413ecfcd6dcc337a919eda5741df6 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 24 May 2023 14:59:39 +0800
Subject: [PATCH 055/236] * Update copy playlist button to like adding multiple
videos to playlists
---
.../components/ft-list-video/ft-list-video.js | 6 +-
.../ft-playlist-add-video-prompt.js | 56 +++++++++----------
.../ft-playlist-add-video-prompt.vue | 8 +--
.../components/playlist-info/playlist-info.js | 9 +--
.../playlist-info/playlist-info.vue | 4 +-
.../watch-video-info/watch-video-info.js | 4 +-
src/renderer/store/modules/utils.js | 14 ++---
7 files changed, 47 insertions(+), 54 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 c4e7947de848c..8818ff5664b02 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -549,10 +549,10 @@ export default defineComponent({
timeAdded: new Date().getTime(),
isLive: false,
paid: false,
- type: 'video'
+ type: 'video',
}
- this.showAddToPlaylistPrompt(videoData)
+ this.showAddToPlaylistPromptForManyVideos([videoData])
},
...mapActions([
@@ -560,7 +560,7 @@ export default defineComponent({
'updateHistory',
'removeFromHistory',
'addVideo',
- 'showAddToPlaylistPrompt',
+ 'showAddToPlaylistPromptForManyVideos',
])
}
})
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index f9f2274f1a5f5..e841d4ebfb75a 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -21,11 +21,7 @@ export default Vue.extend({
},
data: function () {
return {
- playlistAddVideoPromptValues: [
- 'save',
- 'cancel'
- ],
- selectedPlaylistIdSet: new Set(),
+ selectedPlaylistIdList: [],
query: '',
updateQueryDebounce: function() {},
}
@@ -57,20 +53,17 @@ export default Vue.extend({
return a.title.localeCompare(b.title, this.locale)
})
},
- selectedPlaylistIdSetCount: function () {
- return this.selectedPlaylistIdSet.size
+ selectedPlaylistCount: function () {
+ return this.selectedPlaylistIdList.length
+ },
+ toBeAddedToPlaylistVideoCount: function () {
+ return this.toBeAddedToPlaylistVideoList.length
},
showAddToPlaylistPrompt: function () {
return this.$store.getters.getShowAddToPlaylistPrompt
},
- playlistAddVideoObject: function () {
- return this.$store.getters.getPlaylistAddVideoObject
- },
- playlistAddVideoPromptNames: function () {
- return [
- 'Save',
- 'Cancel'
- ]
+ toBeAddedToPlaylistVideoList: function () {
+ return this.$store.getters.getToBeAddedToPlaylistVideoList
},
processedQuery: function() {
@@ -95,35 +88,38 @@ export default Vue.extend({
this.updateQueryDebounce = debounce(this.updateQuery, 500)
},
methods: {
- handleAddToPlaylistPrompt: function (option) {
+ hide: function () {
this.hideAddToPlaylistPrompt()
},
countSelected: function (playlistId) {
- if (this.selectedPlaylistIdSet.has(playlistId)) {
- this.selectedPlaylistIdSet.delete(playlistId)
+ const index = this.selectedPlaylistIdList.indexOf(playlistId)
+ if (index !== -1) {
+ this.selectedPlaylistIdList.splice(index, 1)
} else {
- this.selectedPlaylistIdSet.add(playlistId)
+ this.selectedPlaylistIdList.push(playlistId)
}
},
addSelectedToPlaylists: function () {
- let addedPlaylists = 0
- const videoId = this.playlistAddVideoObject.videoId
- this.selectedPlaylistIdSet.forEach((selectedPlaylistId) => {
+ const addedPlaylistIds = new Set()
+
+ this.selectedPlaylistIdList.forEach((selectedPlaylistId) => {
const playlist = this.allPlaylists.find((list) => list._id === selectedPlaylistId)
if (playlist == null) { return }
- const payload = {
- _id: playlist._id,
- videoData: this.playlistAddVideoObject,
- }
- this.addVideo(payload)
- addedPlaylists++
+ this.toBeAddedToPlaylistVideoList.forEach((videoObject) => {
+ const payload = {
+ _id: playlist._id,
+ videoData: videoObject,
+ }
+ this.addVideo(payload)
+ addedPlaylistIds.add(playlist._id)
+ })
})
- showToast(`Video has been added to ${addedPlaylists} playlist(s).`)
- this.handleAddToPlaylistPrompt(null)
+ showToast(`${this.toBeAddedToPlaylistVideoCount} video(s) added to ${addedPlaylistIds.size} playlist(s).`)
+ this.hide()
},
createNewPlaylist: function () {
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 35f2377378867..1452305db7df6 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -1,12 +1,12 @@
- Select a Playlist to add your video(s) to
+ Select a Playlist to add your {{ toBeAddedToPlaylistVideoCount }} video(s) to
- {{ selectedPlaylistIdSetCount }} Selected
+ {{ selectedPlaylistCount }} Selected
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index edddc4d4ff579..d583ffda26ffe 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -163,11 +163,8 @@ export default defineComponent({
this.newDescription = this.description
},
methods: {
- copyPlaylist: function () {
- this.showCreatePlaylistPrompt({
- title: this.title,
- videos: this.videos
- })
+ toggleCopyVideosPrompt: function () {
+ this.showAddToPlaylistPromptForManyVideos(this.videos)
},
savePlaylistInfo: function () {
@@ -264,7 +261,7 @@ export default defineComponent({
},
...mapActions([
- 'showCreatePlaylistPrompt',
+ 'showAddToPlaylistPromptForManyVideos',
'updatePlaylist',
'removePlaylist',
]),
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index fc59911de3146..5e0c8a5cb0c32 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -105,11 +105,11 @@
@click="enterEditMode"
/>
Date: Wed, 24 May 2023 15:40:46 +0800
Subject: [PATCH 056/236] * Update copy playlist prompt to prefill title if
create new playlist prompt shown
---
.../components/ft-list-video/ft-list-video.js | 2 +-
.../ft-playlist-add-video-prompt.js | 7 +++++--
.../components/playlist-info/playlist-info.js | 5 ++++-
.../watch-video-info/watch-video-info.js | 2 +-
src/renderer/store/modules/utils.js | 19 ++++++++++++++++++-
5 files changed, 29 insertions(+), 6 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 8818ff5664b02..5b465c20a702d 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -552,7 +552,7 @@ export default defineComponent({
type: 'video',
}
- this.showAddToPlaylistPromptForManyVideos([videoData])
+ this.showAddToPlaylistPromptForManyVideos({ videos: [videoData] })
},
...mapActions([
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index e841d4ebfb75a..408a64051c281 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -65,6 +65,9 @@ export default Vue.extend({
toBeAddedToPlaylistVideoList: function () {
return this.$store.getters.getToBeAddedToPlaylistVideoList
},
+ newPlaylistDefaultProperties: function () {
+ return this.$store.getters.getNewPlaylistDefaultProperties
+ },
processedQuery: function() {
return this.query.trim().toLowerCase()
@@ -124,8 +127,8 @@ export default Vue.extend({
createNewPlaylist: function () {
this.showCreatePlaylistPrompt({
- title: '',
- videos: []
+ title: this.newPlaylistDefaultProperties.title || '',
+ videos: [],
})
},
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index d583ffda26ffe..5aa8fddba67d5 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -164,7 +164,10 @@ export default defineComponent({
},
methods: {
toggleCopyVideosPrompt: function () {
- this.showAddToPlaylistPromptForManyVideos(this.videos)
+ this.showAddToPlaylistPromptForManyVideos({
+ videos: this.videos,
+ newPlaylistDefaultProperties: { title: this.title },
+ })
},
savePlaylistInfo: function () {
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index 1895d123ff8a2..399bf832c4b98 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -315,7 +315,7 @@ export default defineComponent({
type: 'video',
}
- this.showAddToPlaylistPromptForManyVideos([videoData])
+ this.showAddToPlaylistPromptForManyVideos({ videos: [videoData] })
},
...mapActions([
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index 8f7161bc7c51c..ddb79500945cb 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -32,6 +32,7 @@ const state = {
showCreatePlaylistPrompt: false,
progressBarPercentage: 0,
toBeAddedToPlaylistVideoList: [],
+ newPlaylistDefaultProperties: {},
newPlaylistVideoObject: [],
regionNames: [],
regionValues: [],
@@ -89,6 +90,10 @@ const getters = {
return state.toBeAddedToPlaylistVideoList
},
+ getNewPlaylistDefaultProperties () {
+ return state.newPlaylistDefaultProperties
+ },
+
getNewPlaylistVideoObject () {
return state.newPlaylistVideoObject
},
@@ -256,13 +261,18 @@ const actions = {
})
},
- showAddToPlaylistPromptForManyVideos ({ commit }, videoObjectArray) {
+ showAddToPlaylistPromptForManyVideos ({ commit }, { videos: videoObjectArray, newPlaylistDefaultProperties }) {
commit('setShowAddToPlaylistPrompt', true)
commit('setToBeAddedToPlaylistVideoList', videoObjectArray)
+ if (newPlaylistDefaultProperties != null) {
+ commit('setNewPlaylistDefaultProperties', newPlaylistDefaultProperties)
+ }
},
hideAddToPlaylistPrompt ({ commit }) {
commit('setShowAddToPlaylistPrompt', false)
+ // The default value properties are only valid until prompt is closed
+ commit('resetNewPlaylistDefaultProperties')
},
showCreatePlaylistPrompt ({ commit }, videoArray) {
@@ -683,6 +693,13 @@ const mutations = {
state.toBeAddedToPlaylistVideoList = payload
},
+ setNewPlaylistDefaultProperties (state, payload) {
+ state.newPlaylistDefaultProperties = payload
+ },
+ resetNewPlaylistDefaultProperties (state) {
+ state.newPlaylistDefaultProperties = {}
+ },
+
setNewPlaylistVideoObject (state, payload) {
state.newPlaylistVideoObject = payload
},
From 5ecee0c06c1eb5d438019914caee0b244483a708 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 25 May 2023 09:50:13 +0800
Subject: [PATCH 057/236] * Ensure all playlists have `playlistName`
---
src/renderer/store/modules/playlists.js | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index d18df960d1c72..34dec83db9541 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -4,6 +4,10 @@ function generateRandomPlaylistId() {
return `${Date.now()}-${Math.floor(Math.random() * 10000)}`
}
+function generateRandomPlaylistName() {
+ return `Playlist ${new Date().toISOString()}-${Math.floor(Math.random() * 10000)}`
+}
+
const state = {
// Playlist loading takes time on app load (new windows)
// This is necessary to let components to know when to start data loading
@@ -107,14 +111,18 @@ const actions = {
payload.forEach((playlist) => {
let anythingUpdated = false
// Assign generated playlist ID in case DB data corrupted
- // Especially during dev
if (playlist._id == null) {
// {Time now in unix time}-{0-9999}
playlist._id = generateRandomPlaylistId()
anythingUpdated = true
}
+ // Ensure all videos has `playlistName` property
+ if (playlist.playlistName == null) {
+ // Time now in unix time, in ms
+ playlist.playlistName = generateRandomPlaylistName()
+ anythingUpdated = true
+ }
// Assign current time as last updated time in case DB data corrupted
- // Especially during dev
if (playlist.lastUpdatedAt == null) {
// Time now in unix time, in ms
playlist.lastUpdatedAt = Date.now()
@@ -129,6 +137,7 @@ const actions = {
})
// Save updated playlist object
if (anythingUpdated) {
+ DBPlaylistHandlers.upsert(playlist)
commit('upsertPlaylistToList', playlist)
}
})
From dc104a09e9402e8e120cc89db3fb159c69c317b1 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 25 May 2023 09:56:42 +0800
Subject: [PATCH 058/236] $- Remove unused playlist property `removeOnWatched`
---
src/renderer/components/data-settings/data-settings.js | 1 -
.../ft-create-playlist-prompt/ft-create-playlist-prompt.js | 1 -
src/renderer/components/playlist-info/playlist-info.js | 2 --
src/renderer/store/modules/playlists.js | 2 --
src/renderer/views/Playlist/Playlist.js | 2 --
5 files changed, 8 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index 445153265aaf0..86b61ecb3c28b 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -880,7 +880,6 @@ export default defineComponent({
const optionalKeys = [
'_id',
'protected',
- 'removeOnWatched'
]
const requiredVideoKeys = [
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index be361558e9e12..8b1f186fc2768 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -70,7 +70,6 @@ export default Vue.extend({
const playlistObject = {
playlistName: this.playlistName,
protected: false,
- removeOnWatched: false,
description: '',
videos: videosObject,
}
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 5aa8fddba67d5..20c67d1290a51 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -179,7 +179,6 @@ export default defineComponent({
const playlist = {
playlistName: this.newTitle,
protected: this.selectedUserPlaylist.protected,
- removeOnWatched: this.selectedUserPlaylist.removeOnWatched,
description: this.newDescription,
videos: this.selectedUserPlaylist.videos,
_id: this.id,
@@ -230,7 +229,6 @@ export default defineComponent({
const playlist = {
playlistName: this.title,
protected: this.selectedUserPlaylist.protected,
- removeOnWatched: this.selectedUserPlaylist.removeOnWatched,
description: this.description,
videos: videosToWatch,
_id: this.id
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 34dec83db9541..382d8f4e41687 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -18,7 +18,6 @@ const state = {
{
playlistName: 'Favorites',
protected: true,
- removeOnWatched: false,
description: 'Your favorite videos',
videos: [],
_id: 'favorites',
@@ -26,7 +25,6 @@ const state = {
{
playlistName: 'Watch Later',
protected: true,
- removeOnWatched: true,
description: 'Videos to watch later',
videos: [],
_id: 'watchLater',
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 5e4311c263cf6..b9ccf47765e90 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -314,7 +314,6 @@ export default defineComponent({
const playlist = {
playlistName: this.playlistTitle,
protected: this.selectedUserPlaylist.protected,
- removeOnWatched: this.selectedUserPlaylist.removeOnWatched,
description: this.playlistDescription,
videos: playlistItems,
_id: this.playlistId
@@ -347,7 +346,6 @@ export default defineComponent({
const playlist = {
playlistName: this.playlistTitle,
protected: this.selectedUserPlaylist.protected,
- removeOnWatched: this.selectedUserPlaylist.removeOnWatched,
description: this.playlistDescription,
videos: playlistItems,
_id: this.playlistId
From ac366cea24f4b16b7862dba0f30cf0842240cb6a Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 25 May 2023 10:05:34 +0800
Subject: [PATCH 059/236] * Update read all playlist code to ensure existing
"default" playlist properties (_id, protected) have same values as those in
default
Also fix issue discovered during testing
---
src/renderer/store/modules/playlists.js | 40 +++++++++++++++----------
1 file changed, 24 insertions(+), 16 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 382d8f4e41687..2a63b6dc09f84 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -147,35 +147,43 @@ const actions = {
return playlist.playlistName === 'Watch Later' || playlist._id === 'watchLater'
})
+ const defaultFavoritesPlaylist = state.defaultPlaylists.find((e) => e._id === 'favorites')
if (findFavorites.length === 0) {
- const favoritesPlaylist = state.defaultPlaylists.find((e) => e._id === 'favorites')
- dispatch('addPlaylist', favoritesPlaylist)
- payload.push(favoritesPlaylist)
+ dispatch('addPlaylist', defaultFavoritesPlaylist)
} else {
const favoritesPlaylist = findFavorites[0]
- if (favoritesPlaylist._id !== 'favorites' || !favoritesPlaylist.protected) {
+ if (favoritesPlaylist._id !== defaultFavoritesPlaylist._id || favoritesPlaylist.protected !== defaultFavoritesPlaylist.protected) {
const oldId = favoritesPlaylist._id
- favoritesPlaylist._id = 'favorites'
- favoritesPlaylist.protected = true
- dispatch('removePlaylist', oldId)
- dispatch('addPlaylist', favoritesPlaylist)
+ favoritesPlaylist._id = defaultFavoritesPlaylist._id
+ favoritesPlaylist.protected = defaultFavoritesPlaylist.protected
+ if (oldId === defaultFavoritesPlaylist._id) {
+ // Update playlist if ID already the same
+ DBPlaylistHandlers.upsert(favoritesPlaylist)
+ } else {
+ dispatch('removePlaylist', oldId)
+ dispatch('addPlaylist', favoritesPlaylist)
+ }
}
}
+ const defaultWatchLaterPlaylist = state.defaultPlaylists.find((e) => e._id === 'watchLater')
if (findWatchLater.length === 0) {
- const watchLaterPlaylist = state.defaultPlaylists.find((e) => e._id === 'watchLater')
- dispatch('addPlaylist', watchLaterPlaylist)
- payload.push(watchLaterPlaylist)
+ dispatch('addPlaylist', defaultWatchLaterPlaylist)
} else {
const watchLaterPlaylist = findWatchLater[0]
- if (watchLaterPlaylist._id !== 'watchLater') {
+ if (watchLaterPlaylist._id !== defaultWatchLaterPlaylist._id || watchLaterPlaylist.protected !== defaultWatchLaterPlaylist.protected) {
const oldId = watchLaterPlaylist._id
- watchLaterPlaylist._id = 'watchLater'
- watchLaterPlaylist.protected = true
- dispatch('removePlaylist', oldId)
- dispatch('addPlaylist', watchLaterPlaylist)
+ watchLaterPlaylist._id = defaultWatchLaterPlaylist._id
+ watchLaterPlaylist.protected = defaultWatchLaterPlaylist.protected
+ if (oldId === defaultWatchLaterPlaylist._id) {
+ // Update playlist if ID already the same
+ DBPlaylistHandlers.upsert(watchLaterPlaylist)
+ } else {
+ dispatch('removePlaylist', oldId)
+ dispatch('addPlaylist', watchLaterPlaylist)
+ }
}
}
From 8bdc069e9c3a04dccaadf175a58fa9548709c091 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 25 May 2023 10:27:20 +0800
Subject: [PATCH 060/236] *- Remove unnecessary code line
---
src/renderer/store/modules/playlists.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 2a63b6dc09f84..a0addf27b8b04 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -136,7 +136,6 @@ const actions = {
// Save updated playlist object
if (anythingUpdated) {
DBPlaylistHandlers.upsert(playlist)
- commit('upsertPlaylistToList', playlist)
}
})
From 6faae5798ee026dd1d69d6010e433f4960eb446d Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 25 May 2023 10:27:48 +0800
Subject: [PATCH 061/236] * Update playlists from default playlists to be
deletable
---
src/renderer/store/modules/playlists.js | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index a0addf27b8b04..642ac29f59b95 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -17,18 +17,18 @@ const state = {
defaultPlaylists: [
{
playlistName: 'Favorites',
- protected: true,
+ protected: false,
description: 'Your favorite videos',
videos: [],
_id: 'favorites',
},
{
playlistName: 'Watch Later',
- protected: true,
+ protected: false,
description: 'Videos to watch later',
videos: [],
_id: 'watchLater',
- }
+ },
],
}
@@ -147,9 +147,8 @@ const actions = {
})
const defaultFavoritesPlaylist = state.defaultPlaylists.find((e) => e._id === 'favorites')
- if (findFavorites.length === 0) {
- dispatch('addPlaylist', defaultFavoritesPlaylist)
- } else {
+ if (findFavorites.length > 0) {
+ // Update existing matching playlist only if it exists
const favoritesPlaylist = findFavorites[0]
if (favoritesPlaylist._id !== defaultFavoritesPlaylist._id || favoritesPlaylist.protected !== defaultFavoritesPlaylist.protected) {
@@ -167,9 +166,8 @@ const actions = {
}
const defaultWatchLaterPlaylist = state.defaultPlaylists.find((e) => e._id === 'watchLater')
- if (findWatchLater.length === 0) {
- dispatch('addPlaylist', defaultWatchLaterPlaylist)
- } else {
+ if (findWatchLater.length > 0) {
+ // Update existing matching playlist only if it exists
const watchLaterPlaylist = findWatchLater[0]
if (watchLaterPlaylist._id !== defaultWatchLaterPlaylist._id || watchLaterPlaylist.protected !== defaultWatchLaterPlaylist.protected) {
From c3a18d7d30401d013b63b351af918db659db2157 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 25 May 2023 10:39:16 +0800
Subject: [PATCH 062/236] ! Fix duplicate `timeAdded` value for videos copied
from user playlist
---
.../ft-playlist-add-video-prompt.js | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 408a64051c281..6d2d0cdc4dc9e 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -114,7 +114,11 @@ export default Vue.extend({
this.toBeAddedToPlaylistVideoList.forEach((videoObject) => {
const payload = {
_id: playlist._id,
- videoData: videoObject,
+ // Avoid `do not mutate vuex store state outside mutation handlers`
+ videoData: Object.assign({}, videoObject, {
+ // Part of unique ID for duplicate videos
+ timeAdded: new Date().getTime(),
+ }),
}
this.addVideo(payload)
addedPlaylistIds.add(playlist._id)
From d407fe80caa0437f873332d2557ad910d3032ab4 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 25 May 2023 10:54:59 +0800
Subject: [PATCH 063/236] ! Fix playlist import (tested with db file exported
from this branch)
---
.../components/data-settings/data-settings.js | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index 86b61ecb3c28b..2d3cf18eede99 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -874,12 +874,13 @@ export default defineComponent({
const requiredKeys = [
'playlistName',
- 'videos'
+ 'videos',
]
const optionalKeys = [
'_id',
'protected',
+ 'description',
]
const requiredVideoKeys = [
@@ -895,7 +896,7 @@ export default defineComponent({
'type'
]
- playlists.forEach(async (playlistData) => {
+ playlists.forEach((playlistData) => {
// We would technically already be done by the time the data is parsed,
// however we want to limit the possibility of malicious data being sent
// to the app, so we'll only grab the data we need here.
@@ -909,9 +910,10 @@ export default defineComponent({
} else if (key === 'videos') {
const videoArray = []
playlistData.videos.forEach((video) => {
+ const videoPropertyKeys = Object.keys(video)
let hasAllKeys = true
requiredVideoKeys.forEach((videoKey) => {
- if (!Object.keys(video).includes(videoKey)) {
+ if (!videoPropertyKeys.includes(videoKey)) {
hasAllKeys = false
}
})
@@ -944,8 +946,9 @@ export default defineComponent({
})
if (!videoExists) {
+ video.timeAdded = new Date().getTime()
const payload = {
- playlistName: existingPlaylist.playlistName,
+ _id: existingPlaylist._id,
videoData: video,
}
From a4037f60e221c935a89ffcca576f424491074a16 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 26 May 2023 10:58:24 +0800
Subject: [PATCH 064/236] * Update grid view to only display playlist title up
to 255 chars
Still can see full title in single playlist view
---
.../components/ft-list-playlist/ft-list-playlist.js | 9 ++++++++-
.../components/ft-list-playlist/ft-list-playlist.vue | 2 +-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.js b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
index 64c857739f17b..39962a4638fa3 100644
--- a/src/renderer/components/ft-list-playlist/ft-list-playlist.js
+++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
@@ -42,7 +42,14 @@ export default defineComponent({
defaultPlayback: function () {
return this.$store.getters.getDefaultPlayback
- }
+ },
+
+ titleForDisplay: function () {
+ if (typeof this.title !== 'string') { return '' }
+ if (this.title.length <= 255) { return this.title }
+
+ return `${this.title.substring(0, 255)}...`
+ },
},
created: function () {
if (this.data._id != null) {
diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.vue b/src/renderer/components/ft-list-playlist/ft-list-playlist.vue
index 18906c84a7d51..00767445a5b78 100644
--- a/src/renderer/components/ft-list-playlist/ft-list-playlist.vue
+++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.vue
@@ -32,7 +32,7 @@
class="title"
:to="`/playlist/${playlistId}`"
>
- {{ title }}
+ {{ titleForDisplay }}
Date: Fri, 26 May 2023 11:02:32 +0800
Subject: [PATCH 065/236] * Update add video to playlist prompt to only display
playlist title up to 255 chars
---
.../ft-playlist-selector/ft-playlist-selector.js | 9 ++++++++-
.../ft-playlist-selector/ft-playlist-selector.vue | 2 +-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
index 1b7134c9a3da1..ba206d9c5ce90 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
@@ -33,7 +33,14 @@ export default Vue.extend({
computed: {
currentInvidiousInstance: function () {
return this.$store.getters.getCurrentInvidiousInstance
- }
+ },
+
+ titleForDisplay: function () {
+ if (typeof this.title !== 'string') { return '' }
+ if (this.title.length <= 255) { return this.title }
+
+ return `${this.title.substring(0, 255)}...`
+ },
},
mounted: function () {
this.parseUserData()
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue
index c051cac1a0b2c..f9129085a9062 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue
@@ -33,7 +33,7 @@
- {{ title }}
+ {{ titleForDisplay }}
From f9242611d58740cca9322a274e5429eca27060f9 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 26 May 2023 11:27:27 +0800
Subject: [PATCH 066/236] * Update text of new playlist button to be same as
new profile button
---
src/renderer/views/UserPlaylists/UserPlaylists.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index df97bd5ee4bf9..d4b701f8f3dcf 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -13,7 +13,7 @@
{{ $t("User Playlists.Your Playlists") }}
Date: Fri, 26 May 2023 11:49:05 +0800
Subject: [PATCH 067/236] * Ignore many extra keys from playlist objectrs
Also make data import check for object keys against required keys not key counts
---
.../components/data-settings/data-settings.js | 31 ++++++++++++++-----
1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index 2d3cf18eede99..d96806c4b41c8 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -883,6 +883,20 @@ export default defineComponent({
'description',
]
+ const ignoredKeys = [
+ 'title',
+ 'type',
+ 'protected',
+ 'lastUpdatedAt',
+ 'removeOnWatched',
+
+ 'thumbnail',
+ 'channelName',
+ 'channelId',
+ 'playlistId',
+ 'videoCount',
+ ]
+
const requiredVideoKeys = [
'videoId',
'title',
@@ -893,7 +907,7 @@ export default defineComponent({
'timeAdded',
'isLive',
'paid',
- 'type'
+ 'type',
]
playlists.forEach((playlistData) => {
@@ -904,7 +918,7 @@ export default defineComponent({
const playlistObject = {}
Object.keys(playlistData).forEach((key) => {
- if (!requiredKeys.includes(key) && !optionalKeys.includes(key)) {
+ if ([requiredKeys, optionalKeys, ignoredKeys].every((ks) => !ks.includes(key))) {
const message = `${this.$t('Settings.Data Settings.Unknown data key')}: ${key}`
showToast(message)
} else if (key === 'videos') {
@@ -924,17 +938,17 @@ export default defineComponent({
})
playlistObject[key] = videoArray
+ } else if (ignoredKeys.includes(key)) {
+ // Do nothing for keys to be ignored
} else {
playlistObject[key] = playlistData[key]
}
})
- const objectKeys = Object.keys(playlistObject)
+ const playlistObjectKeys = Object.keys(playlistObject)
+ const playlistObjectHasAllRequiredKeys = requiredKeys.every((k) => playlistObjectKeys.includes(k))
- if ((objectKeys.length < requiredKeys.length) || playlistObject.videos.length === 0) {
- const message = this.$t('Settings.Data Settings.Playlist insufficient data', { playlist: playlistData.playlistName })
- showToast(message)
- } else {
+ if (playlistObjectHasAllRequiredKeys) {
const existingPlaylist = this.allPlaylists.find((playlist) => {
return playlist.playlistName === playlistObject.playlistName
})
@@ -958,6 +972,9 @@ export default defineComponent({
} else {
this.addPlaylist(playlistObject)
}
+ } else {
+ const message = this.$t('Settings.Data Settings.Playlist insufficient data', { playlist: playlistData.playlistName })
+ showToast(message)
}
})
From 9992fd0a8f086dbf1418ad0588033f3d6fc6eddb Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 26 May 2023 15:12:53 +0800
Subject: [PATCH 068/236] * Disallow playlist import from changing internal
playlist ID of existing playlists
Existing playlists are matched by playlist name, not by internal playlist ID
---
src/renderer/components/data-settings/data-settings.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index d96806c4b41c8..b25c16a107fcd 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -878,12 +878,12 @@ export default defineComponent({
]
const optionalKeys = [
- '_id',
'protected',
'description',
]
const ignoredKeys = [
+ '_id',
'title',
'type',
'protected',
From 90de8a88fd8cb6a8a6dc544550f119f428bacff9 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 26 May 2023 15:19:24 +0800
Subject: [PATCH 069/236] * Ensure playlist name & description trimmed when
saved
---
src/renderer/store/modules/playlists.js | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 642ac29f59b95..d93cdbe2bbb11 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -49,6 +49,14 @@ const actions = {
// {Time now in unix time}-{0-9999}
payload._id = generateRandomPlaylistId()
}
+ // Ensure playlist name trimmed
+ if (typeof payload.playlistName === 'string') {
+ payload.playlistName = payload.playlistName.trim()
+ }
+ // Ensure playlist description trimmed
+ if (typeof payload.description === 'string') {
+ payload.description = payload.description.trim()
+ }
payload.lastUpdatedAt = Date.now()
try {
@@ -69,6 +77,14 @@ const actions = {
},
async updatePlaylist({ commit }, playlist) {
+ // Ensure playlist name trimmed
+ if (typeof playlist.playlistName === 'string') {
+ playlist.playlistName = playlist.playlistName.trim()
+ }
+ // Ensure playlist description trimmed
+ if (typeof playlist.description === 'string') {
+ playlist.description = playlist.description.trim()
+ }
// Caller no need to assign last updated time
playlist.lastUpdatedAt = Date.now()
From 752f3fa51ed97aab02888bf7e32227febf359840 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 26 May 2023 15:21:29 +0800
Subject: [PATCH 070/236] * Add missing change for importing playlist to ignore
`protected`
---
src/renderer/components/data-settings/data-settings.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index b25c16a107fcd..a24f20a3adea5 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -878,7 +878,6 @@ export default defineComponent({
]
const optionalKeys = [
- 'protected',
'description',
]
From 11519c29bd58a841df187cc9832c557e926d0186 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 26 May 2023 15:26:55 +0800
Subject: [PATCH 071/236] $ Refactor code for "video object has all require
keys"
---
src/renderer/components/data-settings/data-settings.js | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index a24f20a3adea5..7cca3dc28bd08 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -924,14 +924,9 @@ export default defineComponent({
const videoArray = []
playlistData.videos.forEach((video) => {
const videoPropertyKeys = Object.keys(video)
- let hasAllKeys = true
- requiredVideoKeys.forEach((videoKey) => {
- if (!videoPropertyKeys.includes(videoKey)) {
- hasAllKeys = false
- }
- })
+ const videoObjectHasAllRequiredKeys = requiredVideoKeys.every((k) => videoPropertyKeys.includes(k))
- if (hasAllKeys) {
+ if (videoObjectHasAllRequiredKeys) {
videoArray.push(video)
}
})
From 39f5604ddcc855d79fe177182280e6b8254733b4 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 27 May 2023 10:54:32 +0800
Subject: [PATCH 072/236] ! Fix style of prompt from any button within
playlist-info component again
z-index war
---
src/renderer/views/Playlist/Playlist.css | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/renderer/views/Playlist/Playlist.css b/src/renderer/views/Playlist/Playlist.css
index a6456a9262c76..2a5b9a6fcab75 100644
--- a/src/renderer/views/Playlist/Playlist.css
+++ b/src/renderer/views/Playlist/Playlist.css
@@ -12,7 +12,8 @@
position: sticky;
top: 96px;
/* This is needed to make prompt always above video entries */
- z-index: 1;
+ /* High value used to avoid further issues */
+ z-index: 100;
width: 30%;
}
From 53201f47e7437b1adc972b8ae67a6680bef39856 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 27 May 2023 11:16:31 +0800
Subject: [PATCH 073/236] * Update some empty message & button text
---
src/renderer/components/playlist-info/playlist-info.vue | 2 +-
src/renderer/views/UserPlaylists/UserPlaylists.vue | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 5e0c8a5cb0c32..73060ba70cb21 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -99,7 +99,7 @@
- {{ $t("User Playlists['Your saved videos are empty. Click on the save button on the corner of a video to have it listed here']") }}
+ You have no playlist. Click on the create new playlist button to create a new one
Date: Sat, 27 May 2023 11:26:01 +0800
Subject: [PATCH 074/236] * Ensure playlist item action buttons are hidden
during animations
---
.../views/Playlist/{Playlist.css => Playlist.scss} | 10 ++++++++++
src/renderer/views/Playlist/Playlist.vue | 2 +-
2 files changed, 11 insertions(+), 1 deletion(-)
rename src/renderer/views/Playlist/{Playlist.css => Playlist.scss} (83%)
diff --git a/src/renderer/views/Playlist/Playlist.css b/src/renderer/views/Playlist/Playlist.scss
similarity index 83%
rename from src/renderer/views/Playlist/Playlist.css
rename to src/renderer/views/Playlist/Playlist.scss
index 2a5b9a6fcab75..9721b7e6ad67b 100644
--- a/src/renderer/views/Playlist/Playlist.css
+++ b/src/renderer/views/Playlist/Playlist.scss
@@ -37,6 +37,16 @@
.playlistItem-enter-active,
.playlistItem-leave-active {
transition: all 0.2s ease;
+
+ // Hide action buttons during transitions
+ //
+ // The class for icon container is mainly styled in `_ft-list-item.scss`
+ // But the transition related classes are all on container elements
+ // So `:deep` is used
+ :deep(.playlistIcons) {
+ //display: none;
+ background-color: red;
+ }
}
.playlistItem-enter, .playlistItem-leave-to {
opacity: 0;
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index 62c7686f3a271..724a11622c96a 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -87,4 +87,4 @@
-
+
From 2274dfe34a3286558d5aec91dfae17778aab996e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 27 May 2023 11:33:46 +0800
Subject: [PATCH 075/236] ! Fix other prompt z-index
---
src/renderer/components/ft-prompt/ft-prompt.css | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/renderer/components/ft-prompt/ft-prompt.css b/src/renderer/components/ft-prompt/ft-prompt.css
index dbd2f3b37d9d4..0c2cd194cb42a 100644
--- a/src/renderer/components/ft-prompt/ft-prompt.css
+++ b/src/renderer/components/ft-prompt/ft-prompt.css
@@ -5,7 +5,8 @@
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.7);
- z-index: 10;
+ /* Higher than components like playlist info */
+ z-index: 200;
padding: 15px;
box-sizing: border-box;
display: flex;
From d0bb383eafcf71bab4c0cd25e147f9194e19bcd2 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 27 May 2023 15:06:40 +0800
Subject: [PATCH 076/236] * Update `showAddToPlaylistPromptForManyVideos` to
throw error when required keys missing from passed in video data
---
src/renderer/store/modules/utils.js | 44 +++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index ddb79500945cb..1e075571524fd 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -262,6 +262,50 @@ const actions = {
},
showAddToPlaylistPromptForManyVideos ({ commit }, { videos: videoObjectArray, newPlaylistDefaultProperties }) {
+ let videoDataValid = true
+ if (!Array.isArray(videoObjectArray)) {
+ videoDataValid = false
+ }
+ let missingKeys = []
+
+ if (videoDataValid) {
+ const requiredVideoKeys = [
+ 'videoId',
+ 'title',
+ 'author',
+ 'authorId',
+ 'published',
+ 'lengthSeconds',
+ 'timeAdded',
+ 'isLive',
+ 'paid',
+ 'type',
+ ]
+ // Using `every` to loop and `return false` to break
+ videoObjectArray.every((video) => {
+ const videoPropertyKeys = Object.keys(video)
+ const missingKeysHere = requiredVideoKeys.filter(x => !videoPropertyKeys.includes(x))
+ if (missingKeysHere.length > 0) {
+ videoDataValid = false
+ missingKeys = missingKeysHere
+ return false
+ }
+ // Return true to continue loop
+ return true
+ })
+ }
+
+ if (!videoDataValid) {
+ // Print error and abort
+ const errorMsgText = 'Incorrect videos data passed when opening playlist prompt'
+ console.error(errorMsgText)
+ console.error({
+ videoObjectArray,
+ missingKeys,
+ })
+ throw new Error(errorMsgText)
+ }
+
commit('setShowAddToPlaylistPrompt', true)
commit('setToBeAddedToPlaylistVideoList', videoObjectArray)
if (newPlaylistDefaultProperties != null) {
From ce04bd11a939c7bd180c783b4465218750827d0b Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 29 May 2023 13:47:08 +0800
Subject: [PATCH 077/236] *- Remove unused video property `paid` from playlist
related code
---
src/renderer/components/data-settings/data-settings.js | 1 -
src/renderer/components/ft-list-video/ft-list-video.js | 1 -
src/renderer/components/watch-video-info/watch-video-info.js | 1 -
src/renderer/store/modules/utils.js | 1 -
src/renderer/views/Watch/Watch.js | 1 -
5 files changed, 5 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index 7cca3dc28bd08..9e2cb600940e1 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -905,7 +905,6 @@ export default defineComponent({
'lengthSeconds',
'timeAdded',
'isLive',
- 'paid',
'type',
]
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 5b465c20a702d..d21357b864949 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -548,7 +548,6 @@ export default defineComponent({
lengthSeconds: this.data.lengthSeconds,
timeAdded: new Date().getTime(),
isLive: false,
- paid: false,
type: 'video',
}
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index 399bf832c4b98..b1b2bd4096a70 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -311,7 +311,6 @@ export default defineComponent({
lengthSeconds: this.lengthSeconds,
timeAdded: new Date().getTime(),
isLive: false,
- paid: false,
type: 'video',
}
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index 1e075571524fd..d4dd574747a8c 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -278,7 +278,6 @@ const actions = {
'lengthSeconds',
'timeAdded',
'isLive',
- 'paid',
'type',
]
// Using `every` to loop and `return false` to break
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index 70481b1054855..8e04ecce8fc39 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -1001,7 +1001,6 @@ export default defineComponent({
watchProgress: watchProgress,
timeWatched: new Date().getTime(),
isLive: false,
- paid: false,
type: 'video'
}
From efc3b2c72479a4694791509ddef51a89a55d0085 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 29 May 2023 13:51:50 +0800
Subject: [PATCH 078/236] *- Remove unused video property `type` from playlist
related code
---
src/renderer/components/data-settings/data-settings.js | 1 -
src/renderer/components/ft-list-video/ft-list-video.js | 1 -
src/renderer/components/watch-video-info/watch-video-info.js | 1 -
src/renderer/store/modules/utils.js | 1 -
4 files changed, 4 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index 9e2cb600940e1..a6a7f973ebe64 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -905,7 +905,6 @@ export default defineComponent({
'lengthSeconds',
'timeAdded',
'isLive',
- 'type',
]
playlists.forEach((playlistData) => {
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 d21357b864949..5bd1b27631d23 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -548,7 +548,6 @@ export default defineComponent({
lengthSeconds: this.data.lengthSeconds,
timeAdded: new Date().getTime(),
isLive: false,
- type: 'video',
}
this.showAddToPlaylistPromptForManyVideos({ videos: [videoData] })
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index b1b2bd4096a70..f589aeaa9b071 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -311,7 +311,6 @@ export default defineComponent({
lengthSeconds: this.lengthSeconds,
timeAdded: new Date().getTime(),
isLive: false,
- type: 'video',
}
this.showAddToPlaylistPromptForManyVideos({ videos: [videoData] })
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index d4dd574747a8c..6b012587fa42f 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -278,7 +278,6 @@ const actions = {
'lengthSeconds',
'timeAdded',
'isLive',
- 'type',
]
// Using `every` to loop and `return false` to break
videoObjectArray.every((video) => {
From 7039fdad4212514f919b60468d24082c19de7f33 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 29 May 2023 14:24:10 +0800
Subject: [PATCH 079/236] ! Fix duplicate playlist displayed on playlist
conversion
---
src/renderer/store/modules/playlists.js | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index d93cdbe2bbb11..a5baf0f090353 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -176,7 +176,10 @@ const actions = {
DBPlaylistHandlers.upsert(favoritesPlaylist)
} else {
dispatch('removePlaylist', oldId)
- dispatch('addPlaylist', favoritesPlaylist)
+ // DO NOT use dispatch('addPlaylist', ...)
+ // Which causes duplicate displayed playlist in window (But DB is fine)
+ // Due to the object is already in `payload`
+ DBPlaylistHandlers.create(favoritesPlaylist)
}
}
}
@@ -195,7 +198,10 @@ const actions = {
DBPlaylistHandlers.upsert(watchLaterPlaylist)
} else {
dispatch('removePlaylist', oldId)
- dispatch('addPlaylist', watchLaterPlaylist)
+ // DO NOT use dispatch('addPlaylist', ...)
+ // Which causes duplicate displayed playlist in window (But DB is fine)
+ // Due to the object is already in `payload`
+ DBPlaylistHandlers.create(watchLaterPlaylist)
}
}
}
From bbc467c2e76ff9d0dadde4cea9700130be15125a Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 29 May 2023 14:35:52 +0800
Subject: [PATCH 080/236] *- Remove unused video property `published` from
playlist related code
---
src/renderer/components/data-settings/data-settings.js | 1 -
src/renderer/components/ft-list-video/ft-list-video.js | 1 -
src/renderer/components/watch-video-info/watch-video-info.js | 1 -
src/renderer/store/modules/utils.js | 1 -
4 files changed, 4 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index a6a7f973ebe64..e9a8d5c3a87e3 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -901,7 +901,6 @@ export default defineComponent({
'title',
'author',
'authorId',
- 'published',
'lengthSeconds',
'timeAdded',
'isLive',
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 5bd1b27631d23..1bb5ae936bfd7 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -542,7 +542,6 @@ export default defineComponent({
title: this.title,
author: this.channelName,
authorId: this.channelId,
- published: '',
description: this.description,
viewCount: this.viewCount,
lengthSeconds: this.data.lengthSeconds,
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index f589aeaa9b071..e1d6d9ab1096f 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -305,7 +305,6 @@ export default defineComponent({
title: this.title,
author: this.channelName,
authorId: this.channelId,
- published: '',
description: this.description,
viewCount: this.viewCount,
lengthSeconds: this.lengthSeconds,
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index 6b012587fa42f..da594ab73df1a 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -274,7 +274,6 @@ const actions = {
'title',
'author',
'authorId',
- 'published',
'lengthSeconds',
'timeAdded',
'isLive',
From c8187cad5d63a4ba8c765442c752676591d9b02e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 29 May 2023 14:39:53 +0800
Subject: [PATCH 081/236] * Don't require & generate property `timeAdded` when
display a prompt
---
src/renderer/components/ft-list-video/ft-list-video.js | 1 -
src/renderer/components/watch-video-info/watch-video-info.js | 1 -
src/renderer/store/modules/utils.js | 5 ++++-
3 files changed, 4 insertions(+), 3 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 1bb5ae936bfd7..ae9f4112b7542 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -545,7 +545,6 @@ export default defineComponent({
description: this.description,
viewCount: this.viewCount,
lengthSeconds: this.data.lengthSeconds,
- timeAdded: new Date().getTime(),
isLive: false,
}
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index e1d6d9ab1096f..fa82516a49541 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -308,7 +308,6 @@ export default defineComponent({
description: this.description,
viewCount: this.viewCount,
lengthSeconds: this.lengthSeconds,
- timeAdded: new Date().getTime(),
isLive: false,
}
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index da594ab73df1a..097cd0fed5a2e 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -275,8 +275,11 @@ const actions = {
'author',
'authorId',
'lengthSeconds',
- 'timeAdded',
'isLive',
+
+ // `timeAdded` should be generated when videos are added
+ // Not when a prompt is displayed
+ // 'timeAdded',
]
// Using `every` to loop and `return false` to break
videoObjectArray.every((video) => {
From 69dc1a552d09607ccc0cb3e46811b940385ea256 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 29 May 2023 14:48:56 +0800
Subject: [PATCH 082/236] *- Remove unused video property `isLive` from
playlist related code
---
src/renderer/components/data-settings/data-settings.js | 1 -
src/renderer/components/ft-list-video/ft-list-video.js | 1 -
src/renderer/components/watch-video-info/watch-video-info.js | 1 -
src/renderer/store/modules/utils.js | 1 -
4 files changed, 4 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index e9a8d5c3a87e3..d9fbb87820aca 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -903,7 +903,6 @@ export default defineComponent({
'authorId',
'lengthSeconds',
'timeAdded',
- 'isLive',
]
playlists.forEach((playlistData) => {
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 ae9f4112b7542..231b918031501 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -545,7 +545,6 @@ export default defineComponent({
description: this.description,
viewCount: this.viewCount,
lengthSeconds: this.data.lengthSeconds,
- isLive: false,
}
this.showAddToPlaylistPromptForManyVideos({ videos: [videoData] })
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index fa82516a49541..efedecebdb2f0 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -308,7 +308,6 @@ export default defineComponent({
description: this.description,
viewCount: this.viewCount,
lengthSeconds: this.lengthSeconds,
- isLive: false,
}
this.showAddToPlaylistPromptForManyVideos({ videos: [videoData] })
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index 097cd0fed5a2e..b2abd7e73af85 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -275,7 +275,6 @@ const actions = {
'author',
'authorId',
'lengthSeconds',
- 'isLive',
// `timeAdded` should be generated when videos are added
// Not when a prompt is displayed
From 329e0a751b7ef3e95cff8cc02823277633c44241 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 29 May 2023 15:54:33 +0800
Subject: [PATCH 083/236] ! Fix text
---
src/renderer/views/UserPlaylists/UserPlaylists.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index 8f45362a942d8..c451752fc3d00 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -33,7 +33,7 @@
v-show="fullData.length === 0"
>
- You have no playlist. Click on the create new playlist button to create a new one
+ You have no playlist. Click on the create new playlist button to create a new one.
Date: Mon, 29 May 2023 16:22:23 +0800
Subject: [PATCH 084/236] ! Revert code change for debugging only
---
src/renderer/views/Playlist/Playlist.scss | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.scss b/src/renderer/views/Playlist/Playlist.scss
index 9721b7e6ad67b..ab0f6e754f7fc 100644
--- a/src/renderer/views/Playlist/Playlist.scss
+++ b/src/renderer/views/Playlist/Playlist.scss
@@ -44,8 +44,7 @@
// But the transition related classes are all on container elements
// So `:deep` is used
:deep(.playlistIcons) {
- //display: none;
- background-color: red;
+ display: none;
}
}
.playlistItem-enter, .playlistItem-leave-to {
From b25de416a01fc4efa2bdb9dd3243e0b8d8eb0cd1 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 30 May 2023 08:45:27 +0800
Subject: [PATCH 085/236] ! Fix CSS for "Ensure playlist item action buttons
are hidden during animations"
---
src/renderer/views/Playlist/Playlist.scss | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/views/Playlist/Playlist.scss b/src/renderer/views/Playlist/Playlist.scss
index ab0f6e754f7fc..6c3bd467f6dd4 100644
--- a/src/renderer/views/Playlist/Playlist.scss
+++ b/src/renderer/views/Playlist/Playlist.scss
@@ -43,7 +43,7 @@
// The class for icon container is mainly styled in `_ft-list-item.scss`
// But the transition related classes are all on container elements
// So `:deep` is used
- :deep(.playlistIcons) {
+ :deep(.ft-list-item .videoThumbnail .playlistIcons) {
display: none;
}
}
From 51c1bf29aee8e5de35807c5ff871fe9b10d28ce0 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 30 May 2023 08:58:28 +0800
Subject: [PATCH 086/236] * Update add playlist button to be shown for live
videos
---
src/renderer/components/ft-list-video/ft-list-video.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 7aaa4556adb85..ede496e455dfd 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -46,7 +46,7 @@
/>
Date: Tue, 30 May 2023 09:40:44 +0800
Subject: [PATCH 087/236] + Add clear all playlists button
---
src/datastores/handlers/base.js | 2 +-
.../components/privacy-settings/privacy-settings.js | 11 ++++++++++-
.../privacy-settings/privacy-settings.vue | 13 +++++++++++++
src/renderer/store/modules/playlists.js | 2 +-
4 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js
index f9f110e3f7e7c..381770323f9f2 100644
--- a/src/datastores/handlers/base.js
+++ b/src/datastores/handlers/base.js
@@ -161,7 +161,7 @@ class Playlists {
}
static deleteAll() {
- return db.playlists.remove({ protected: { $ne: true } })
+ return db.playlists.removeMany()
}
}
diff --git a/src/renderer/components/privacy-settings/privacy-settings.js b/src/renderer/components/privacy-settings/privacy-settings.js
index 7b2a406dc4863..e52f45fd69d40 100644
--- a/src/renderer/components/privacy-settings/privacy-settings.js
+++ b/src/renderer/components/privacy-settings/privacy-settings.js
@@ -22,6 +22,7 @@ export default defineComponent({
showSearchCachePrompt: false,
showRemoveHistoryPrompt: false,
showRemoveSubscriptionsPrompt: false,
+ showRemovePlaylistsPrompt: false,
promptValues: [
'yes',
'no'
@@ -119,6 +120,13 @@ export default defineComponent({
}
},
+ handleRemovePlaylists: function (option) {
+ this.showRemovePlaylistsPrompt = false
+ if (option !== 'yes') { return }
+
+ this.removeAllPlaylists()
+ },
+
...mapActions([
'updateRememberHistory',
'updateRemoveVideoMetaFiles',
@@ -130,7 +138,8 @@ export default defineComponent({
'removeProfile',
'updateActiveProfile',
'updateAllSubscriptionsList',
- 'updateProfileSubscriptions'
+ 'updateProfileSubscriptions',
+ 'removeAllPlaylists',
])
}
})
diff --git a/src/renderer/components/privacy-settings/privacy-settings.vue b/src/renderer/components/privacy-settings/privacy-settings.vue
index e64b9203d4872..bbce30a3e8fa0 100644
--- a/src/renderer/components/privacy-settings/privacy-settings.vue
+++ b/src/renderer/components/privacy-settings/privacy-settings.vue
@@ -59,6 +59,12 @@
background-color="var(--primary-color)"
@click="showRemoveSubscriptionsPrompt = true"
/>
+
+
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index a5baf0f090353..e431b235c91f9 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -307,7 +307,7 @@ const mutations = {
},
removeAllPlaylists(state) {
- state.playlists = state.playlists.filter(playlist => playlist.protected !== true)
+ state.playlists = []
},
removeAllVideos(state, playlistId) {
From 8ff279ebf829fba403a5f359294e3361b510f30c Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 30 May 2023 09:44:41 +0800
Subject: [PATCH 088/236] * Update add video to playlist prompt to swap "save"
& "create playlist" button
---
.../ft-playlist-add-video-prompt.vue | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 1452305db7df6..eb3ea0139d6a1 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -27,14 +27,14 @@
/>
-
+
Date: Tue, 30 May 2023 09:49:25 +0800
Subject: [PATCH 089/236] ! Fix playlist view won't load after default playlist
added due to lack of playlist
---
src/renderer/store/modules/playlists.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index e431b235c91f9..1a81c5d650346 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -207,8 +207,8 @@ const actions = {
}
commit('setAllPlaylists', payload)
- commit('setPlaylistsReady', true)
}
+ commit('setPlaylistsReady', true)
} catch (errMessage) {
console.error(errMessage)
}
From 83022f0035f2b841a28600e7977fe1ea39a45062 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 30 May 2023 10:41:54 +0800
Subject: [PATCH 090/236] * Show toast message when no playlist selected after
pressing save button
---
.../ft-playlist-add-video-prompt.js | 5 +++++
src/renderer/components/ft-toast/ft-toast.css | 3 ++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 6d2d0cdc4dc9e..8962d45cd7e30 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -107,6 +107,11 @@ export default Vue.extend({
addSelectedToPlaylists: function () {
const addedPlaylistIds = new Set()
+ if (this.selectedPlaylistIdList.length === 0) {
+ showToast('You haven\'t selected any playlist yet.')
+ return
+ }
+
this.selectedPlaylistIdList.forEach((selectedPlaylistId) => {
const playlist = this.allPlaylists.find((list) => list._id === selectedPlaylistId)
if (playlist == null) { return }
diff --git a/src/renderer/components/ft-toast/ft-toast.css b/src/renderer/components/ft-toast/ft-toast.css
index c8418624c709b..b44ea7ea4c24e 100644
--- a/src/renderer/components/ft-toast/ft-toast.css
+++ b/src/renderer/components/ft-toast/ft-toast.css
@@ -3,7 +3,8 @@
left: 50vw;
transform: translate(-50%, 0);
bottom: 50px;
- z-index: 10;
+ /* Higher than any prompt */
+ z-index: 300;
display: flex;
flex-direction: column;
align-items: center;
From bbe1593b02ceb15445870775eb889ab5d58b659d Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 30 May 2023 10:47:58 +0800
Subject: [PATCH 091/236] * Update add video to playlist prompt to show latest
updated playlist first
Easier for copying playlist with new playlist(s)
---
.../ft-playlist-add-video-prompt.js | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 8962d45cd7e30..9a060c7aaf6af 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -39,14 +39,10 @@ export default Vue.extend({
playlist.videoCount = playlist.videos.length
return playlist
}).sort((a, b) => {
- // Sort by favorites, watch later, then alphabetically
- if (a._id === 'favorites') {
+ // Sort by `lastUpdatedAt`, then alphabetically
+ if (a.lastUpdatedAt > b.lastUpdatedAt) {
return -1
- } else if (b._id === 'favorites') {
- return 1
- } else if (a._id === 'watchLater') {
- return -1
- } else if (b._id === 'watchLater') {
+ } else if (b.lastUpdatedAt > a.lastUpdatedAt) {
return 1
}
From 5ccbec609f02a67606bd2e57f20eb3cb9aa195d1 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 30 May 2023 15:05:19 +0800
Subject: [PATCH 092/236] ! Fix watch page when visited via history after
viewing the video from a deleted user playlist
---
src/datastores/handlers/base.js | 4 +-
src/datastores/handlers/electron.js | 4 +-
src/datastores/handlers/web.js | 4 +-
src/main/index.js | 2 +-
.../components/ft-list-video/ft-list-video.js | 27 ++++++++-
.../ft-list-video/ft-list-video.vue | 2 +-
src/renderer/store/modules/history.js | 9 +--
src/renderer/views/Watch/Watch.js | 55 ++++++++++++++++---
8 files changed, 83 insertions(+), 24 deletions(-)
diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js
index 381770323f9f2..89300feb9d740 100644
--- a/src/datastores/handlers/base.js
+++ b/src/datastores/handlers/base.js
@@ -60,8 +60,8 @@ class History {
return db.history.update({ videoId }, { $set: { watchProgress } }, { upsert: true })
}
- static updateLastViewedPlaylist(videoId, lastViewedPlaylistId) {
- return db.history.update({ videoId }, { $set: { lastViewedPlaylistId } }, { upsert: true })
+ static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType) {
+ return db.history.update({ videoId }, { $set: { lastViewedPlaylistId, lastViewedPlaylistType } }, { upsert: true })
}
static delete(videoId) {
diff --git a/src/datastores/handlers/electron.js b/src/datastores/handlers/electron.js
index caba5752ff406..d929177569b54 100644
--- a/src/datastores/handlers/electron.js
+++ b/src/datastores/handlers/electron.js
@@ -42,12 +42,12 @@ class History {
)
}
- static updateLastViewedPlaylist(videoId, lastViewedPlaylistId) {
+ static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType) {
return ipcRenderer.invoke(
IpcChannels.DB_HISTORY,
{
action: DBActions.HISTORY.UPDATE_PLAYLIST,
- data: { videoId, lastViewedPlaylistId }
+ data: { videoId, lastViewedPlaylistId, lastViewedPlaylistType }
}
)
}
diff --git a/src/datastores/handlers/web.js b/src/datastores/handlers/web.js
index 16ccc5c5bbb44..2d51842db0bb3 100644
--- a/src/datastores/handlers/web.js
+++ b/src/datastores/handlers/web.js
@@ -33,8 +33,8 @@ class History {
return baseHandlers.history.updateWatchProgress(videoId, watchProgress)
}
- static updateLastViewedPlaylist(videoId, lastViewedPlaylistId) {
- return baseHandlers.history.updateLastViewedPlaylist(videoId, lastViewedPlaylistId)
+ static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType) {
+ return baseHandlers.history.updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType)
}
static delete(videoId) {
diff --git a/src/main/index.js b/src/main/index.js
index da1d603f9f852..219dadb0935d9 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -789,7 +789,7 @@ function runApp() {
return null
case DBActions.HISTORY.UPDATE_PLAYLIST:
- await baseHandlers.history.updateLastViewedPlaylist(data.videoId, data.lastViewedPlaylistId)
+ await baseHandlers.history.updateLastViewedPlaylist(data.videoId, data.lastViewedPlaylistId, data.lastViewedPlaylistType)
syncOtherWindows(
IpcChannels.SYNC_HISTORY,
event,
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 231b918031501..438247fdfb3ae 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -305,9 +305,12 @@ export default defineComponent({
})
},
- playlistIdFinal: function () {
+ playlistIdTypePairFinal() {
if (this.playlistId) {
- return this.playlistId
+ return {
+ playlistId: this.playlistId,
+ playlistType: null,
+ }
}
// Get playlist ID from history ONLY if option enabled
@@ -318,7 +321,25 @@ export default defineComponent({
return undefined
}
- return this.historyCache[historyIndex].lastViewedPlaylistId
+ return {
+ playlistId: this.historyCache[historyIndex].lastViewedPlaylistId,
+ playlistType: this.historyCache[historyIndex].lastViewedPlaylistType,
+ }
+ },
+
+ playlistIdFinal: function () {
+ return this.playlistIdTypePairFinal?.playlistId
+ },
+
+ playlistTypeFinal: function () {
+ return this.playlistIdTypePairFinal?.playlistType
+ },
+
+ watchPageLinkQuery() {
+ const query = {}
+ if (this.playlistIdFinal) { query.playlistId = this.playlistIdFinal }
+ if (this.playlistTypeFinal) { query.playlistType = this.playlistTypeFinal }
+ return query
},
currentLocale: function () {
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 ede496e455dfd..2d7926e8d6083 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -16,7 +16,7 @@
tabindex="-1"
:to="{
path: `/watch/${id}`,
- query: playlistIdFinal ? {playlistId: playlistIdFinal} : {}
+ query: watchPageLinkQuery,
}"
>
{
return currentRecord.videoId === videoId
})
const targetRecord = Object.assign({}, state.historyCache[i])
targetRecord.lastViewedPlaylistId = lastViewedPlaylistId
+ targetRecord.lastViewedPlaylistType = lastViewedPlaylistType
state.historyCache.splice(i, 1, targetRecord)
},
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index 8e04ecce8fc39..e33bf4d5f29b6 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -114,6 +114,7 @@ export default defineComponent({
downloadLinks: [],
watchingPlaylist: false,
playlistId: '',
+ playlistType: '',
timestamp: null,
playNextTimeout: null,
playNextCountDownIntervalId: null,
@@ -203,6 +204,13 @@ export default defineComponent({
allowDashAv1Formats: function () {
return this.$store.getters.getAllowDashAv1Formats
},
+
+ selectedUserPlaylist: function () {
+ if (this.playlistId == null) { return null }
+ if (this.playlistId === '') { return null }
+
+ return this.$store.getters.getPlaylist(this.playlistId)
+ },
},
watch: {
$route() {
@@ -1030,7 +1038,8 @@ export default defineComponent({
const payload = {
videoId: this.videoId,
// Whether there is a playlist ID or not, save it
- lastViewedPlaylistId: this.$route.query?.playlistId,
+ lastViewedPlaylistId: this.playlistId,
+ lastViewedPlaylistType: this.playlistType,
}
this.updateLastViewedPlaylist(payload)
},
@@ -1080,17 +1089,45 @@ export default defineComponent({
},
checkIfPlaylist: function () {
- if (typeof (this.$route.query) !== 'undefined') {
- this.playlistId = this.$route.query.playlistId
+ if (this.$route.query == null) {
+ this.watchingPlaylist = false
+ return
+ }
- if (typeof (this.playlistId) !== 'undefined') {
- this.watchingPlaylist = true
- } else {
- this.watchingPlaylist = false
- }
- } else {
+ this.playlistId = this.$route.query.playlistId
+
+ if (this.playlistId == null || this.playlistId.length === 0) {
+ this.playlistType = ''
this.watchingPlaylist = false
+ return
+ }
+
+ // `playlistId` present
+ if (this.selectedUserPlaylist != null) {
+ // If playlist ID matches a user playlist, it must be user playlist
+ // (Assuming FT never generates an ID same as a remote playlist)
+ this.playlistType = 'user'
+ this.watchingPlaylist = true
+ return
+ }
+
+ // Still possible to be a user playlist from history
+ // (but user playlist could be already removed)
+ this.playlistType = this.$route.query.playlistType
+ if (this.playlistType !== 'user') {
+ // Remote playlist
+ this.watchingPlaylist = true
+ return
+ }
+
+ // At this point `playlistType === 'user'`
+ // But the playlist might be already removed
+ if (this.selectedUserPlaylist == null) {
+ // Clear playlist data so that watch history will be properly updated
+ this.playlistId = ''
+ this.playlistType = ''
}
+ this.watchingPlaylist = this.selectedUserPlaylist != null
},
checkIfTimestamp: function () {
From 1e42a598f6b4e00be9132f270d8df165ca87471e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 30 May 2023 15:32:30 +0800
Subject: [PATCH 093/236] ! Fix share buttons emitting user playlist IDs
---
.../components/ft-list-video/ft-list-video.js | 21 +++++++++++++----
.../ft-share-button/ft-share-button.js | 23 ++++++++++++++-----
2 files changed, 33 insertions(+), 11 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 438247fdfb3ae..c4ebecf36e503 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -125,10 +125,23 @@ export default defineComponent({
return this.$router.currentRoute.path.includes('playlist') && this.playlistType === 'user'
},
+ selectedUserPlaylist: function () {
+ if (this.playlistIdFinal == null) { return null }
+ if (this.playlistIdFinal === '') { return null }
+
+ return this.$store.getters.getPlaylist(this.playlistIdFinal)
+ },
+
+ playlistSharable() {
+ // `playlistId` can be undefined
+ // User playlist ID should not be shared
+ return this.playlistIdFinal && this.playlistIdFinal.length !== 0 && this.selectedUserPlaylist == null
+ },
+
invidiousUrl: function () {
let videoUrl = `${this.currentInvidiousInstance}/watch?v=${this.id}`
// `playlistId` can be undefined
- if (this.playlistIdFinal && this.playlistIdFinal.length !== 0) {
+ if (this.playlistSharable) {
// `index` seems can be ignored
videoUrl += `&list=${this.playlistIdFinal}`
}
@@ -141,8 +154,7 @@ export default defineComponent({
youtubeUrl: function () {
let videoUrl = `https://www.youtube.com/watch?v=${this.id}`
- // `playlistId` can be undefined
- if (this.playlistIdFinal && this.playlistIdFinal.length !== 0) {
+ if (this.playlistSharable) {
// `index` seems can be ignored
videoUrl += `&list=${this.playlistIdFinal}`
}
@@ -150,8 +162,7 @@ export default defineComponent({
},
youtubeShareUrl: function () {
- // `playlistId` can be undefined
- if (this.playlistIdFinal && this.playlistIdFinal.length !== 0) {
+ if (this.playlistSharable) {
// `index` seems can be ignored
return `https://youtu.be/${this.id}?list=${this.playlistIdFinal}`
}
diff --git a/src/renderer/components/ft-share-button/ft-share-button.js b/src/renderer/components/ft-share-button/ft-share-button.js
index f4068b07d9db5..1ecbf7a59d0e8 100644
--- a/src/renderer/components/ft-share-button/ft-share-button.js
+++ b/src/renderer/components/ft-share-button/ft-share-button.js
@@ -62,6 +62,19 @@ export default defineComponent({
return this.$store.getters.getCurrentInvidiousInstance
},
+ selectedUserPlaylist: function () {
+ if (this.playlistId == null) { return null }
+ if (this.playlistId === '') { return null }
+
+ return this.$store.getters.getPlaylist(this.playlistId)
+ },
+
+ playlistSharable() {
+ // `playlistId` can be undefined
+ // User playlist ID should not be shared
+ return this.playlistId && this.playlistId.length !== 0 && this.selectedUserPlaylist == null
+ },
+
invidiousURL() {
if (this.isChannel) {
return `${this.currentInvidiousInstance}/channel/${this.id}`
@@ -71,7 +84,7 @@ export default defineComponent({
}
let videoUrl = `${this.currentInvidiousInstance}/watch?v=${this.id}`
// `playlistId` can be undefined
- if (this.playlistId && this.playlistId.length !== 0) {
+ if (this.playlistSharable) {
// `index` seems can be ignored
videoUrl += `&list=${this.playlistId}`
}
@@ -101,8 +114,7 @@ export default defineComponent({
return this.youtubePlaylistUrl
}
let videoUrl = `https://www.youtube.com/watch?v=${this.id}`
- // `playlistId` can be undefined
- if (this.playlistId && this.playlistId.length !== 0) {
+ if (this.playlistSharable) {
// `index` seems can be ignored
videoUrl += `&list=${this.playlistId}`
}
@@ -116,8 +128,7 @@ export default defineComponent({
if (this.isPlaylist) {
return this.youtubePlaylistUrl
}
- // `playlistId` can be undefined
- if (this.playlistId && this.playlistId.length !== 0) {
+ if (this.playlistSharable) {
// `index` seems can be ignored
return `https://www.youtube.com/watch?v=${this.id}&list=${this.playlistId}`
}
@@ -129,7 +140,7 @@ export default defineComponent({
return `https://www.youtube-nocookie.com/embed/videoseries?list=${this.id}`
}
return `https://www.youtube-nocookie.com/embed/${this.id}`
- }
+ },
},
mounted() {
// Prevents to instantiate a ft-share-button for a video without a get-timestamp function
From 9a3b302bbefd780c9f85233ec15939a0113b4d36 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 31 May 2023 08:56:11 +0800
Subject: [PATCH 094/236] * Add toast message after removing all playlists
---
src/renderer/components/privacy-settings/privacy-settings.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/renderer/components/privacy-settings/privacy-settings.js b/src/renderer/components/privacy-settings/privacy-settings.js
index e52f45fd69d40..50979dcbbdae2 100644
--- a/src/renderer/components/privacy-settings/privacy-settings.js
+++ b/src/renderer/components/privacy-settings/privacy-settings.js
@@ -125,6 +125,7 @@ export default defineComponent({
if (option !== 'yes') { return }
this.removeAllPlaylists()
+ showToast('All playlists have been removed')
},
...mapActions([
From 416a7a81f0bbed32f0b46907598c16dafc324fb8 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 31 May 2023 09:19:47 +0800
Subject: [PATCH 095/236] ! Fix remote playlist video list rendering with
duplicate videos
---
src/renderer/views/Playlist/Playlist.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index 724a11622c96a..d7759d57d217d 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -35,7 +35,7 @@
>
Date: Wed, 31 May 2023 09:22:49 +0800
Subject: [PATCH 096/236] ! Fix missing key for some direct child elements
under `transition-group`
---
src/renderer/views/Playlist/Playlist.vue | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index d7759d57d217d..d8a774004ab5f 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -60,6 +60,7 @@
From 2992b4b74031109171f1dcd163bc76636aab4177 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 31 May 2023 09:29:25 +0800
Subject: [PATCH 097/236] ! Fix animation introduced to unnecessary elements
---
src/renderer/views/Playlist/Playlist.vue | 59 ++++++++++++------------
1 file changed, 30 insertions(+), 29 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index d8a774004ab5f..2cb4b7b9d427e 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -28,39 +28,41 @@
v-if="!isLoading"
class="playlistItems"
>
-
-
-
- {{ index + 1 }}
-
-
-
+
+ {{ index + 1 }}
+
+
+
+
-
+
From a5292ec145f4629886240b65481b841e9359f309 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 31 May 2023 09:33:29 +0800
Subject: [PATCH 098/236] ! Prevent video link click during animation
---
src/renderer/views/Playlist/Playlist.scss | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/renderer/views/Playlist/Playlist.scss b/src/renderer/views/Playlist/Playlist.scss
index 6c3bd467f6dd4..325d5749b6d73 100644
--- a/src/renderer/views/Playlist/Playlist.scss
+++ b/src/renderer/views/Playlist/Playlist.scss
@@ -46,6 +46,11 @@
:deep(.ft-list-item .videoThumbnail .playlistIcons) {
display: none;
}
+ // Prevent link click
+ :deep(.ft-list-item .videoThumbnail .thumbnailLink) {
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
+ pointer-events: none;
+ }
}
.playlistItem-enter, .playlistItem-leave-to {
opacity: 0;
From a08126679c965139458450a0011a3cce62b3cc89 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 3 Jun 2023 21:04:45 +0800
Subject: [PATCH 099/236] ! Fix playlist creation/removal not reflected in
other windows
---
src/main/index.js | 14 ++++++++++----
src/renderer/store/modules/playlists.js | 2 +-
src/renderer/store/modules/settings.js | 8 ++++++++
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/src/main/index.js b/src/main/index.js
index 219dadb0935d9..b9a1e44e17591 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -890,8 +890,11 @@ function runApp() {
switch (action) {
case DBActions.GENERAL.CREATE:
await baseHandlers.playlists.create(data)
- // TODO: Syncing (implement only when it starts being used)
- // syncOtherWindows(IpcChannels.SYNC_PLAYLISTS, event, { event: '_', data })
+ syncOtherWindows(
+ IpcChannels.SYNC_PLAYLISTS,
+ event,
+ { event: SyncEvents.GENERAL.CREATE, data }
+ )
return null
case DBActions.GENERAL.FIND:
@@ -923,8 +926,11 @@ function runApp() {
case DBActions.GENERAL.DELETE:
await baseHandlers.playlists.delete(data)
- // TODO: Syncing (implement only when it starts being used)
- // syncOtherWindows(IpcChannels.SYNC_PLAYLISTS, event, { event: '_', data })
+ syncOtherWindows(
+ IpcChannels.SYNC_PLAYLISTS,
+ event,
+ { event: SyncEvents.GENERAL.DELETE, data }
+ )
return null
case DBActions.PLAYLISTS.DELETE_VIDEO_ID:
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 1a81c5d650346..2d2d8d23fa532 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -60,7 +60,7 @@ const actions = {
payload.lastUpdatedAt = Date.now()
try {
- await DBPlaylistHandlers.create(payload)
+ await DBPlaylistHandlers.create([payload])
commit('addPlaylist', payload)
} catch (errMessage) {
console.error(errMessage)
diff --git a/src/renderer/store/modules/settings.js b/src/renderer/store/modules/settings.js
index f6439f28ce2a6..6cd1bb56e72fd 100644
--- a/src/renderer/store/modules/settings.js
+++ b/src/renderer/store/modules/settings.js
@@ -490,6 +490,14 @@ const customActions = {
ipcRenderer.on(IpcChannels.SYNC_PLAYLISTS, (_, { event, data }) => {
switch (event) {
+ case SyncEvents.GENERAL.CREATE:
+ commit('addPlaylists', data)
+ break
+
+ case SyncEvents.GENERAL.DELETE:
+ commit('removePlaylist', data)
+ break
+
case SyncEvents.PLAYLISTS.UPSERT:
commit('upsertPlaylistToList', data)
break
From 40db0b5caf119fe0a145bb9e61cf3ac236559b1a Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 6 Jun 2023 09:24:32 +0800
Subject: [PATCH 100/236] * Ensure playlist visual selected state in sync with
data in parent
---
.../ft-playlist-add-video-prompt.vue | 1 +
.../ft-playlist-selector.js | 18 +++++++++---------
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index eb3ea0139d6a1..abd67a9f9b291 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -23,6 +23,7 @@
:key="`${playlist._id}-${index}`"
:data="playlist"
:index="index"
+ :selected="selectedPlaylistIdList.includes(playlist._id)"
@selected="countSelected(playlist._id)"
/>
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
index ba206d9c5ce90..4de8884c5aca1 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
@@ -10,24 +10,26 @@ export default Vue.extend({
props: {
data: {
type: Object,
- required: true
+ required: true,
},
index: {
type: Number,
- required: true
+ required: true,
},
appearance: {
type: String,
- default: 'grid'
- }
+ default: 'grid',
+ },
+ selected: {
+ type: Boolean,
+ required: true,
+ },
},
data: function () {
return {
title: '',
thumbnail: '',
- playlistId: '',
videoCount: 0,
- selected: false
}
},
computed: {
@@ -53,12 +55,10 @@ export default Vue.extend({
} else {
this.thumbnail = 'https://i.ytimg.com/vi/aaaaaa/mqdefault.jpg'
}
- this.playlistLink = this.data._id
- this.videoCount = this.data.videoCount ? this.data.videoCount : this.data.videos.length
+ this.videoCount = this.data.videos.length
},
toggleSelection: function () {
- this.selected = !this.selected
this.$emit('selected', this.index)
},
From 6ec711cef0d6a0419b10415de6793db8c4646049 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 6 Jun 2023 09:49:49 +0800
Subject: [PATCH 101/236] * Update add video to playlist prompt to auto select
playlists created after prompt shown once
---
.../ft-playlist-add-video-prompt.js | 25 +++++++++++++++++++
src/renderer/store/modules/playlists.js | 7 ++++++
2 files changed, 32 insertions(+)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 9a060c7aaf6af..a9be8d67fb16d 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -22,8 +22,10 @@ export default Vue.extend({
data: function () {
return {
selectedPlaylistIdList: [],
+ createdSincePromptShownPlaylistIdList: [],
query: '',
updateQueryDebounce: function() {},
+ lastShownAt: Date.now(),
}
},
computed: {
@@ -49,6 +51,9 @@ export default Vue.extend({
return a.title.localeCompare(b.title, this.locale)
})
},
+ allPlaylistsLength() {
+ return this.allPlaylists.length
+ },
selectedPlaylistCount: function () {
return this.selectedPlaylistIdList.length
},
@@ -82,6 +87,26 @@ export default Vue.extend({
})
},
},
+ watch: {
+ allPlaylistsLength(val, oldVal) {
+ // When playlist length changed, a playlist removed or added
+ // Only cares about playlist added
+ if (val < oldVal) { return }
+
+ this.allPlaylists.forEach((playlist) => {
+ // Old playlists don't have `createdAt`
+ if (playlist.createdAt == null) { return }
+ // Only playlists created after this prompt shown should be considered
+ if (playlist.createdAt < this.lastShownAt) { return }
+ // Only playlists not auto added to selected yet should be considered
+ if (this.createdSincePromptShownPlaylistIdList.includes(playlist._id)) { return }
+
+ // Add newly created playlists to selected ONCE
+ this.createdSincePromptShownPlaylistIdList.push(playlist._id)
+ this.selectedPlaylistIdList.push(playlist._id)
+ })
+ },
+ },
mounted: function () {
// this.parseUserData()
this.updateQueryDebounce = debounce(this.updateQuery, 500)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 2d2d8d23fa532..89b39349f97b6 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -57,6 +57,7 @@ const actions = {
if (typeof payload.description === 'string') {
payload.description = payload.description.trim()
}
+ payload.createdAt = Date.now()
payload.lastUpdatedAt = Date.now()
try {
@@ -136,6 +137,12 @@ const actions = {
playlist.playlistName = generateRandomPlaylistName()
anythingUpdated = true
}
+ // 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()
+ 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
From bd9ff58d425bcd66e105e978a06634cbd044324d Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 6 Jun 2023 10:08:56 +0800
Subject: [PATCH 102/236] * Update copy playlist button to show warning about
not loaded videos when some not loaded yet
For remote playlist
Won't work for Invidious though (coz no way to load more)
---
.../components/playlist-info/playlist-info.js | 13 ++++++++++++-
src/renderer/views/Playlist/Playlist.js | 4 ++++
src/renderer/views/Playlist/Playlist.vue | 3 ++-
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 20c67d1290a51..09150f1f475ca 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -67,6 +67,10 @@ export default defineComponent({
type: String,
required: true,
},
+ moreVideoDataAvailable: {
+ type: Boolean,
+ required: true,
+ },
},
data: function () {
return {
@@ -163,7 +167,14 @@ export default defineComponent({
this.newDescription = this.description
},
methods: {
- toggleCopyVideosPrompt: function () {
+ toggleCopyVideosPrompt: function (force = false) {
+ if (this.moreVideoDataAvailable && !force) {
+ showToast('Some videos in the playlist are not loaded yet. Click here to copy anyway.', 5000, () => {
+ this.toggleCopyVideosPrompt(true)
+ })
+ return
+ }
+
this.showAddToPlaylistPromptForManyVideos({
videos: this.videos,
newPlaylistDefaultProperties: { title: this.title },
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index b9ccf47765e90..f66dd0f976ad8 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -92,6 +92,10 @@ export default defineComponent({
selectedUserPlaylistVideoCount: function() {
return this.selectedUserPlaylistVideos.length
},
+
+ moreVideoDataAvailable() {
+ return this.continuationData !== null
+ },
},
watch: {
$route () {
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index 2cb4b7b9d427e..f37456dc557f1 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -19,6 +19,7 @@
:videos="playlistItems"
:view-count="viewCount"
:info-source="infoSource"
+ :more-video-data-available="moreVideoDataAvailable"
class="playlistInfo"
@enter-edit-mode="playlistInEditMode = true"
@exit-edit-mode="playlistInEditMode = false"
@@ -62,7 +63,7 @@
Date: Wed, 7 Jun 2023 09:35:48 +0800
Subject: [PATCH 103/236] * Update add video prompt to make it easier to access
buttons via keyboard
---
.../ft-playlist-add-video-prompt.vue | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index abd67a9f9b291..9f274744f1b59 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -30,14 +30,17 @@
From b35db8f3e0731f5de3ee7f65ee760ab607dff95a Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 8 Jun 2023 08:25:57 +0800
Subject: [PATCH 104/236] * Make video reorder & remove button always visible
in user playlist view
---
src/renderer/scss-partials/_ft-list-item.scss | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/src/renderer/scss-partials/_ft-list-item.scss b/src/renderer/scss-partials/_ft-list-item.scss
index 57f97d559e915..3a32f8b66677c 100644
--- a/src/renderer/scss-partials/_ft-list-item.scss
+++ b/src/renderer/scss-partials/_ft-list-item.scss
@@ -168,17 +168,11 @@ $watched-transition-duration: 0.5s;
}
// Show some buttons on hover only
- .addToPlaylistIcon ,
- .trashIcon ,
- .upArrowIcon ,
- .downArrowIcon {
+ .addToPlaylistIcon {
display: none;
}
&:hover {
- .addToPlaylistIcon ,
- .trashIcon ,
- .upArrowIcon ,
- .downArrowIcon {
+ .addToPlaylistIcon {
display: inherit;
}
}
From 6c5b30f9494c1b5b95c7656627c220208b8cba05 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 8 Jun 2023 08:49:18 +0800
Subject: [PATCH 105/236] * Make plus button can be focused with tab
Side effect is thumbnail link can be focused too (otherwise can't make plus button visible)
---
src/renderer/components/ft-list-video/ft-list-video.vue | 2 +-
src/renderer/scss-partials/_ft-list-item.scss | 3 ++-
2 files changed, 3 insertions(+), 2 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 2d7926e8d6083..e05b92ecffd11 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -13,7 +13,7 @@
>
Date: Mon, 12 Jun 2023 11:06:56 +0800
Subject: [PATCH 109/236] $ Refactor `inUserPlaylist`
Only playlist view would supply `playlistType`
---
src/renderer/components/ft-list-video/ft-list-video.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 85a79f8b6480c..0089e2c2305e5 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -126,7 +126,7 @@ export default defineComponent({
},
inUserPlaylist: function () {
- return this.$router.currentRoute.path.includes('playlist') && this.playlistType === 'user'
+ return this.playlistType === 'user'
},
selectedUserPlaylist: function () {
From b6b60f50e28bee575c501616833091b87d69fc3e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 13 Jun 2023 14:49:23 +0800
Subject: [PATCH 110/236] * Improve accessibility for new prompts
---
src/renderer/components/ft-button/ft-button.js | 7 ++++++-
src/renderer/components/ft-button/ft-button.vue | 1 +
.../ft-create-playlist-prompt.js | 15 ++++++++++++++-
.../ft-create-playlist-prompt.vue | 4 ++++
src/renderer/components/ft-input/ft-input.js | 7 ++++++-
src/renderer/components/ft-input/ft-input.vue | 1 +
.../ft-playlist-add-video-prompt.js | 11 +++++++++++
.../ft-playlist-add-video-prompt.vue | 8 +++++---
8 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/src/renderer/components/ft-button/ft-button.js b/src/renderer/components/ft-button/ft-button.js
index 808b8949b2b4b..2ebab33a56250 100644
--- a/src/renderer/components/ft-button/ft-button.js
+++ b/src/renderer/components/ft-button/ft-button.js
@@ -18,6 +18,11 @@ export default defineComponent({
id: {
type: String,
default: ''
- }
+ },
+ tabindex: {
+ type: Number,
+ // Relies on template to not output tabindex on values < -1
+ default: -2,
+ },
}
})
diff --git a/src/renderer/components/ft-button/ft-button.vue b/src/renderer/components/ft-button/ft-button.vue
index 88a340248188e..d0107780768c0 100644
--- a/src/renderer/components/ft-button/ft-button.vue
+++ b/src/renderer/components/ft-button/ft-button.vue
@@ -2,6 +2,7 @@
diff --git a/src/renderer/components/ft-input/ft-input.js b/src/renderer/components/ft-input/ft-input.js
index 763d72d807bd3..8e2af8315f40b 100644
--- a/src/renderer/components/ft-input/ft-input.js
+++ b/src/renderer/components/ft-input/ft-input.js
@@ -60,7 +60,12 @@ export default defineComponent({
tooltip: {
type: String,
default: ''
- }
+ },
+ inputTabindex: {
+ type: Number,
+ // Relies on template to not output tabindex on values < -1
+ default: -2,
+ },
},
data: function () {
let actionIcon = ['fas', 'search']
diff --git a/src/renderer/components/ft-input/ft-input.vue b/src/renderer/components/ft-input/ft-input.vue
index 5ced9eea7ab87..4f6e9904f5cbb 100644
--- a/src/renderer/components/ft-input/ft-input.vue
+++ b/src/renderer/components/ft-input/ft-input.vue
@@ -45,6 +45,7 @@
v-model="inputData"
:list="idDataList"
class="ft-input"
+ :tabindex="inputTabindex >= -1 ? inputTabindex : null"
:type="inputType"
:placeholder="placeholder"
:disabled="disabled"
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 4ebc4ea11a839..4dda3b0db6043 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -86,6 +86,13 @@ export default Vue.extend({
return b.lastUpdatedAt - a.lastUpdatedAt
})
},
+
+ tabindexOffset() {
+ // To avoid tabbing into content outside the prompt
+ // Assigning an offset here
+ // Hardcoding one first but might switch to some kind of calculation later
+ return 100 * 100
+ },
},
watch: {
allPlaylistsLength(val, oldVal) {
@@ -167,6 +174,10 @@ export default Vue.extend({
this.query = query
},
+ localToGlobalTabindex(localTabindex) {
+ return this.tabindexOffset + localTabindex
+ },
+
...mapActions([
'addVideo',
'hideAddToPlaylistPrompt',
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 9f274744f1b59..df6892880ab0c 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -14,6 +14,7 @@
placeholder="Search in Playlist"
:show-clear-text-button="true"
:show-action-button="false"
+ :input-tabindex="localToGlobalTabindex(0)"
@input="(input) => updateQueryDebounce(input)"
@clear="updateQueryDebounce('')"
/>
@@ -21,6 +22,7 @@
From a624a85b12a7b467c2b8eb7ab06b77d0f5c26de8 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 15 Jun 2023 09:51:40 +0800
Subject: [PATCH 111/236] * Make edit playlist inputs focused on entering edit
mode
---
src/renderer/components/playlist-info/playlist-info.js | 7 ++++++-
src/renderer/components/playlist-info/playlist-info.vue | 3 +++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 09150f1f475ca..f72ab72b6f33f 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -1,4 +1,4 @@
-import { defineComponent } from 'vue'
+import { defineComponent, nextTick } from 'vue'
import { mapActions } from 'vuex'
import FtShareButton from '../ft-share-button/ft-share-button.vue'
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
@@ -211,6 +211,11 @@ export default defineComponent({
this.editMode = true
this.$emit('enter-edit-mode')
+
+ nextTick(() => {
+ // Some elements only present after rendering update
+ this.$refs.playlistTitleInput.focus()
+ })
},
exitEditMode: function () {
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 73060ba70cb21..19cbefdfee475 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -20,7 +20,9 @@
Date: Fri, 16 Jun 2023 11:54:54 +0800
Subject: [PATCH 112/236] * Make most prompts focus back to last focused
element on close
---
.../ft-create-playlist-prompt.js | 10 +++++++++-
.../ft-playlist-add-video-prompt.js | 8 ++++++++
src/renderer/components/ft-prompt/ft-prompt.js | 10 +++++++++-
3 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index 10ad32ac61ef6..d08f9372752b7 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -25,7 +25,8 @@ export default Vue.extend({
'save',
'cancel'
],
- selectedPlaylists: []
+ selectedPlaylists: [],
+ lastActiveElement: null,
}
},
computed: {
@@ -47,10 +48,17 @@ export default Vue.extend({
},
},
mounted: function () {
+ this.lastActiveElement = document.activeElement
+
this.playlistName = this.newPlaylistVideoObject.title
// Faster to input required playlist name
this.$refs.playlistNameInput.focus()
},
+ destroyed() {
+ if (this.lastActiveElement != null) {
+ this.lastActiveElement.focus()
+ }
+ },
methods: {
handleCreatePlaylistPrompt: function (option) {
this.hideCreatePlaylistPrompt()
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 4dda3b0db6043..5ad4c31fb388d 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -26,6 +26,7 @@ export default Vue.extend({
query: '',
updateQueryDebounce: function() {},
lastShownAt: Date.now(),
+ lastActiveElement: null,
}
},
computed: {
@@ -115,10 +116,17 @@ export default Vue.extend({
},
},
mounted: function () {
+ this.lastActiveElement = document.activeElement
+
this.updateQueryDebounce = debounce(this.updateQuery, 500)
// User might want to search first if they have many playlists
this.$refs.searchBar.focus()
},
+ destroyed() {
+ if (this.lastActiveElement != null) {
+ this.lastActiveElement.focus()
+ }
+ },
methods: {
hide: function () {
this.hideAddToPlaylistPrompt()
diff --git a/src/renderer/components/ft-prompt/ft-prompt.js b/src/renderer/components/ft-prompt/ft-prompt.js
index 622eb64f72742..c6ac3ad911798 100644
--- a/src/renderer/components/ft-prompt/ft-prompt.js
+++ b/src/renderer/components/ft-prompt/ft-prompt.js
@@ -39,7 +39,8 @@ export default defineComponent({
},
data: function () {
return {
- promptButtons: []
+ promptButtons: [],
+ lastActiveElement: null,
}
},
computed: {
@@ -51,6 +52,8 @@ export default defineComponent({
document.removeEventListener('keydown', this.closeEventFunction, true)
},
mounted: function () {
+ this.lastActiveElement = document.activeElement
+
document.addEventListener('keydown', this.closeEventFunction, true)
document.querySelector('.prompt').addEventListener('keydown', this.arrowKeys, true)
this.promptButtons = Array.from(
@@ -60,6 +63,11 @@ export default defineComponent({
})
this.focusItem(0)
},
+ destroyed() {
+ if (this.lastActiveElement != null) {
+ this.lastActiveElement.focus()
+ }
+ },
methods: {
hide: function() {
this.$emit('click', null)
From d7412b18638ce61bf0d89cc48b3c390396f87737 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 16 Jun 2023 15:07:10 +0800
Subject: [PATCH 113/236] $ Use tabindex 0 for prompts
Possible tabindex values unnecessary with elements programatically focused
---
.../ft-create-playlist-prompt.js | 11 -----------
.../ft-create-playlist-prompt.vue | 6 +++---
.../ft-playlist-add-video-prompt.js | 11 -----------
.../ft-playlist-add-video-prompt.vue | 10 +++++-----
4 files changed, 8 insertions(+), 30 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index d08f9372752b7..b5393a22c976f 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -39,13 +39,6 @@ export default Vue.extend({
videoImportLength: function () {
return this.newPlaylistVideoObject.videos.length
},
-
- tabindexOffset() {
- // To avoid tabbing into content outside the prompt
- // Assigning an offset here
- // Hardcoding one first but might switch to some kind of calculation later
- return 2 * 100 * 100
- },
},
mounted: function () {
this.lastActiveElement = document.activeElement
@@ -102,10 +95,6 @@ export default Vue.extend({
}
},
- localToGlobalTabindex(localTabindex) {
- return this.tabindexOffset + localTabindex
- },
-
...mapActions([
'showToast',
'addPlaylist',
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
index 5060067a6c941..809b01c3407de 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
@@ -9,7 +9,7 @@
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 5ad4c31fb388d..a90bfe66a3995 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -87,13 +87,6 @@ export default Vue.extend({
return b.lastUpdatedAt - a.lastUpdatedAt
})
},
-
- tabindexOffset() {
- // To avoid tabbing into content outside the prompt
- // Assigning an offset here
- // Hardcoding one first but might switch to some kind of calculation later
- return 100 * 100
- },
},
watch: {
allPlaylistsLength(val, oldVal) {
@@ -182,10 +175,6 @@ export default Vue.extend({
this.query = query
},
- localToGlobalTabindex(localTabindex) {
- return this.tabindexOffset + localTabindex
- },
-
...mapActions([
'addVideo',
'hideAddToPlaylistPrompt',
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index df6892880ab0c..8cbe3529a5c7f 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -14,7 +14,7 @@
placeholder="Search in Playlist"
:show-clear-text-button="true"
:show-action-button="false"
- :input-tabindex="localToGlobalTabindex(0)"
+ :input-tabindex="0"
@input="(input) => updateQueryDebounce(input)"
@clear="updateQueryDebounce('')"
/>
@@ -22,7 +22,7 @@
From 349c36377be49bbcefde5b1646d6168e5f65b69f Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 19 Jun 2023 16:16:27 +0800
Subject: [PATCH 114/236] * Update add video to playlist prompt to focus back
to search input after new playlist created
---
.../ft-playlist-add-video-prompt.js | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index a90bfe66a3995..855d1cd0fc13d 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -106,6 +106,10 @@ export default Vue.extend({
this.createdSincePromptShownPlaylistIdList.push(playlist._id)
this.selectedPlaylistIdList.push(playlist._id)
})
+
+ // Focus back to search input
+ // Allow search and easier deselecting new created playlist
+ this.$refs.searchBar.focus()
},
},
mounted: function () {
From 1d41b23e91dd238eaf74ab44164f57c36540aa02 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 20 Jun 2023 11:47:55 +0800
Subject: [PATCH 115/236] * Update ft-list-video to focus back on thumbnail
link element after add to playlist prompt closed
---
.../components/ft-list-video/ft-list-video.js | 24 ++++++++++++++++++-
.../ft-list-video/ft-list-video.vue | 1 +
2 files changed, 24 insertions(+), 1 deletion(-)
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 0089e2c2305e5..624b1f05b61ef 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -91,7 +91,8 @@ export default defineComponent({
isLive: false,
isUpcoming: false,
isPremium: false,
- hideViews: false
+ hideViews: false,
+ addToPlaylistPromptCloseCallback: null,
}
},
computed: {
@@ -360,11 +361,22 @@ export default defineComponent({
currentLocale: function () {
return this.$i18n.locale.replace('_', '-')
},
+
+ showAddToPlaylistPrompt: function () {
+ return this.$store.getters.getShowAddToPlaylistPrompt
+ },
},
watch: {
historyIndex() {
this.checkIfWatched()
},
+ showAddToPlaylistPrompt(value) {
+ if (value) { return }
+ // Execute on prompt close
+
+ if (this.addToPlaylistPromptCloseCallback == null) { return }
+ this.addToPlaylistPromptCloseCallback()
+ },
},
created: function () {
this.parseVideoData()
@@ -584,6 +596,16 @@ export default defineComponent({
}
this.showAddToPlaylistPromptForManyVideos({ videos: [videoData] })
+
+ // Focus when prompt closed
+ this.addToPlaylistPromptCloseCallback = () => {
+ // Run once only
+ this.addToPlaylistPromptCloseCallback = null
+
+ // `thumbnailLink` is a `router-link`
+ // `focus()` can only be called on the actual element
+ this.$refs.thumbnailLink.$el.focus()
+ }
},
...mapActions([
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 878ef066bc6b8..4a16c7f6a756c 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -12,6 +12,7 @@
class="videoThumbnail"
>
New Playlist Name
@@ -33,7 +33,7 @@
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 855d1cd0fc13d..138eaf7538ab3 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -27,6 +27,8 @@ export default Vue.extend({
updateQueryDebounce: function() {},
lastShownAt: Date.now(),
lastActiveElement: null,
+ interactionsLocked: false,
+ preventOpenCreatePlaylistPromptOnce: false,
}
},
computed: {
@@ -87,6 +89,14 @@ export default Vue.extend({
return b.lastUpdatedAt - a.lastUpdatedAt
})
},
+
+ createPlaylistPromptShown: function () {
+ return this.$store.getters.getShowCreatePlaylistPrompt
+ },
+
+ tabindex() {
+ return this.interactionsLocked ? -1 : 0
+ }
},
watch: {
allPlaylistsLength(val, oldVal) {
@@ -111,6 +121,17 @@ export default Vue.extend({
// Allow search and easier deselecting new created playlist
this.$refs.searchBar.focus()
},
+
+ createPlaylistPromptShown(value) {
+ // Lock interactions when create playlist prompt opened
+ this.interactionsLocked = value
+
+ if (!value) {
+ // create playlist prompt closing
+ // Solution/Workaround for strange click event
+ this.preventOpenCreatePlaylistPromptOnce = true
+ }
+ },
},
mounted: function () {
this.lastActiveElement = document.activeElement
@@ -168,7 +189,14 @@ export default Vue.extend({
this.hide()
},
- createNewPlaylist: function () {
+ openCreatePlaylistPrompt: function () {
+ // Solution/Workaround for strange click event
+ // Prevents prompt from reopening right after close
+ if (this.preventOpenCreatePlaylistPromptOnce) {
+ this.preventOpenCreatePlaylistPromptOnce = false
+ return
+ }
+
this.showCreatePlaylistPrompt({
title: this.newPlaylistDefaultProperties.title || '',
videos: [],
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 8cbe3529a5c7f..a5d6ecea383ee 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -14,7 +14,7 @@
placeholder="Search in Playlist"
:show-clear-text-button="true"
:show-action-button="false"
- :input-tabindex="0"
+ :input-tabindex="tabindex"
@input="(input) => updateQueryDebounce(input)"
@clear="updateQueryDebounce('')"
/>
@@ -22,7 +22,7 @@
From 3b1bace0231b38db7f8a6b455bfb9e097f38a202 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 27 Jun 2023 10:33:48 +0800
Subject: [PATCH 118/236] ! Fix duplicate video entry ID when playlist with
duplicate videoId entries copied to another playlist
---
.../components/data-settings/data-settings.js | 22 +++++++++--
.../ft-create-playlist-prompt.js | 7 +---
.../ft-playlist-add-video-prompt.js | 5 +--
src/renderer/store/modules/playlists.js | 37 ++++++++++++++++---
src/renderer/store/modules/utils.js | 3 ++
src/renderer/views/Playlist/Playlist.js | 12 +++---
src/renderer/views/Playlist/Playlist.vue | 8 ++--
7 files changed, 65 insertions(+), 29 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index 0562be9e935b6..e33531288db8d 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -904,6 +904,9 @@ export default defineComponent({
'authorId',
'lengthSeconds',
'timeAdded',
+
+ // `uniqueId` should be optional for backward compatibility
+ // 'uniqueId',
]
playlists.forEach((playlistData) => {
@@ -946,10 +949,21 @@ export default defineComponent({
if (existingPlaylist !== undefined) {
playlistObject.videos.forEach((video) => {
- const videoExists = existingPlaylist.videos.some((x) => {
- // Allow duplicate (by videoId) videos to be added
- return x.videoId === video.videoId && x.timeAdded === video.timeAdded
- })
+ let videoExists = false
+ if (video.uniqueId != null) {
+ // Find by `uniqueId` if present
+ videoExists = existingPlaylist.videos.some((x) => {
+ // Allow duplicate (by videoId) videos to be added
+ return x.videoId === video.videoId && x.uniqueId === video.uniqueId
+ })
+ } else {
+ // Older playlist exports have no `uniqueId` but have `timeAdded`
+ // Which might be duplicate for copied playlists with duplicate `videoId`
+ videoExists = existingPlaylist.videos.some((x) => {
+ // Allow duplicate (by videoId) videos to be added
+ return x.videoId === video.videoId && x.timeAdded === video.timeAdded
+ })
+ }
if (!videoExists) {
// Keep original `timeAdded` value
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index 9a308d0c50cd7..10689810a4f16 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -62,12 +62,7 @@ export default Vue.extend({
return
}
- const videosObject = (this.videoImportLength > 0 ? this.newPlaylistVideoObject.videos : []).map((vobj) => {
- if (vobj.timeAdded == null) {
- vobj.timeAdded = new Date().getTime()
- }
- return vobj
- })
+ const videosObject = (this.videoImportLength > 0 ? this.newPlaylistVideoObject.videos : [])
const playlistObject = {
playlistName: this.playlistName,
protected: false,
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 138eaf7538ab3..0848ee27e4283 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -175,10 +175,7 @@ export default Vue.extend({
const payload = {
_id: playlist._id,
// Avoid `do not mutate vuex store state outside mutation handlers`
- videoData: Object.assign({}, videoObject, {
- // Part of unique ID for duplicate videos
- timeAdded: new Date().getTime(),
- }),
+ videoData: videoObject,
}
this.addVideo(payload)
addedPlaylistIds.add(playlist._id)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 89b39349f97b6..e52e1a1ce3f54 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -1,3 +1,4 @@
+import crypto from 'crypto'
import { DBPlaylistHandlers } from '../../../datastores/handlers/index'
function generateRandomPlaylistId() {
@@ -8,6 +9,10 @@ function generateRandomPlaylistName() {
return `Playlist ${new Date().toISOString()}-${Math.floor(Math.random() * 10000)}`
}
+function generateRandomUniqueId() {
+ return crypto.randomUUID()
+}
+
const state = {
// Playlist loading takes time on app load (new windows)
// This is necessary to let components to know when to start data loading
@@ -59,6 +64,17 @@ const actions = {
}
payload.createdAt = Date.now()
payload.lastUpdatedAt = Date.now()
+ // Ensure all videos has required attributes
+ if (Array.isArray(payload.videos)) {
+ payload.videos.forEach(videoData => {
+ if (videoData.timeAdded == null) {
+ videoData.timeAdded = new Date().getTime()
+ }
+ if (videoData.uniqueId == null) {
+ videoData.uniqueId = generateRandomUniqueId()
+ }
+ })
+ }
try {
await DBPlaylistHandlers.create([payload])
@@ -100,6 +116,12 @@ const actions = {
async addVideo({ commit }, payload) {
try {
const { _id, videoData } = payload
+ if (videoData.timeAdded == null) {
+ videoData.timeAdded = new Date().getTime()
+ }
+ if (videoData.uniqueId == null) {
+ videoData.uniqueId = generateRandomUniqueId()
+ }
await DBPlaylistHandlers.upsertVideoByPlaylistId(_id, videoData)
commit('addVideo', payload)
} catch (errMessage) {
@@ -149,12 +171,17 @@ const actions = {
playlist.lastUpdatedAt = Date.now()
anythingUpdated = true
}
- // Ensure all videos has `timeAdded` property
playlist.videos.forEach((v) => {
- if (v.timeAdded != null) { return }
+ // Ensure all videos has `timeAdded` property
+ if (v.timeAdded == null) {
+ v.timeAdded = new Date().getTime()
+ anythingUpdated = true
+ }
- v.timeAdded = new Date().getTime()
- anythingUpdated = true
+ // Ensure all videos has `uniqueId` property
+ if (v.uniqueId == null) {
+ v.uniqueId = generateRandomUniqueId()
+ }
})
// Save updated playlist object
if (anythingUpdated) {
@@ -327,7 +354,7 @@ const mutations = {
removeVideo(state, payload) {
const playlist = state.playlists.find(playlist => playlist._id === payload._id)
if (playlist) {
- playlist.videos = playlist.videos.filter(video => video.videoId !== payload.videoId || video.timeAdded !== payload.timeAdded)
+ playlist.videos = playlist.videos.filter(video => video.videoId !== payload.videoId || video.uniqueId !== payload.uniqueId)
}
},
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index b2abd7e73af85..402c4017b5e9c 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -279,6 +279,9 @@ const actions = {
// `timeAdded` should be generated when videos are added
// Not when a prompt is displayed
// 'timeAdded',
+
+ // `uniqueId` should be generated anyway
+ // 'uniqueId',
]
// Using `every` to loop and `return false` to break
videoObjectArray.every((video) => {
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index f66dd0f976ad8..07645d93856b3 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -299,10 +299,10 @@ export default defineComponent({
})
},
- moveVideoUp: function (videoId, timeAdded) {
+ moveVideoUp: function (videoId, uniqueId) {
const playlistItems = [].concat(this.playlistItems)
const videoIndex = playlistItems.findIndex((video) => {
- return video.videoId === videoId && video.timeAdded === timeAdded
+ return video.videoId === videoId && video.uniqueId === uniqueId
})
if (videoIndex === 0) {
@@ -331,10 +331,10 @@ export default defineComponent({
}
},
- moveVideoDown: function (videoId, timeAdded) {
+ moveVideoDown: function (videoId, uniqueId) {
const playlistItems = [].concat(this.playlistItems)
const videoIndex = playlistItems.findIndex((video) => {
- return video.videoId === videoId && video.timeAdded === timeAdded
+ return video.videoId === videoId && video.uniqueId === uniqueId
})
if (videoIndex + 1 === playlistItems.length || videoIndex + 1 > playlistItems.length) {
@@ -363,11 +363,11 @@ export default defineComponent({
}
},
- removeVideoFromPlaylist: function (videoId, timeAdded) {
+ removeVideoFromPlaylist: function (videoId, uniqueId) {
const payload = {
_id: this.playlistId,
videoId: videoId,
- timeAdded: timeAdded,
+ uniqueId: uniqueId,
}
try {
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index b7465d71a2715..53ccfdf86d05f 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -38,7 +38,7 @@
>
From c29529fa34fc846cab8e6ae7e662d87cd81d96dd Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 3 Jul 2023 16:54:21 +0800
Subject: [PATCH 119/236] ! Fix issues caused by last merge in
e291cc8b41b2273a0d77c9f35ea760f0e0f7ac10
---
src/renderer/components/playlist-info/playlist-info.js | 8 +++++---
src/renderer/views/Playlist/Playlist.js | 1 +
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 1e6139d11180e..56adb6c457d06 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -130,11 +130,13 @@ export default defineComponent({
},
thumbnail: function () {
- let baseUrl
+ if (typeof this.playlistThumbnail === 'string' && this.playlistThumbnail.length > 0) {
+ return this.playlistThumbnail
+ }
+
+ let baseUrl = 'https://i.ytimg.com'
if (this.backendPreference === 'invidious') {
baseUrl = this.currentInvidiousInstance
- } else {
- return this.data.playlistThumbnail
}
switch (this.thumbnailPreference) {
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 6c0da26d51da4..68b20f9b689ee 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -40,6 +40,7 @@ export default defineComponent({
playlistTitle: '',
playlistDescription: '',
firstVideoId: '',
+ playlistThumbnail: '',
viewCount: 0,
videoCount: 0,
lastUpdated: undefined,
From 960532d2d7e8cce1382f14e95cb91d7a5d3dc2a5 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 6 Jul 2023 08:37:43 +0800
Subject: [PATCH 120/236] $ Remove unused imports
---
src/renderer/components/watch-video-info/watch-video-info.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index efedecebdb2f0..8d9bc5cb90cdd 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -4,7 +4,7 @@ import FtCard from '../ft-card/ft-card.vue'
import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
import FtShareButton from '../ft-share-button/ft-share-button.vue'
import FtSubscribeButton from '../ft-subscribe-button/ft-subscribe-button.vue'
-import { formatNumber, openExternalLink, showToast } from '../../helpers/utils'
+import { formatNumber, openExternalLink } from '../../helpers/utils'
export default defineComponent({
name: 'WatchVideoInfo',
From bcc99a1b83b1ac3c7e2799c010617394251426fb Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 15 Aug 2023 09:44:53 +0800
Subject: [PATCH 121/236] ! Fix default playlists added when no playlist stored
had no required attributes added on 1st run
---
src/renderer/store/modules/playlists.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index e52e1a1ce3f54..91b43c6137109 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -143,7 +143,10 @@ const actions = {
try {
const payload = (await DBPlaylistHandlers.find()).filter((e) => e != null)
if (payload.length === 0) {
- dispatch('addPlaylists', state.defaultPlaylists)
+ // Not using `addPlaylists` to ensure required attributes with dynamic values added
+ state.defaultPlaylists.forEach(playlist => {
+ dispatch('addPlaylist', playlist)
+ })
} else {
payload.forEach((playlist) => {
let anythingUpdated = false
From f51e28290e78a2f34878a219af1c94876f250f99 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 15 Aug 2023 11:28:31 +0800
Subject: [PATCH 122/236] ! Fix invalid prop type warning
---
src/renderer/components/ft-prompt/ft-prompt.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/ft-prompt/ft-prompt.vue b/src/renderer/components/ft-prompt/ft-prompt.vue
index 0482696d8fdd5..dfcd84ad71e94 100644
--- a/src/renderer/components/ft-prompt/ft-prompt.vue
+++ b/src/renderer/components/ft-prompt/ft-prompt.vue
@@ -38,7 +38,7 @@
v-if="showClose"
:id="'prompt-' + sanitizedLabel + '-close'"
:label="$t('Close')"
- tabindex="0"
+ :tabindex="0"
text-color="'var(--accent-color)'"
background-color="'var(--text-with-accent-color)'"
@click="hide"
From edb841b2c79db6220680dea72960b694cdd29232 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 22 Aug 2023 09:05:46 +0800
Subject: [PATCH 123/236] * Use v-if instead of v-show
---
src/renderer/views/UserPlaylists/UserPlaylists.vue | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index f4d49f53b5cde..2462289f94f75 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -1,11 +1,11 @@
@@ -20,7 +20,7 @@
@click="createNewPlaylist"
/>
You have no playlist. Click on the create new playlist button to create a new one.
{{ $t("User Playlists['Empty Search Message']") }}
From 1f920fc8ebda49470138bf7ed6da4b8c039790ab Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 22 Aug 2023 09:08:57 +0800
Subject: [PATCH 124/236] $ Just assign bool value instead of if-else
---
src/renderer/views/UserPlaylists/UserPlaylists.js | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index 7df8e71636e62..9b681465358aa 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -100,11 +100,7 @@ export default defineComponent({
this.activeData = this.fullData
- if (this.activeData.length < this.allPlaylists.length) {
- this.showLoadMoreButton = true
- } else {
- this.showLoadMoreButton = false
- }
+ this.showLoadMoreButton = this.activeData.length < this.allPlaylists.length
this.filterPlaylistDebounce = debounce(this.filterPlaylist, 500)
},
From d1a2e90d1b797b3f18a20960e60e5d2148757c17 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 22 Aug 2023 09:41:40 +0800
Subject: [PATCH 125/236] + Update playlists view to add sorting option
---
.../views/UserPlaylists/UserPlaylists.css | 5 ++
.../views/UserPlaylists/UserPlaylists.js | 67 +++++++++++++++----
.../views/UserPlaylists/UserPlaylists.vue | 9 +++
3 files changed, 69 insertions(+), 12 deletions(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.css b/src/renderer/views/UserPlaylists/UserPlaylists.css
index 255344bd2b8e3..54859bf97ecc0 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.css
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.css
@@ -16,6 +16,11 @@
vertical-align: middle;
}
+.sortSelect {
+ /* Put it on the right */
+ margin-left: auto;
+}
+
.message {
color: var(--tertiary-text-color);
}
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index 9b681465358aa..4d3a0c067dc2c 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -6,10 +6,32 @@ import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue'
import FtTooltip from '../../components/ft-tooltip/ft-tooltip.vue'
import FtLoader from '../../components/ft-loader/ft-loader.vue'
import FtButton from '../../components/ft-button/ft-button.vue'
+import FtSelect from '../../components/ft-select/ft-select.vue'
import FtElementList from '../../components/ft-element-list/ft-element-list.vue'
import FtInput from '../../components/ft-input/ft-input.vue'
import FtIconButton from '../../components/ft-icon-button/ft-icon-button.vue'
+const SORT_BY_VALUES = {
+ NameAscending: 'name_ascending',
+ NameDescending: 'name_descending',
+
+ LatestCreatedFirst: 'latest_created_first',
+ EarliestCreatedFirst: 'earliest_created_first',
+
+ LatestUpdatedFirst: 'latest_updated_first',
+ EarliestUpdatedFirst: 'earliest_updated_first',
+}
+const SORT_BY_NAMES = {
+ NameAscending: 'A-Z',
+ NameDescending: 'Z-A',
+
+ LatestCreatedFirst: 'Latest Created',
+ EarliestCreatedFirst: 'Earliest Created',
+
+ LatestUpdatedFirst: 'Latest Updated',
+ EarliestUpdatedFirst: 'Earliest Updated',
+}
+
export default defineComponent({
name: 'UserPlaylists',
components: {
@@ -18,6 +40,7 @@ export default defineComponent({
'ft-tooltip': FtTooltip,
'ft-loader': FtLoader,
'ft-button': FtButton,
+ 'ft-select': FtSelect,
'ft-element-list': FtElementList,
'ft-icon-button': FtIconButton,
'ft-input': FtInput,
@@ -30,6 +53,7 @@ export default defineComponent({
showLoadMoreButton: false,
query: '',
activeData: [],
+ sortBy: SORT_BY_VALUES.LatestUpdatedFirst,
}
},
computed: {
@@ -53,18 +77,23 @@ export default defineComponent({
playlist.videoCount = playlist.videos.length
return playlist
}).sort((a, b) => {
- // Sort by favorites, watch later, then alphabetically
- if (a._id === 'favorites') {
- return -1
- } else if (b._id === 'favorites') {
- return 1
- } else if (a._id === 'watchLater') {
- return -1
- } else if (b._id === 'watchLater') {
- return 1
+ switch (this.sortBy) {
+ case SORT_BY_VALUES.NameAscending:
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ case SORT_BY_VALUES.NameDescending:
+ return b.playlistName.localeCompare(a.playlistName, this.locale)
+ case SORT_BY_VALUES.LatestCreatedFirst:
+ return a.createdAt > b.createdAt ? -1 : 1
+ case SORT_BY_VALUES.EarliestCreatedFirst:
+ return a.createdAt < b.createdAt ? -1 : 1
+ case SORT_BY_VALUES.LatestUpdatedFirst:
+ return a.lastUpdatedAt > b.lastUpdatedAt ? -1 : 1
+ case SORT_BY_VALUES.EarliestUpdatedFirst:
+ return a.lastUpdatedAt < b.lastUpdatedAt ? -1 : 1
+ default:
+ console.error(`Unknown sortby: ${this.sortBy}`)
+ return 0
}
-
- return a.title.localeCompare(b.title, this.locale)
})
},
@@ -80,6 +109,13 @@ export default defineComponent({
lowerCaseQuery: function() {
return this.query.toLowerCase()
},
+
+ sortBySelectNames() {
+ return Object.keys(SORT_BY_VALUES).map(k => SORT_BY_NAMES[k])
+ },
+ sortBySelectValues() {
+ return Object.values(SORT_BY_VALUES)
+ },
},
watch: {
lowerCaseQuery() {
@@ -90,14 +126,21 @@ export default defineComponent({
this.activeData = this.fullData
this.filterPlaylist()
},
+ sortBy() {
+ sessionStorage.setItem('UserPlaylists/sortBy', this.sortBy)
+ }
},
mounted: function () {
const limit = sessionStorage.getItem('favoritesLimit')
-
if (limit !== null) {
this.dataLimit = limit
}
+ const sortBy = sessionStorage.getItem('UserPlaylists/sortBy')
+ if (sortBy != null) {
+ this.sortBy = sortBy
+ }
+
this.activeData = this.fullData
this.showLoadMoreButton = this.activeData.length < this.allPlaylists.length
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index 2462289f94f75..cc755dd3334a4 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -28,6 +28,15 @@
@input="(input) => query = input"
@clear="query = ''"
/>
+
Date: Tue, 22 Aug 2023 09:44:00 +0800
Subject: [PATCH 126/236] $- Remove unnecessary property assignments
---
.../ft-playlist-add-video-prompt.js | 11 +----------
src/renderer/views/UserPlaylists/UserPlaylists.js | 11 +----------
2 files changed, 2 insertions(+), 20 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 0848ee27e4283..76d7e345e3d2b 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -34,16 +34,7 @@ export default Vue.extend({
computed: {
allPlaylists: function () {
const playlists = this.$store.getters.getAllPlaylists
- return [].concat(playlists).map((playlist) => {
- playlist.title = playlist.playlistName
- playlist.type = 'playlist'
- playlist.thumbnail = ''
- playlist.channelName = ''
- playlist.channelId = ''
- playlist.playlistId = ''
- playlist.videoCount = playlist.videos.length
- return playlist
- }).sort((a, b) => {
+ return [].concat(playlists).sort((a, b) => {
// Sort by `lastUpdatedAt`, then alphabetically
if (a.lastUpdatedAt > b.lastUpdatedAt) {
return -1
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index 4d3a0c067dc2c..5b8f042760906 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -67,16 +67,7 @@ export default defineComponent({
allPlaylists: function () {
const playlists = this.$store.getters.getAllPlaylists
- return [].concat(playlists).map((playlist) => {
- playlist.title = playlist.playlistName
- playlist.type = 'playlist'
- playlist.thumbnail = ''
- playlist.channelName = ''
- playlist.channelId = ''
- playlist.playlistId = ''
- playlist.videoCount = playlist.videos.length
- return playlist
- }).sort((a, b) => {
+ return [].concat(playlists).sort((a, b) => {
switch (this.sortBy) {
case SORT_BY_VALUES.NameAscending:
return a.playlistName.localeCompare(b.playlistName, this.locale)
From 72fbea2b1621dfed69c6977e41f26df821e68ebb Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 23 Aug 2023 10:39:06 +0800
Subject: [PATCH 127/236] ! Fix issues caused by "Remove unnecessary property
assignments"
---
.../ft-element-list/ft-element-list.js | 4 ++++
.../ft-element-list/ft-element-list.vue | 3 ++-
.../ft-list-lazy-wrapper.js | 19 ++++++++++++++-----
.../ft-list-lazy-wrapper.vue | 8 ++++----
.../ft-list-playlist/ft-list-playlist.js | 4 ++--
.../views/UserPlaylists/UserPlaylists.js | 2 +-
.../views/UserPlaylists/UserPlaylists.vue | 1 +
7 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/src/renderer/components/ft-element-list/ft-element-list.js b/src/renderer/components/ft-element-list/ft-element-list.js
index 31e57f31151c4..0270f0ee41fe9 100644
--- a/src/renderer/components/ft-element-list/ft-element-list.js
+++ b/src/renderer/components/ft-element-list/ft-element-list.js
@@ -13,6 +13,10 @@ export default defineComponent({
type: Array,
required: true
},
+ dataType: {
+ type: String,
+ default: null,
+ },
display: {
type: String,
required: false,
diff --git a/src/renderer/components/ft-element-list/ft-element-list.vue b/src/renderer/components/ft-element-list/ft-element-list.vue
index f588503ea4c98..e0dee96965e57 100644
--- a/src/renderer/components/ft-element-list/ft-element-list.vue
+++ b/src/renderer/components/ft-element-list/ft-element-list.vue
@@ -4,9 +4,10 @@
>
diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.js b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
index 39962a4638fa3..bfbd83386f677 100644
--- a/src/renderer/components/ft-list-playlist/ft-list-playlist.js
+++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
@@ -97,7 +97,7 @@ export default defineComponent({
},
parseUserData: function () {
- this.title = this.data.title
+ this.title = this.data.playlistName
if (this.data.videos.length > 0) {
this.thumbnail = `https://i.ytimg.com/vi/${this.data.videos[0].videoId}/mqdefault.jpg`
} else {
@@ -106,7 +106,7 @@ export default defineComponent({
this.channelName = ''
this.channelId = ''
this.playlistId = this.data._id
- this.videoCount = this.data.videoCount
+ this.videoCount = this.data.videos.length
},
...mapActions([
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index 5b8f042760906..63700d81fc613 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -119,7 +119,7 @@ export default defineComponent({
},
sortBy() {
sessionStorage.setItem('UserPlaylists/sortBy', this.sortBy)
- }
+ },
},
mounted: function () {
const limit = sessionStorage.getItem('favoritesLimit')
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index cc755dd3334a4..52a6d8d3d1c0c 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -55,6 +55,7 @@
Date: Thu, 24 Aug 2023 10:04:15 +0800
Subject: [PATCH 128/236] ! Fix issues caused by "Remove unnecessary property
assignments"
---
.../ft-playlist-add-video-prompt.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 76d7e345e3d2b..62e2fb0693b96 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -42,7 +42,7 @@ export default Vue.extend({
return 1
}
- return a.title.localeCompare(b.title, this.locale)
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
})
},
allPlaylistsLength() {
From 40c760cb73c2cb20597f3389167e216b5c7c1237 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 24 Aug 2023 10:15:34 +0800
Subject: [PATCH 129/236] * Ensure sort by time also fallbacks to playlist name
sorting
---
.../views/UserPlaylists/UserPlaylists.js | 34 ++++++++++++++-----
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index 63700d81fc613..663779022329b 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -73,16 +73,32 @@ export default defineComponent({
return a.playlistName.localeCompare(b.playlistName, this.locale)
case SORT_BY_VALUES.NameDescending:
return b.playlistName.localeCompare(a.playlistName, this.locale)
- case SORT_BY_VALUES.LatestCreatedFirst:
- return a.createdAt > b.createdAt ? -1 : 1
- case SORT_BY_VALUES.EarliestCreatedFirst:
- return a.createdAt < b.createdAt ? -1 : 1
- case SORT_BY_VALUES.LatestUpdatedFirst:
- return a.lastUpdatedAt > b.lastUpdatedAt ? -1 : 1
- case SORT_BY_VALUES.EarliestUpdatedFirst:
- return a.lastUpdatedAt < b.lastUpdatedAt ? -1 : 1
+ case SORT_BY_VALUES.LatestCreatedFirst: {
+ if (a.createdAt > b.createdAt) { return -1 }
+ if (a.createdAt < b.createdAt) { return 1 }
+
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
+ case SORT_BY_VALUES.EarliestCreatedFirst: {
+ if (a.createdAt < b.createdAt) { return -1 }
+ if (a.createdAt > b.createdAt) { return 1 }
+
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
+ case SORT_BY_VALUES.LatestUpdatedFirst: {
+ if (a.lastUpdatedAt > b.lastUpdatedAt) { return -1 }
+ if (a.lastUpdatedAt < b.lastUpdatedAt) { return 1 }
+
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
+ case SORT_BY_VALUES.EarliestUpdatedFirst: {
+ if (a.lastUpdatedAt < b.lastUpdatedAt) { return -1 }
+ if (a.lastUpdatedAt > b.lastUpdatedAt) { return 1 }
+
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
default:
- console.error(`Unknown sortby: ${this.sortBy}`)
+ console.error(`Unknown sortBy: ${this.sortBy}`)
return 0
}
})
From 0c8d1996e6b3dc1eb0fe2a817bfce937c3464d21 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 24 Aug 2023 11:12:09 +0800
Subject: [PATCH 130/236] ! Fix add/remove video does not update playlist last
created time
---
src/datastores/handlers/base.js | 2 +-
src/renderer/components/data-settings/data-settings.js | 5 ++++-
.../ft-playlist-add-video-prompt.js | 3 +++
src/renderer/views/Playlist/Playlist.js | 2 ++
4 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js
index 466c970a8b4c5..e7b0eacb2caba 100644
--- a/src/datastores/handlers/base.js
+++ b/src/datastores/handlers/base.js
@@ -113,7 +113,7 @@ class Playlists {
}
static upsert(playlist) {
- return db.playlists.updateAsync({ _id: playlist._id }, playlist, { upsert: true })
+ return db.playlists.updateAsync({ _id: playlist._id }, { $set: playlist }, { upsert: true })
}
static upsertVideoByPlaylistId(_id, videoData) {
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index 314c22e56787d..2bc28640d55ac 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -972,6 +972,8 @@ export default defineComponent({
this.addVideo(payload)
}
})
+ // Update playlist's `lastUpdatedAt`
+ this.updatePlaylist({ _id: existingPlaylist._id })
} else {
this.addPlaylist(playlistObject)
}
@@ -1166,7 +1168,8 @@ export default defineComponent({
'updateShowProgressBar',
'updateHistory',
'addPlaylist',
- 'addVideo'
+ 'addVideo',
+ 'updatePlaylist',
]),
...mapMutations([
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 62e2fb0693b96..e74ab532d510c 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -171,6 +171,8 @@ export default Vue.extend({
this.addVideo(payload)
addedPlaylistIds.add(playlist._id)
})
+ // Update playlist's `lastUpdatedAt`
+ this.updatePlaylist({ _id: playlist._id })
})
showToast(`${this.toBeAddedToPlaylistVideoCount} video(s) added to ${addedPlaylistIds.size} playlist(s).`)
@@ -197,6 +199,7 @@ export default Vue.extend({
...mapActions([
'addVideo',
+ 'updatePlaylist',
'hideAddToPlaylistPrompt',
'showCreatePlaylistPrompt',
])
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index df90033a2341e..7045e4270e98e 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -386,6 +386,8 @@ export default defineComponent({
try {
this.removeVideo(payload)
+ // Update playlist's `lastUpdatedAt`
+ this.updatePlaylist({ _id: this.playlistId })
showToast('Video has been removed')
} catch (e) {
showToast('There was a problem with removing this video')
From 9ba72628b2f5e3b42af043e17d84808074ce3242 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 24 Aug 2023 10:55:42 +0800
Subject: [PATCH 131/236] ! Fix multi window playlist sync
---
src/constants.js | 1 -
src/datastores/handlers/electron.js | 2 +-
src/main/index.js | 4 ++--
src/renderer/components/ft-element-list/ft-element-list.vue | 2 +-
src/renderer/store/modules/playlists.js | 3 ++-
src/renderer/store/modules/settings.js | 2 +-
6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/constants.js b/src/constants.js
index f4286c205e0de..4693d857623fd 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -65,7 +65,6 @@ const SyncEvents = {
},
PLAYLISTS: {
- UPSERT: 'sync-playlists-upsert',
UPSERT_VIDEO: 'sync-playlists-upsert-video',
DELETE_VIDEO: 'sync-playlists-delete-video'
}
diff --git a/src/datastores/handlers/electron.js b/src/datastores/handlers/electron.js
index d929177569b54..ca1d2ee8552f7 100644
--- a/src/datastores/handlers/electron.js
+++ b/src/datastores/handlers/electron.js
@@ -129,7 +129,7 @@ class Playlists {
static upsert(playlist) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
- { action: DBActions.PLAYLISTS.UPSERT, data: playlist }
+ { action: DBActions.GENERAL.UPSERT, data: playlist }
)
}
diff --git a/src/main/index.js b/src/main/index.js
index d5ddbc79144e3..4470f78bebae8 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -949,12 +949,12 @@ function runApp() {
case DBActions.GENERAL.FIND:
return await baseHandlers.playlists.find()
- case DBActions.PLAYLISTS.UPSERT:
+ case DBActions.GENERAL.UPSERT:
await baseHandlers.playlists.upsert(data)
syncOtherWindows(
IpcChannels.SYNC_PLAYLISTS,
event,
- { event: SyncEvents.PLAYLISTS.UPSERT, data }
+ { event: SyncEvents.GENERAL.UPSERT, data }
)
return null
diff --git a/src/renderer/components/ft-element-list/ft-element-list.vue b/src/renderer/components/ft-element-list/ft-element-list.vue
index e0dee96965e57..91cdf1a78775f 100644
--- a/src/renderer/components/ft-element-list/ft-element-list.vue
+++ b/src/renderer/components/ft-element-list/ft-element-list.vue
@@ -4,7 +4,7 @@
>
Date: Tue, 29 Aug 2023 08:22:40 +0800
Subject: [PATCH 132/236] * Show filtering input & sorting element when no. of
playlist > 1
---
src/renderer/views/UserPlaylists/UserPlaylists.vue | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index 52a6d8d3d1c0c..9bbe7bb64836a 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -20,7 +20,7 @@
@click="createNewPlaylist"
/>
Date: Tue, 29 Aug 2023 08:31:47 +0800
Subject: [PATCH 133/236] * Update upcoming video to allow saving in playlist
---
src/renderer/components/ft-list-video/ft-list-video.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 70cdecbfa35a4..3b32e878b20be 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -48,7 +48,7 @@
/>
Date: Tue, 29 Aug 2023 08:45:44 +0800
Subject: [PATCH 134/236] ! Fix unable to visit previous video when playing
first video in a playlist
---
.../watch-video-playlist.js | 57 +++++++------------
1 file changed, 22 insertions(+), 35 deletions(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index 44dd9d8186b9a..36b05e9e375f8 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -253,28 +253,22 @@ export default defineComponent({
const videoIndex = this.playlistItems.findIndex((item) => {
return (item.id ?? item.videoId) === this.videoId
})
+ const targetVideoIndex = videoIndex === this.playlistItems.length - 1 ? 0 : videoIndex + 1
+ const targetPlaylistItem = this.playlistItems[targetVideoIndex]
- if (videoIndex === this.playlistItems.length - 1) {
- if (this.loopEnabled) {
- this.$router.push(
- {
- path: `/watch/${this.playlistItems[0].id ?? this.playlistItems[0].videoId}`,
- query: playlistInfo
- }
- )
- showToast(this.$t('Playing Next Video'))
- } else {
- showToast(this.$t('The playlist has ended. Enable loop to continue playing'))
- }
- } else {
- this.$router.push(
- {
- path: `/watch/${this.playlistItems[videoIndex + 1].id ?? this.playlistItems[videoIndex + 1].videoId}`,
- query: playlistInfo
- }
- )
- showToast(this.$t('Playing Next Video'))
+ const stopDueToLoopDisabled = videoIndex === this.playlistItems.length - 1 && !this.loopEnabled
+ if (stopDueToLoopDisabled) {
+ showToast(this.$t('The playlist has ended. Enable loop to continue playing'))
+ return
}
+
+ this.$router.push(
+ {
+ path: `/watch/${targetPlaylistItem.id ?? targetPlaylistItem.videoId}`,
+ query: playlistInfo
+ }
+ )
+ showToast(this.$t('Playing Next Video'))
}
},
@@ -309,22 +303,15 @@ export default defineComponent({
const videoIndex = this.playlistItems.findIndex((item) => {
return (item.id ?? item.videoId) === this.videoId
})
+ const targetVideoIndex = videoIndex === 0 ? this.playlistItems.length - 1 : videoIndex - 1
+ const targetPlaylistItem = this.playlistItems[targetVideoIndex]
- if (videoIndex === 0) {
- this.$router.push(
- {
- path: `/watch/${this.playlistItems[this.randomizedPlaylistItems.length - 1].id ?? this.playlistItems[this.randomizedPlaylistItems.length - 1].videoId}`,
- query: playlistInfo
- }
- )
- } else {
- this.$router.push(
- {
- path: `/watch/${this.playlistItems[videoIndex - 1].id ?? this.playlistItems[videoIndex - 1].videoId}`,
- query: playlistInfo
- }
- )
- }
+ this.$router.push(
+ {
+ path: `/watch/${targetPlaylistItem.id ?? targetPlaylistItem.videoId}`,
+ query: playlistInfo
+ }
+ )
}
},
From f988fd8b676a5b70cfbabc845e1741c471691177 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 29 Aug 2023 14:37:29 +0800
Subject: [PATCH 135/236] * Update sorting options labels
---
src/renderer/views/UserPlaylists/UserPlaylists.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index 663779022329b..b5e3cd3bfa38b 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -25,10 +25,10 @@ const SORT_BY_NAMES = {
NameAscending: 'A-Z',
NameDescending: 'Z-A',
- LatestCreatedFirst: 'Latest Created',
+ LatestCreatedFirst: 'Recently Created',
EarliestCreatedFirst: 'Earliest Created',
- LatestUpdatedFirst: 'Latest Updated',
+ LatestUpdatedFirst: 'Recently Updated',
EarliestUpdatedFirst: 'Earliest Updated',
}
From a2be3caedff1c360c091a0aaa3708684cb395a71 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 29 Aug 2023 14:54:22 +0800
Subject: [PATCH 136/236] ! Fix add to play prompt max width
---
...video-prompt.css => ft-playlist-add-video-prompt.scss} | 8 ++++++++
.../ft-playlist-add-video-prompt.vue | 2 +-
2 files changed, 9 insertions(+), 1 deletion(-)
rename src/renderer/components/ft-playlist-add-video-prompt/{ft-playlist-add-video-prompt.css => ft-playlist-add-video-prompt.scss} (81%)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
similarity index 81%
rename from src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
rename to src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
index d649d4ca9d675..89dff08a90015 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
@@ -21,3 +21,11 @@
.center {
text-align: center;
}
+
+:deep(.promptCard:not(.autosize)) {
+ /* Override some existing style */
+ $horizontal-margin: 2.5%;
+ left: $horizontal-margin;
+ right: $horizontal-margin;
+ width: 100% - ($horizontal-margin * 2);
+}
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index a5d6ecea383ee..501459a057b2d 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -50,4 +50,4 @@
-
+
From d6f2f5dd9ad8ae17a5f452709571e8040651536f Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 29 Aug 2023 14:56:59 +0800
Subject: [PATCH 137/236] ! Fix user playlist view incorrectly sorted playlists
by latest updated first when filtered
---
src/renderer/views/UserPlaylists/UserPlaylists.js | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index b5e3cd3bfa38b..c7f1ace3319d1 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -178,9 +178,6 @@ export default defineComponent({
if (typeof (playlist.playlistName) !== 'string') { return false }
return playlist.playlistName.toLowerCase().includes(this.lowerCaseQuery)
- }).sort((a, b) => {
- // Latest updated first
- return b.lastUpdatedAt - a.lastUpdatedAt
})
this.showLoadMoreButton = filteredPlaylists.length > this.searchDataLimit
this.activeData = filteredPlaylists.length < this.searchDataLimit ? filteredPlaylists : filteredPlaylists.slice(0, this.searchDataLimit)
From 433eb0d9768c962315f78824a47a86e484a37806 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 29 Aug 2023 14:58:11 +0800
Subject: [PATCH 138/236] * Update add to playlist prompt to add sort options
---
.../ft-playlist-add-video-prompt.js | 72 ++++++++++++++++---
.../ft-playlist-add-video-prompt.scss | 5 ++
.../ft-playlist-add-video-prompt.vue | 11 ++-
3 files changed, 79 insertions(+), 9 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index e74ab532d510c..8fd09680ac52d 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -6,10 +6,32 @@ import FtPrompt from '../ft-prompt/ft-prompt.vue'
import FtButton from '../ft-button/ft-button.vue'
import FtPlaylistSelector from '../ft-playlist-selector/ft-playlist-selector.vue'
import FtInput from '../../components/ft-input/ft-input.vue'
+import FtSelect from '../../components/ft-select/ft-select.vue'
import {
showToast,
} from '../../helpers/utils'
+const SORT_BY_VALUES = {
+ NameAscending: 'name_ascending',
+ NameDescending: 'name_descending',
+
+ LatestCreatedFirst: 'latest_created_first',
+ EarliestCreatedFirst: 'earliest_created_first',
+
+ LatestUpdatedFirst: 'latest_updated_first',
+ EarliestUpdatedFirst: 'earliest_updated_first',
+}
+const SORT_BY_NAMES = {
+ NameAscending: 'A-Z',
+ NameDescending: 'Z-A',
+
+ LatestCreatedFirst: 'Recently Created',
+ EarliestCreatedFirst: 'Earliest Created',
+
+ LatestUpdatedFirst: 'Recently Updated',
+ EarliestUpdatedFirst: 'Earliest Updated',
+}
+
export default Vue.extend({
name: 'FtPlaylistAddVideoPrompt',
components: {
@@ -18,6 +40,7 @@ export default Vue.extend({
'ft-button': FtButton,
'ft-playlist-selector': FtPlaylistSelector,
'ft-input': FtInput,
+ 'ft-select': FtSelect,
},
data: function () {
return {
@@ -29,20 +52,46 @@ export default Vue.extend({
lastActiveElement: null,
interactionsLocked: false,
preventOpenCreatePlaylistPromptOnce: false,
+ sortBy: SORT_BY_VALUES.LatestUpdatedFirst,
}
},
computed: {
allPlaylists: function () {
const playlists = this.$store.getters.getAllPlaylists
return [].concat(playlists).sort((a, b) => {
- // Sort by `lastUpdatedAt`, then alphabetically
- if (a.lastUpdatedAt > b.lastUpdatedAt) {
- return -1
- } else if (b.lastUpdatedAt > a.lastUpdatedAt) {
- return 1
- }
+ switch (this.sortBy) {
+ case SORT_BY_VALUES.NameAscending:
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ case SORT_BY_VALUES.NameDescending:
+ return b.playlistName.localeCompare(a.playlistName, this.locale)
+ case SORT_BY_VALUES.LatestCreatedFirst: {
+ if (a.createdAt > b.createdAt) { return -1 }
+ if (a.createdAt < b.createdAt) { return 1 }
+
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
+ case SORT_BY_VALUES.EarliestCreatedFirst: {
+ if (a.createdAt < b.createdAt) { return -1 }
+ if (a.createdAt > b.createdAt) { return 1 }
+
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
+ case SORT_BY_VALUES.LatestUpdatedFirst: {
+ if (a.lastUpdatedAt > b.lastUpdatedAt) { return -1 }
+ if (a.lastUpdatedAt < b.lastUpdatedAt) { return 1 }
- return a.playlistName.localeCompare(b.playlistName, this.locale)
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
+ case SORT_BY_VALUES.EarliestUpdatedFirst: {
+ if (a.lastUpdatedAt < b.lastUpdatedAt) { return -1 }
+ if (a.lastUpdatedAt > b.lastUpdatedAt) { return 1 }
+
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
+ default:
+ console.error(`Unknown sortBy: ${this.sortBy}`)
+ return 0
+ }
})
},
allPlaylistsLength() {
@@ -87,7 +136,14 @@ export default Vue.extend({
tabindex() {
return this.interactionsLocked ? -1 : 0
- }
+ },
+
+ sortBySelectNames() {
+ return Object.keys(SORT_BY_VALUES).map(k => SORT_BY_NAMES[k])
+ },
+ sortBySelectValues() {
+ return Object.values(SORT_BY_VALUES)
+ },
},
watch: {
allPlaylistsLength(val, oldVal) {
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
index 89dff08a90015..7698bf7d968fe 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
@@ -29,3 +29,8 @@
right: $horizontal-margin;
width: 100% - ($horizontal-margin * 2);
}
+
+.sortSelect {
+ /* Put it on the right */
+ margin-left: auto;
+}
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 501459a057b2d..e98680dec6707 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -9,7 +9,7 @@
{{ selectedPlaylistCount }} Selected
updateQueryDebounce(input)"
@clear="updateQueryDebounce('')"
/>
+
Date: Tue, 29 Aug 2023 15:29:22 +0800
Subject: [PATCH 139/236] $ Remove unused classname
---
src/renderer/components/ft-list-video/ft-list-video.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 08f51bf1c0770..90674512eace5 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -51,7 +51,7 @@
v-if="showPlaylists"
title="Add to playlist"
:icon="['fas', 'plus']"
- class="playlistIcon addToPlaylistIcon"
+ class="addToPlaylistIcon"
:class="alwaysShowAddToPlaylistButton ? 'alwaysVisible' : ''"
:padding="appearance === `watchPlaylistItem` ? 5 : 6"
:size="appearance === `watchPlaylistItem` ? 14 : 18"
From 454763fd10d428173a6c9c2150f82a6edc543e40 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 29 Aug 2023 15:51:59 +0800
Subject: [PATCH 140/236] ! Ensure new playlist button focused after add to
playlist prompt closed while thumbnail link unselectable
---
.../components/ft-list-video/ft-list-video.js | 2 +-
.../components/ft-list-video/ft-list-video.vue | 4 ++--
src/renderer/scss-partials/_ft-list-item.scss | 14 --------------
3 files changed, 3 insertions(+), 17 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 27e7dc8759654..2bcbddba584fd 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -646,7 +646,7 @@ export default defineComponent({
// `thumbnailLink` is a `router-link`
// `focus()` can only be called on the actual element
- this.$refs.thumbnailLink.$el.focus()
+ this.$refs.addToPlaylistIcon?.$el?.focus()
}
},
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 90674512eace5..79e5dbc022a9d 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -12,9 +12,8 @@
class="videoThumbnail"
>
Date: Wed, 30 Aug 2023 10:46:47 +0800
Subject: [PATCH 141/236] * Add playlists sort order for last played at, update
it on play
---
.../components/data-settings/data-settings.js | 1 +
src/renderer/store/modules/playlists.js | 13 ++++++++
.../views/UserPlaylists/UserPlaylists.js | 33 ++++++++++++++++++-
src/renderer/views/Watch/Watch.js | 11 ++++++-
4 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index 2bc28640d55ac..7da43caa521f3 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -885,6 +885,7 @@ export default defineComponent({
'type',
'protected',
'lastUpdatedAt',
+ 'lastPlayedAt',
'removeOnWatched',
'thumbnail',
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index e483892d30e59..17101e5e9b6b7 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -113,6 +113,19 @@ const actions = {
}
},
+ async updatePlaylistLastPlayedAt({ commit }, playlist) {
+ // This action does NOT update `lastUpdatedAt` on purpose
+ // Only `lastPlayedAt` should be updated
+ playlist.lastPlayedAt = Date.now()
+
+ try {
+ await DBPlaylistHandlers.upsert(playlist)
+ commit('upsertPlaylistToList', playlist)
+ } catch (errMessage) {
+ console.error(errMessage)
+ }
+ },
+
async addVideo({ commit }, payload) {
try {
const { _id, videoData } = payload
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index c7f1ace3319d1..5cb7e50eab67e 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -20,6 +20,9 @@ const SORT_BY_VALUES = {
LatestUpdatedFirst: 'latest_updated_first',
EarliestUpdatedFirst: 'earliest_updated_first',
+
+ LatestPlayedFirst: 'latest_played_first',
+ EarliestPlayedFirst: 'earliest_played_first',
}
const SORT_BY_NAMES = {
NameAscending: 'A-Z',
@@ -30,6 +33,9 @@ const SORT_BY_NAMES = {
LatestUpdatedFirst: 'Recently Updated',
EarliestUpdatedFirst: 'Earliest Updated',
+
+ LatestPlayedFirst: 'Recently Played',
+ EarliestPlayedFirst: 'Earliest Played',
}
export default defineComponent({
@@ -53,7 +59,7 @@ export default defineComponent({
showLoadMoreButton: false,
query: '',
activeData: [],
- sortBy: SORT_BY_VALUES.LatestUpdatedFirst,
+ sortBy: SORT_BY_VALUES.LatestPlayedFirst,
}
},
computed: {
@@ -97,6 +103,31 @@ export default defineComponent({
return a.playlistName.localeCompare(b.playlistName, this.locale)
}
+ case SORT_BY_VALUES.LatestPlayedFirst: {
+ if (a.lastPlayedAt == null && b.lastPlayedAt == null) {
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
+ // Never played playlist = move to last
+ if (a.lastPlayedAt == null) { return 1 }
+ if (b.lastPlayedAt == null) { return -1 }
+ if (a.lastPlayedAt > b.lastPlayedAt) { return -1 }
+ if (a.lastPlayedAt < b.lastPlayedAt) { return 1 }
+
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
+ case SORT_BY_VALUES.EarliestPlayedFirst: {
+ // Never played playlist = first
+ if (a.lastPlayedAt == null && b.lastPlayedAt == null) {
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
+ // Never played playlist = move to first
+ if (a.lastPlayedAt == null) { return -1 }
+ if (b.lastPlayedAt == null) { return 1 }
+ if (a.lastPlayedAt < b.lastPlayedAt) { return -1 }
+ if (a.lastPlayedAt > b.lastPlayedAt) { return 1 }
+
+ return a.playlistName.localeCompare(b.playlistName, this.locale)
+ }
default:
console.error(`Unknown sortBy: ${this.sortBy}`)
return 0
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index e11ae301bc9ec..1325633b9c1a3 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -1045,6 +1045,7 @@ export default defineComponent({
handleVideoReady: function () {
this.videoPlayerReady = true
this.checkIfWatched()
+ this.updateLocalPlaylistLastPlayedAtSometimes()
},
checkIfWatched: function () {
@@ -1601,11 +1602,19 @@ export default defineComponent({
document.title = `${this.videoTitle} - FreeTube`
},
+ updateLocalPlaylistLastPlayedAtSometimes() {
+ if (this.selectedUserPlaylist == null) { return }
+
+ const playlist = this.selectedUserPlaylist
+ this.updatePlaylistLastPlayedAt({ _id: playlist._id })
+ },
+
...mapActions([
'updateHistory',
'updateWatchProgress',
'updateLastViewedPlaylist',
- 'updateSubscriptionDetails'
+ 'updatePlaylistLastPlayedAt',
+ 'updateSubscriptionDetails',
])
}
})
From 762ab3333552418d1df2385f3853f63e569fe333 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 5 Sep 2023 09:03:55 +0800
Subject: [PATCH 142/236] ! Fix bug introduced by last merge
---
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 4507a7a239841..8289ecbe51bc3 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -147,7 +147,7 @@ export default defineComponent({
baseUrl = this.currentInvidiousInstance
} else if (typeof this.playlistThumbnail === 'string' && this.playlistThumbnail.length > 0) {
// Use playlist thumbnail provided by YT when available
- return this.data.playlistThumbnail
+ return this.playlistThumbnail
}
switch (this.thumbnailPreference) {
From 4b2ba552f6b06510cc912a118bcab40cdf916b0d Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 5 Sep 2023 09:27:52 +0800
Subject: [PATCH 143/236] ! Fix thumbnail not respecting backend preference
---
.../ft-list-playlist/ft-list-playlist.js | 27 +++++++++++--------
.../ft-playlist-selector.js | 14 +++++++---
2 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.js b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
index 9c92ea3e7b8ea..654e5c97b9dd2 100644
--- a/src/renderer/components/ft-list-playlist/ft-list-playlist.js
+++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
@@ -22,12 +22,15 @@ export default defineComponent({
playlistId: '',
channelId: '',
title: 'Pop Music Playlist - Timeless Pop Songs (Updated Weekly 2020)',
- thumbnail: 'https://i.ytimg.com/vi/JGwWNGJdvx8/mqdefault.jpg',
+ thumbnail: require('../../assets/img/thumbnail_placeholder.svg'),
channelName: '#RedMusic: Just Hits',
videoCount: 200,
}
},
computed: {
+ backendPreference: function () {
+ return this.$store.getters.getBackendPreference
+ },
currentInvidiousInstance: function () {
return this.$store.getters.getCurrentInvidiousInstance
},
@@ -62,6 +65,9 @@ export default defineComponent({
thumbnailPreference: function () {
return this.$store.getters.getThumbnailPreference
},
+ thumbnailCanBeShown() {
+ return this.thumbnailPreference !== 'hidden'
+ },
},
created: function () {
if (this.data._id != null) {
@@ -88,9 +94,7 @@ export default defineComponent({
parseInvidiousData: function () {
this.title = this.data.title
- if (this.thumbnailPreference === 'hidden') {
- this.thumbnail = require('../../assets/img/thumbnail_placeholder.svg')
- } else {
+ if (this.thumbnailCanBeShown) {
this.thumbnail = this.data.playlistThumbnail.replace('https://i.ytimg.com', this.currentInvidiousInstance).replace('hqdefault', 'mqdefault')
}
this.channelName = this.data.author
@@ -105,9 +109,7 @@ export default defineComponent({
parseLocalData: function () {
this.title = this.data.title
- if (this.thumbnailPreference === 'hidden') {
- this.thumbnail = require('../../assets/img/thumbnail_placeholder.svg')
- } else {
+ if (this.thumbnailCanBeShown) {
this.thumbnail = this.data.thumbnail
}
this.channelName = this.data.channelName
@@ -118,10 +120,13 @@ export default defineComponent({
parseUserData: function () {
this.title = this.data.playlistName
- if (this.thumbnailPreference === 'hidden' || this.data.videos.length === 0) {
- this.thumbnail = require('../../assets/img/thumbnail_placeholder.svg')
- } else {
- this.thumbnail = `https://i.ytimg.com/vi/${this.data.videos[0].videoId}/mqdefault.jpg`
+ if (this.thumbnailCanBeShown && this.data.videos.length > 0) {
+ const thumbnailURL = `https://i.ytimg.com/vi/${this.data.videos[0].videoId}/mqdefault.jpg`
+ if (this.backendPreference === 'invidious') {
+ this.thumbnail = thumbnailURL.replace('https://i.ytimg.com', this.currentInvidiousInstance)
+ } else {
+ this.thumbnail = thumbnailURL
+ }
}
this.channelName = ''
this.channelId = ''
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
index 4de8884c5aca1..e865056593e9f 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
@@ -28,11 +28,14 @@ export default Vue.extend({
data: function () {
return {
title: '',
- thumbnail: '',
+ thumbnail: require('../../assets/img/thumbnail_placeholder.svg'),
videoCount: 0,
}
},
computed: {
+ backendPreference: function () {
+ return this.$store.getters.getBackendPreference
+ },
currentInvidiousInstance: function () {
return this.$store.getters.getCurrentInvidiousInstance
},
@@ -51,9 +54,12 @@ export default Vue.extend({
parseUserData: function () {
this.title = this.data.playlistName
if (this.data.videos.length > 0) {
- this.thumbnail = `https://i.ytimg.com/vi/${this.data.videos[0].videoId}/mqdefault.jpg`
- } else {
- this.thumbnail = 'https://i.ytimg.com/vi/aaaaaa/mqdefault.jpg'
+ const thumbnailURL = `https://i.ytimg.com/vi/${this.data.videos[0].videoId}/mqdefault.jpg`
+ if (this.backendPreference === 'invidious') {
+ this.thumbnail = thumbnailURL.replace('https://i.ytimg.com', this.currentInvidiousInstance)
+ } else {
+ this.thumbnail = thumbnailURL
+ }
}
this.videoCount = this.data.videos.length
},
From e0348a2758e503a1d7f9d772499b9a1f7c71bbf2 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 5 Sep 2023 10:57:37 +0800
Subject: [PATCH 144/236] ! Fix empty playlist thumbnail in single playlist
view
---
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 8289ecbe51bc3..a9a3d147a46a0 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -138,7 +138,7 @@ export default defineComponent({
},
thumbnail: function () {
- if (this.thumbnailPreference === 'hidden') {
+ if (this.thumbnailPreference === 'hidden' || this.firstVideoId === '') {
return require('../../assets/img/thumbnail_placeholder.svg')
}
From ca9816aec7cf589776ae67ec8d5c7c81602d03ac Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 6 Sep 2023 10:03:22 +0800
Subject: [PATCH 145/236] * Make adding large no. of videos faster
---
src/constants.js | 1 +
src/datastores/handlers/base.js | 8 ++++++++
src/datastores/handlers/electron.js | 10 ++++++++++
src/datastores/handlers/web.js | 4 ++++
src/main/index.js | 9 +++++++++
.../ft-playlist-add-video-prompt.js | 14 ++++++--------
src/renderer/store/modules/playlists.js | 8 ++++----
src/renderer/store/modules/settings.js | 4 ++++
8 files changed, 46 insertions(+), 12 deletions(-)
diff --git a/src/constants.js b/src/constants.js
index 4693d857623fd..bb04ec0a365e9 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -44,6 +44,7 @@ const DBActions = {
PLAYLISTS: {
UPSERT_VIDEO: 'db-action-playlists-upsert-video-by-playlist-name',
+ UPSERT_VIDEOS: 'db-action-playlists-upsert-videos-by-playlist-name',
UPSERT_VIDEO_IDS: 'db-action-playlists-upsert-video-ids-by-playlist-id',
DELETE_VIDEO_ID: 'db-action-playlists-delete-video-by-playlist-name',
DELETE_VIDEO_IDS: 'db-action-playlists-delete-video-ids',
diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js
index e7b0eacb2caba..3a144fe038309 100644
--- a/src/datastores/handlers/base.js
+++ b/src/datastores/handlers/base.js
@@ -124,6 +124,14 @@ class Playlists {
)
}
+ static upsertVideosByPlaylistId(_id, videos) {
+ return db.playlists.updateAsync(
+ { _id },
+ { $push: { videos: { $each: videos } } },
+ { upsert: true }
+ )
+ }
+
static upsertVideoIdsByPlaylistId(_id, videoIds) {
return db.playlists.updateAsync(
{ _id },
diff --git a/src/datastores/handlers/electron.js b/src/datastores/handlers/electron.js
index ca1d2ee8552f7..196429cbc86e4 100644
--- a/src/datastores/handlers/electron.js
+++ b/src/datastores/handlers/electron.js
@@ -143,6 +143,16 @@ class Playlists {
)
}
+ static upsertVideosByPlaylistId(_id, videos) {
+ return ipcRenderer.invoke(
+ IpcChannels.DB_PLAYLISTS,
+ {
+ action: DBActions.PLAYLISTS.UPSERT_VIDEOS,
+ data: { _id, videos }
+ }
+ )
+ }
+
static upsertVideoIdsByPlaylistId(_id, videoIds) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
diff --git a/src/datastores/handlers/web.js b/src/datastores/handlers/web.js
index 2d51842db0bb3..fc34ffefb0f6d 100644
--- a/src/datastores/handlers/web.js
+++ b/src/datastores/handlers/web.js
@@ -89,6 +89,10 @@ class Playlists {
return baseHandlers.playlists.upsertVideoByPlaylistId(_id, videoData)
}
+ static upsertVideosByPlaylistId(_id, videoData) {
+ return baseHandlers.playlists.upsertVideosByPlaylistId(_id, videoData)
+ }
+
static upsertVideoIdsByPlaylistId(_id, videoIds) {
return baseHandlers.playlists.upsertVideoIdsByPlaylistId(_id, videoIds)
}
diff --git a/src/main/index.js b/src/main/index.js
index f1958642caa73..54e5f1c747d81 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -971,6 +971,15 @@ function runApp() {
)
return null
+ case DBActions.PLAYLISTS.UPSERT_VIDEOS:
+ await baseHandlers.playlists.upsertVideosByPlaylistId(data._id, data.videos)
+ syncOtherWindows(
+ IpcChannels.SYNC_PLAYLISTS,
+ event,
+ { event: SyncEvents.PLAYLISTS.UPSERT_VIDEOS, data }
+ )
+ return null
+
case DBActions.PLAYLISTS.UPSERT_VIDEO_IDS:
await baseHandlers.playlists.upsertVideoIdsByPlaylistId(data._id, data.videoIds)
// TODO: Syncing (implement only when it starts being used)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 8fd09680ac52d..3dd7b8e842568 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -218,15 +218,12 @@ export default Vue.extend({
const playlist = this.allPlaylists.find((list) => list._id === selectedPlaylistId)
if (playlist == null) { return }
- this.toBeAddedToPlaylistVideoList.forEach((videoObject) => {
- const payload = {
- _id: playlist._id,
- // Avoid `do not mutate vuex store state outside mutation handlers`
- videoData: videoObject,
- }
- this.addVideo(payload)
- addedPlaylistIds.add(playlist._id)
+ this.addVideos({
+ _id: playlist._id,
+ // Use [].concat to avoid `do not mutate vuex store state outside mutation handlers`
+ videos: [].concat(this.toBeAddedToPlaylistVideoList),
})
+ addedPlaylistIds.add(playlist._id)
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: playlist._id })
})
@@ -255,6 +252,7 @@ export default Vue.extend({
...mapActions([
'addVideo',
+ 'addVideos',
'updatePlaylist',
'hideAddToPlaylistPrompt',
'showCreatePlaylistPrompt',
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 17101e5e9b6b7..92d2368d53d1b 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -144,8 +144,8 @@ const actions = {
async addVideos({ commit }, payload) {
try {
- const { playlistId, videoIds } = payload
- await DBPlaylistHandlers.upsertVideoIdsByPlaylistId(playlistId, videoIds)
+ const { _id, videos } = payload
+ await DBPlaylistHandlers.upsertVideosByPlaylistId(_id, videos)
commit('addVideos', payload)
} catch (errMessage) {
console.error(errMessage)
@@ -351,9 +351,9 @@ const mutations = {
},
addVideos(state, payload) {
- const playlist = state.playlists.find(playlist => playlist._id === payload.playlistId)
+ const playlist = state.playlists.find(playlist => playlist._id === payload._id)
if (playlist) {
- playlist.videos = playlist.videos.concat(payload.playlistIds)
+ playlist.videos = playlist.videos.concat(payload.videos)
}
},
diff --git a/src/renderer/store/modules/settings.js b/src/renderer/store/modules/settings.js
index 036933a846508..c353e07e92c24 100644
--- a/src/renderer/store/modules/settings.js
+++ b/src/renderer/store/modules/settings.js
@@ -514,6 +514,10 @@ const customActions = {
commit('addVideo', data)
break
+ case SyncEvents.PLAYLISTS.UPSERT_VIDEOS:
+ commit('addVideos', data)
+ break
+
case SyncEvents.PLAYLISTS.DELETE_VIDEO:
commit('removeVideo', data)
break
From 336c052ff10b567a98627a29d2a43812adc1003c Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 6 Sep 2023 10:05:29 +0800
Subject: [PATCH 146/236] $ Remove unused mapActions entries
---
src/renderer/components/ft-list-video/ft-list-video.js | 1 -
.../ft-playlist-add-video-prompt.js | 1 -
src/renderer/components/watch-video-info/watch-video-info.js | 2 --
3 files changed, 4 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 6fcd5d9bbce05..f3691787a3f7b 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -664,7 +664,6 @@ export default defineComponent({
'openInExternalPlayer',
'updateHistory',
'removeFromHistory',
- 'addVideo',
'showAddToPlaylistPromptForManyVideos',
])
}
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 3dd7b8e842568..6cdb0ee3edffb 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -251,7 +251,6 @@ export default Vue.extend({
},
...mapActions([
- 'addVideo',
'addVideos',
'updatePlaylist',
'hideAddToPlaylistPrompt',
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index 82c48b0ee8765..d434e57b9f8b3 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -315,8 +315,6 @@ export default defineComponent({
...mapActions([
'openInExternalPlayer',
- 'addVideo',
- 'removeVideo',
'downloadMedia',
'showAddToPlaylistPromptForManyVideos',
])
From ca0ac8ec43f13cb9d0522fc687e39e87e1d31914 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 6 Sep 2023 15:47:17 +0800
Subject: [PATCH 147/236] $ Remove unused and unusable playlist code for
inserting video IDs into a playlist
---
src/constants.js | 1 -
src/datastores/handlers/base.js | 8 --------
src/datastores/handlers/electron.js | 10 ----------
src/datastores/handlers/web.js | 4 ----
src/main/index.js | 6 ------
5 files changed, 29 deletions(-)
diff --git a/src/constants.js b/src/constants.js
index bb04ec0a365e9..92e7b19949b4b 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -45,7 +45,6 @@ const DBActions = {
PLAYLISTS: {
UPSERT_VIDEO: 'db-action-playlists-upsert-video-by-playlist-name',
UPSERT_VIDEOS: 'db-action-playlists-upsert-videos-by-playlist-name',
- UPSERT_VIDEO_IDS: 'db-action-playlists-upsert-video-ids-by-playlist-id',
DELETE_VIDEO_ID: 'db-action-playlists-delete-video-by-playlist-name',
DELETE_VIDEO_IDS: 'db-action-playlists-delete-video-ids',
DELETE_ALL_VIDEOS: 'db-action-playlists-delete-all-videos'
diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js
index 3a144fe038309..cb9f419152afb 100644
--- a/src/datastores/handlers/base.js
+++ b/src/datastores/handlers/base.js
@@ -132,14 +132,6 @@ class Playlists {
)
}
- static upsertVideoIdsByPlaylistId(_id, videoIds) {
- return db.playlists.updateAsync(
- { _id },
- { $push: { videos: { $each: videoIds } } },
- { upsert: true }
- )
- }
-
static delete(_id) {
return db.playlists.removeAsync({ _id, protected: { $ne: true } })
}
diff --git a/src/datastores/handlers/electron.js b/src/datastores/handlers/electron.js
index 196429cbc86e4..2dc5f7d3896f7 100644
--- a/src/datastores/handlers/electron.js
+++ b/src/datastores/handlers/electron.js
@@ -153,16 +153,6 @@ class Playlists {
)
}
- static upsertVideoIdsByPlaylistId(_id, videoIds) {
- return ipcRenderer.invoke(
- IpcChannels.DB_PLAYLISTS,
- {
- action: DBActions.PLAYLISTS.UPSERT_VIDEO_IDS,
- data: { _id, videoIds }
- }
- )
- }
-
static delete(_id) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
diff --git a/src/datastores/handlers/web.js b/src/datastores/handlers/web.js
index fc34ffefb0f6d..a300335f4b236 100644
--- a/src/datastores/handlers/web.js
+++ b/src/datastores/handlers/web.js
@@ -93,10 +93,6 @@ class Playlists {
return baseHandlers.playlists.upsertVideosByPlaylistId(_id, videoData)
}
- static upsertVideoIdsByPlaylistId(_id, videoIds) {
- return baseHandlers.playlists.upsertVideoIdsByPlaylistId(_id, videoIds)
- }
-
static delete(_id) {
return baseHandlers.playlists.delete(_id)
}
diff --git a/src/main/index.js b/src/main/index.js
index 54e5f1c747d81..a469578e21e8d 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -980,12 +980,6 @@ function runApp() {
)
return null
- case DBActions.PLAYLISTS.UPSERT_VIDEO_IDS:
- await baseHandlers.playlists.upsertVideoIdsByPlaylistId(data._id, data.videoIds)
- // TODO: Syncing (implement only when it starts being used)
- // syncOtherWindows(IpcChannels.SYNC_PLAYLISTS, event, { event: '_', data })
- return null
-
case DBActions.GENERAL.DELETE:
await baseHandlers.playlists.delete(data)
syncOtherWindows(
From 6aa8e3d81a6721d519593e18cda01ea6146b54c3 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 7 Sep 2023 10:08:27 +0800
Subject: [PATCH 148/236] * Update single playlist view to only show `Remove
watched videos` btn when there is any video
---
src/renderer/components/playlist-info/playlist-info.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index d70630f923433..1d59be84e3f42 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -126,7 +126,7 @@
@click="toggleCopyVideosPrompt"
/>
Date: Thu, 7 Sep 2023 10:32:07 +0800
Subject: [PATCH 149/236] ! Fix prompt style issue caused by old branch changes
---
src/renderer/components/ft-prompt/ft-prompt.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/ft-prompt/ft-prompt.css b/src/renderer/components/ft-prompt/ft-prompt.css
index 0c2cd194cb42a..def0f84c67313 100644
--- a/src/renderer/components/ft-prompt/ft-prompt.css
+++ b/src/renderer/components/ft-prompt/ft-prompt.css
@@ -21,7 +21,7 @@
}
.promptCard:not(.autosize) {
- width: 100%;
+ width: 95%;
margin: 0;
position: absolute;
left: 2.5%;
From d6439b62b5670a555ecc70cdac40e98d312dfcf2 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 12 Sep 2023 09:50:40 +0800
Subject: [PATCH 150/236] ! Fix removing video from local playlist remove all
entries with same video ID
---
src/datastores/handlers/base.js | 4 ++--
src/datastores/handlers/electron.js | 4 ++--
src/datastores/handlers/web.js | 4 ++--
src/main/index.js | 2 +-
src/renderer/store/modules/playlists.js | 4 ++--
src/renderer/views/Playlist/Playlist.js | 12 +++++-------
6 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js
index cb9f419152afb..f875b57b3d943 100644
--- a/src/datastores/handlers/base.js
+++ b/src/datastores/handlers/base.js
@@ -136,10 +136,10 @@ class Playlists {
return db.playlists.removeAsync({ _id, protected: { $ne: true } })
}
- static deleteVideoIdByPlaylistId(_id, videoId) {
+ static deleteVideoIdByPlaylistId(_id, uniqueId) {
return db.playlists.updateAsync(
{ _id },
- { $pull: { videos: { videoId } } },
+ { $pull: { videos: { uniqueId } } },
{ upsert: true }
)
}
diff --git a/src/datastores/handlers/electron.js b/src/datastores/handlers/electron.js
index 2dc5f7d3896f7..aea0c0376746b 100644
--- a/src/datastores/handlers/electron.js
+++ b/src/datastores/handlers/electron.js
@@ -160,12 +160,12 @@ class Playlists {
)
}
- static deleteVideoIdByPlaylistId(_id, videoId) {
+ static deleteVideoIdByPlaylistId(_id, uniqueId) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
{
action: DBActions.PLAYLISTS.DELETE_VIDEO_ID,
- data: { _id, videoId }
+ data: { _id, uniqueId }
}
)
}
diff --git a/src/datastores/handlers/web.js b/src/datastores/handlers/web.js
index a300335f4b236..bb74f7160c09c 100644
--- a/src/datastores/handlers/web.js
+++ b/src/datastores/handlers/web.js
@@ -97,8 +97,8 @@ class Playlists {
return baseHandlers.playlists.delete(_id)
}
- static deleteVideoIdByPlaylistId(_id, videoId) {
- return baseHandlers.playlists.deleteVideoIdByPlaylistId(_id, videoId)
+ static deleteVideoIdByPlaylistId(_id, uniqueId) {
+ return baseHandlers.playlists.deleteVideoIdByPlaylistId(_id, uniqueId)
}
static deleteVideoIdsByPlaylistId(_id, videoIds) {
diff --git a/src/main/index.js b/src/main/index.js
index 26866b694d8d2..a99768d35dfaf 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -994,7 +994,7 @@ function runApp() {
return null
case DBActions.PLAYLISTS.DELETE_VIDEO_ID:
- await baseHandlers.playlists.deleteVideoIdByPlaylistId(data._id, data.videoId)
+ await baseHandlers.playlists.deleteVideoIdByPlaylistId(data._id, data.uniqueId)
syncOtherWindows(
IpcChannels.SYNC_PLAYLISTS,
event,
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 92d2368d53d1b..e5393fbeceb66 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -302,8 +302,8 @@ const actions = {
async removeVideo({ commit }, payload) {
try {
- const { _id, videoId } = payload
- await DBPlaylistHandlers.deleteVideoIdByPlaylistId(_id, videoId)
+ const { _id, uniqueId } = payload
+ await DBPlaylistHandlers.deleteVideoIdByPlaylistId(_id, uniqueId)
commit('removeVideo', payload)
} catch (errMessage) {
console.error(errMessage)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 7045e4270e98e..1090dacbfbdda 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -378,14 +378,12 @@ export default defineComponent({
},
removeVideoFromPlaylist: function (videoId, uniqueId) {
- const payload = {
- _id: this.playlistId,
- videoId: videoId,
- uniqueId: uniqueId,
- }
-
try {
- this.removeVideo(payload)
+ this.removeVideo({
+ _id: this.playlistId,
+ videoId: videoId,
+ uniqueId: uniqueId,
+ })
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: this.playlistId })
showToast('Video has been removed')
From 2462099f345ee57e34a0b298539429c8a533722a Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 12 Sep 2023 11:02:17 +0800
Subject: [PATCH 151/236] ! Fix adding video does not have uniqueID & timeAdded
set
Caused by previous add many video performance fix
---
src/renderer/store/modules/playlists.js | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index e5393fbeceb66..e51aa2c8906be 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -145,6 +145,14 @@ const actions = {
async addVideos({ commit }, payload) {
try {
const { _id, videos } = payload
+ videos.forEach((videoData) => {
+ if (videoData.timeAdded == null) {
+ videoData.timeAdded = new Date().getTime()
+ }
+ if (videoData.uniqueId == null) {
+ videoData.uniqueId = generateRandomUniqueId()
+ }
+ })
await DBPlaylistHandlers.upsertVideosByPlaylistId(_id, videos)
commit('addVideos', payload)
} catch (errMessage) {
From 6e7a627902847a6a242b0740565960a83100e007 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 12 Sep 2023 11:06:27 +0800
Subject: [PATCH 152/236] ! Fix navigation in user playlist between entries of
same video
---
.../ft-list-video-lazy/ft-list-video-lazy.js | 4 ++++
.../ft-list-video-lazy/ft-list-video-lazy.vue | 1 +
src/renderer/components/ft-list-video/ft-list-video.js | 10 +++++++++-
src/renderer/components/playlist-info/playlist-info.js | 4 ++++
.../components/playlist-info/playlist-info.vue | 5 ++++-
.../watch-video-playlist/watch-video-playlist.vue | 1 +
src/renderer/store/modules/playlists.js | 2 +-
src/renderer/views/Playlist/Playlist.js | 3 +++
src/renderer/views/Playlist/Playlist.vue | 2 ++
src/renderer/views/Watch/Watch.js | 2 ++
src/renderer/views/Watch/Watch.vue | 1 +
11 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
index 97737e85dd05e..a7a7d71f9922a 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
@@ -35,6 +35,10 @@ export default defineComponent({
type: Boolean,
default: false
},
+ uniqueId: {
+ type: String,
+ default: null,
+ },
forceListType: {
type: String,
default: null
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
index cf1de46d116af..bdb98bbf0ce83 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
@@ -14,6 +14,7 @@
:playlist-reverse="playlistReverse"
:playlist-shuffle="playlistShuffle"
:playlist-loop="playlistLoop"
+ :unique-id="uniqueId"
:force-list-type="forceListType"
:appearance="appearance"
:always-show-add-to-playlist-button="alwaysShowAddToPlaylistButton"
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 f3691787a3f7b..eb7ecca0350e6 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -30,6 +30,10 @@ export default defineComponent({
type: String,
default: null
},
+ uniqueId: {
+ type: String,
+ default: null
+ },
playlistIndex: {
type: Number,
default: null
@@ -348,6 +352,7 @@ export default defineComponent({
return {
playlistId: this.playlistId,
playlistType: null,
+ uniqueId: this.uniqueId,
}
}
@@ -368,15 +373,18 @@ export default defineComponent({
playlistIdFinal: function () {
return this.playlistIdTypePairFinal?.playlistId
},
-
playlistTypeFinal: function () {
return this.playlistIdTypePairFinal?.playlistType
},
+ uniqueIdFinal: function () {
+ return this.playlistIdTypePairFinal?.uniqueId
+ },
watchPageLinkQuery() {
const query = {}
if (this.playlistIdFinal) { query.playlistId = this.playlistIdFinal }
if (this.playlistTypeFinal) { query.playlistType = this.playlistTypeFinal }
+ if (this.uniqueIdFinal) { query.uniqueId = this.uniqueIdFinal }
return query
},
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index a9a3d147a46a0..04d45af5f1b90 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -27,6 +27,10 @@ export default defineComponent({
type: String,
required: true,
},
+ firstVideoUniqueId: {
+ type: String,
+ required: true,
+ },
playlistThumbnail: {
type: String,
required: true,
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 1d59be84e3f42..21e7e421dbb2c 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -6,7 +6,10 @@
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
index 021cdb552ed77..33be27cad532f 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
@@ -139,6 +139,7 @@
:playlist-reverse="reversePlaylist"
:playlist-shuffle="shuffleEnabled"
:playlist-loop="loopEnabled"
+ :unique-id="item.uniqueId"
appearance="watchPlaylistItem"
force-list-type="list"
:initial-visible-state="index < ((currentVideoIndex - 1) + 4) && index > ((currentVideoIndex - 1) - 4)"
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index e51aa2c8906be..5dc27963715dc 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -379,7 +379,7 @@ const mutations = {
removeVideo(state, payload) {
const playlist = state.playlists.find(playlist => playlist._id === payload._id)
if (playlist) {
- playlist.videos = playlist.videos.filter(video => video.videoId !== payload.videoId || video.uniqueId !== payload.uniqueId)
+ playlist.videos = playlist.videos.filter(video => video.uniqueId !== payload.uniqueId)
}
},
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 1090dacbfbdda..d6f3a1881129a 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -40,6 +40,7 @@ export default defineComponent({
playlistTitle: '',
playlistDescription: '',
firstVideoId: '',
+ firstVideoUniqueId: '',
playlistThumbnail: '',
viewCount: 0,
videoCount: 0,
@@ -268,8 +269,10 @@ export default defineComponent({
if (playlist.videos.length > 0) {
this.firstVideoId = playlist.videos[0].videoId
+ this.firstVideoUniqueId = playlist.videos[0].uniqueId
} else {
this.firstVideoId = ''
+ this.firstVideoUniqueId = ''
}
this.viewCount = 0
this.videoCount = playlist.videos.length
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index fe5fc301d42f9..d94852bc73dd9 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -9,6 +9,7 @@
v-if="!isLoading"
:id="playlistId"
:first-video-id="firstVideoId"
+ :first-video-unique-id="firstVideoUniqueId"
:playlist-thumbnail="playlistThumbnail"
:title="playlistTitle"
:channel-name="channelName"
@@ -52,6 +53,7 @@
:playlist-id="playlistId"
:playlist-type="infoSource"
:playlist-index="index"
+ :unique-id="item.uniqueId"
appearance="result"
force-list-type="list"
:always-show-add-to-playlist-button="true"
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index a267363513163..7217081d29c2e 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -116,6 +116,7 @@ export default defineComponent({
watchingPlaylist: false,
playlistId: '',
playlistType: '',
+ uniqueId: null,
timestamp: null,
playNextTimeout: null,
playNextCountDownIntervalId: null,
@@ -1098,6 +1099,7 @@ export default defineComponent({
}
this.playlistId = this.$route.query.playlistId
+ this.uniqueId = this.$route.query.uniqueId
if (this.playlistId == null || this.playlistId.length === 0) {
this.playlistType = ''
diff --git a/src/renderer/views/Watch/Watch.vue b/src/renderer/views/Watch/Watch.vue
index 7fafe72915510..21dba1c046e0e 100644
--- a/src/renderer/views/Watch/Watch.vue
+++ b/src/renderer/views/Watch/Watch.vue
@@ -173,6 +173,7 @@
:watch-view-loading="isLoading"
:playlist-id="playlistId"
:video-id="videoId"
+ :unique-id="uniqueId"
class="watchVideoSideBar watchVideoPlaylist"
:class="{ theatrePlaylist: useTheatreMode }"
@pause-player="pausePlayer"
From 125a46741e46692ae3f2f03f45210fdd39375990 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 12 Sep 2023 11:35:25 +0800
Subject: [PATCH 153/236] * Reflect playlist updates on watch page playlist
panel
---
.../watch-video-playlist.js | 46 ++++++++++++++++---
.../watch-video-playlist.vue | 2 +-
2 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index 3f93c34a106c7..f785cb6358b06 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -17,15 +17,19 @@ export default defineComponent({
props: {
playlistId: {
type: String,
- required: true
+ required: true,
},
videoId: {
type: String,
- required: true
+ required: true,
+ },
+ uniqueId: {
+ type: String,
+ default: null,
},
watchViewLoading: {
type: Boolean,
- required: true
+ required: true,
},
},
data: function () {
@@ -60,10 +64,18 @@ export default defineComponent({
return this.$store.getters.getPlaylist(this.playlistId)
},
+ selectedUserPlaylistVideoCount () {
+ return this.selectedUserPlaylist?.videos?.length
+ },
+ selectedUserPlaylistLastUpdatedAt () {
+ return this.selectedUserPlaylist?.lastUpdatedAt
+ },
currentVideoIndex: function () {
const index = this.playlistItems.findIndex((item) => {
- if (typeof item.videoId !== 'undefined') {
+ if (item.uniqueId != null && this.uniqueId != null) {
+ return item.uniqueId === this.uniqueId
+ } else if (item.videoId != null) {
return item.videoId === this.videoId
} else {
return item.id === this.videoId
@@ -108,6 +120,18 @@ export default defineComponent({
userPlaylistsReady: function() {
this.getPlaylistInfoWithDelay()
},
+ selectedUserPlaylistVideoCount () {
+ // Re-fetch from local store when current user playlist updated
+ this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: false })
+ },
+ selectedUserPlaylistLastUpdatedAt () {
+ // Re-fetch from local store when current user playlist updated
+ this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: false })
+ },
+ uniqueId () {
+ // Re-fetch from local store when different item played
+ this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: true })
+ },
videoId: function (newId, oldId) {
// Check if next video is from the shuffled list or if the user clicked a different video
if (this.shuffleEnabled) {
@@ -431,14 +455,22 @@ export default defineComponent({
})
},
- parseUserPlaylist: function (playlist) {
+ parseUserPlaylist: function (playlist, { allowPlayingVideoRemoval = true } = {}) {
this.playlistTitle = playlist.playlistName
- this.videoCount = playlist.videoCount
this.channelName = ''
this.channelThumbnail = ''
this.channelId = ''
- this.playlistItems = playlist.videos
+ if (this.playlistItems.length === 0 || allowPlayingVideoRemoval) {
+ this.playlistItems = playlist.videos
+ } else {
+ // `this.currentVideo` relies on `playlistItems`
+ const latestPlaylistContainsCurrentVideo = playlist.videos.find(v => v.uniqueId === this.uniqueId) != null
+ // Only update list of videos if latest video list still contains currently playing video
+ if (latestPlaylistContainsCurrentVideo) {
+ this.playlistItems = playlist.videos
+ }
+ }
this.isLoading = false
},
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
index 33be27cad532f..9c9e195ad30ee 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
@@ -115,7 +115,7 @@
>
From 2884836402dc08ced6db55bf815c47af56255d7e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 12 Sep 2023 14:23:12 +0800
Subject: [PATCH 154/236] $- Remove outdated incorrect prompt style fix
---
.../ft-playlist-add-video-prompt.scss | 8 --------
1 file changed, 8 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
index 7698bf7d968fe..57fa8ae7cc30c 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
@@ -22,14 +22,6 @@
text-align: center;
}
-:deep(.promptCard:not(.autosize)) {
- /* Override some existing style */
- $horizontal-margin: 2.5%;
- left: $horizontal-margin;
- right: $horizontal-margin;
- width: 100% - ($horizontal-margin * 2);
-}
-
.sortSelect {
/* Put it on the right */
margin-left: auto;
From d7421c7f6a387a490cb122ba310425b39bce43f5 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 12 Sep 2023 14:52:44 +0800
Subject: [PATCH 155/236] ! Fix add video to playlist prompt too high when
there are too many playlists
---
.../ft-playlist-add-video-prompt.scss | 29 +++++++--
.../ft-playlist-add-video-prompt.vue | 64 ++++++++++---------
2 files changed, 57 insertions(+), 36 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
index 57fa8ae7cc30c..4cc629a8f59f5 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
@@ -12,17 +12,34 @@
along with FreeTube. If not, see .
*/
-/*
-* Credit goes to pavelvaravko for making this css.
-* https://codepen.io/pavelvaravko/pen/qjojOr
-*/
+.heading {
+ text-align: center;
+}
-/* select starting stylings ------------------------------*/
-.center {
+.selected-count {
text-align: center;
}
+// Style for `ft-prompt`
+:deep(.promptCard) {
+ // Currently only this prompt has enough content to make prompt too high
+ max-height: 95%;
+
+ // Some child(s) will grow vertically
+ display: flex;
+ flex-direction: column;
+}
+
.sortSelect {
/* Put it on the right */
margin-left: auto;
}
+
+.playlists-container {
+ box-shadow: inset 0 0 5px rgba(0,0,0,.5);
+
+ // Use remaining height
+ flex-grow: 1;
+
+ overflow-y: scroll;
+}
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index e98680dec6707..2a5c9662fccdb 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -2,10 +2,10 @@
-
+
Select a Playlist to add your {{ toBeAddedToPlaylistVideoCount }} video(s) to
-
+
{{ selectedPlaylistCount }} Selected
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
From 66e3dbe7ac3a0313d15adf6eb25464fcccd9536d Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 12 Sep 2023 15:46:20 +0800
Subject: [PATCH 156/236] ! Fix watch page play next/prev video in local
playlist
---
.../watch-video-playlist.js | 145 ++++++++----------
.../watch-video-playlist.vue | 10 +-
src/renderer/views/Watch/Watch.js | 4 +-
3 files changed, 75 insertions(+), 84 deletions(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index f785cb6358b06..ca5408afa4759 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -71,8 +71,8 @@ export default defineComponent({
return this.selectedUserPlaylist?.lastUpdatedAt
},
- currentVideoIndex: function () {
- const index = this.playlistItems.findIndex((item) => {
+ currentVideoIndexZeroBased: function () {
+ return this.playlistItems.findIndex((item) => {
if (item.uniqueId != null && this.uniqueId != null) {
return item.uniqueId === this.uniqueId
} else if (item.videoId != null) {
@@ -81,8 +81,12 @@ export default defineComponent({
return item.id === this.videoId
}
})
-
- return index + 1
+ },
+ currentVideoIndexOneBased: function () {
+ return this.currentVideoIndexZeroBased + 1
+ },
+ currentVideo: function () {
+ return this.playlistItems[this.currentVideoIndexZeroBased]
},
playlistVideoCount: function () {
@@ -105,15 +109,23 @@ export default defineComponent({
},
videoIndexInPlaylistItems: function () {
- if (this.shuffleEnabled) {
- return this.randomizedPlaylistItems.findIndex((item) => {
- return item === this.videoId
- })
- } else {
- return this.playlistItems.findIndex((item) => {
- return (item.id ?? item.videoId) === this.videoId
- })
- }
+ const playlistItems = this.shuffleEnabled ? this.randomizedPlaylistItems : this.playlistItems
+
+ return playlistItems.findIndex((item) => {
+ if (item.uniqueId != null && this.uniqueId != null) {
+ return item.uniqueId === this.uniqueId
+ } else if (item.videoId != null) {
+ return item.videoId === this.videoId
+ } else {
+ return item.id === this.videoId
+ }
+ })
+ },
+ videoIsFirstPlaylistItem: function () {
+ return this.videoIndexInPlaylistItems === 0
+ },
+ videoIsLastPlaylistItem: function () {
+ return this.videoIndexInPlaylistItems === (this.playlistItems.length - 1)
},
},
watch: {
@@ -136,11 +148,11 @@ export default defineComponent({
// Check if next video is from the shuffled list or if the user clicked a different video
if (this.shuffleEnabled) {
const newVideoIndex = this.randomizedPlaylistItems.findIndex((item) => {
- return item === newId
+ return item.videoId === newId
})
const oldVideoIndex = this.randomizedPlaylistItems.findIndex((item) => {
- return item === oldId
+ return item.videoId === oldId
})
if ((newVideoIndex - 1) !== oldVideoIndex) {
@@ -258,40 +270,32 @@ export default defineComponent({
}
if (this.shuffleEnabled) {
- const videoIndex = this.randomizedPlaylistItems.findIndex((item) => {
- return item === this.videoId
- })
+ const videoIndex = this.videoIndexInPlaylistItems
+ let doShufflePlaylistItems = false
+ if (this.videoIsLastPlaylistItem && !this.loopEnabled) {
+ showToast(this.$t('The playlist has ended. Enable loop to continue playing'))
+ return
+ }
+ // loopEnabled = true
+ if (this.videoIsLastPlaylistItem) { doShufflePlaylistItems = true }
+
+ const targetVideoIndex = this.videoIsLastPlaylistItem ? 0 : videoIndex + 1
+ const targetPlaylistItem = this.randomizedPlaylistItems[targetVideoIndex]
- if (videoIndex === this.randomizedPlaylistItems.length - 1) {
- if (this.loopEnabled) {
- this.$router.push(
- {
- path: `/watch/${this.randomizedPlaylistItems[0]}`,
- query: playlistInfo
- }
- )
- showToast(this.$t('Playing Next Video'))
- this.shufflePlaylistItems()
- } else {
- showToast(this.$t('The playlist has ended. Enable loop to continue playing'))
+ this.$router.push(
+ {
+ path: `/watch/${targetPlaylistItem.videoId}`,
+ query: Object.assign(playlistInfo, { uniqueId: targetPlaylistItem.uniqueId }),
}
- } else {
- this.$router.push(
- {
- path: `/watch/${this.randomizedPlaylistItems[videoIndex + 1]}`,
- query: playlistInfo
- }
- )
- showToast(this.$t('Playing Next Video'))
- }
+ )
+ showToast(this.$t('Playing Next Video'))
+ if (doShufflePlaylistItems) { this.shufflePlaylistItems() }
} else {
- const videoIndex = this.playlistItems.findIndex((item) => {
- return (item.id ?? item.videoId) === this.videoId
- })
- const targetVideoIndex = videoIndex === this.playlistItems.length - 1 ? 0 : videoIndex + 1
+ const videoIndex = this.videoIndexInPlaylistItems
+ const targetVideoIndex = this.videoIsLastPlaylistItem ? 0 : videoIndex + 1
const targetPlaylistItem = this.playlistItems[targetVideoIndex]
- const stopDueToLoopDisabled = videoIndex === this.playlistItems.length - 1 && !this.loopEnabled
+ const stopDueToLoopDisabled = this.videoIsLastPlaylistItem && !this.loopEnabled
if (stopDueToLoopDisabled) {
showToast(this.$t('The playlist has ended. Enable loop to continue playing'))
return
@@ -299,8 +303,8 @@ export default defineComponent({
this.$router.push(
{
- path: `/watch/${targetPlaylistItem.id ?? targetPlaylistItem.videoId}`,
- query: playlistInfo
+ path: `/watch/${targetPlaylistItem.videoId}`,
+ query: Object.assign(playlistInfo, { uniqueId: targetPlaylistItem.uniqueId }),
}
)
showToast(this.$t('Playing Next Video'))
@@ -315,36 +319,25 @@ export default defineComponent({
}
if (this.shuffleEnabled) {
- const videoIndex = this.randomizedPlaylistItems.findIndex((item) => {
- return item === this.videoId
- })
+ const videoIndex = this.videoIndexInPlaylistItems
+ const targetVideoIndex = this.videoIsFirstPlaylistItem ? this.randomizedPlaylistItems.length - 1 : videoIndex - 1
+ const targetPlaylistItem = this.randomizedPlaylistItems[targetVideoIndex]
- if (videoIndex === 0) {
- this.$router.push(
- {
- path: `/watch/${this.randomizedPlaylistItems[this.randomizedPlaylistItems.length - 1]}`,
- query: playlistInfo
- }
- )
- } else {
- this.$router.push(
- {
- path: `/watch/${this.randomizedPlaylistItems[videoIndex - 1]}`,
- query: playlistInfo
- }
- )
- }
+ this.$router.push(
+ {
+ path: `/watch/${targetPlaylistItem.videoId}`,
+ query: Object.assign(playlistInfo, { uniqueId: targetPlaylistItem.uniqueId }),
+ }
+ )
} else {
- const videoIndex = this.playlistItems.findIndex((item) => {
- return (item.id ?? item.videoId) === this.videoId
- })
- const targetVideoIndex = videoIndex === 0 ? this.playlistItems.length - 1 : videoIndex - 1
+ const videoIndex = this.videoIndexInPlaylistItems
+ const targetVideoIndex = this.videoIsFirstPlaylistItem ? this.playlistItems.length - 1 : videoIndex - 1
const targetPlaylistItem = this.playlistItems[targetVideoIndex]
this.$router.push(
{
- path: `/watch/${targetPlaylistItem.id ?? targetPlaylistItem.videoId}`,
- query: playlistInfo
+ path: `/watch/${targetPlaylistItem.videoId}`,
+ query: Object.assign(playlistInfo, { uniqueId: targetPlaylistItem.uniqueId }),
}
)
}
@@ -480,17 +473,15 @@ export default defineComponent({
const remainingItems = [].concat(this.playlistItems)
const items = []
- items.push(this.videoId)
+ items.push(this.currentVideo)
+ remainingItems.splice(this.currentVideoIndexZeroBased, 1)
- this.playlistItems.forEach((item) => {
+ while (remainingItems.length > 0) {
const randomInt = Math.floor(Math.random() * remainingItems.length)
- if ((remainingItems[randomInt].id ?? remainingItems[randomInt].videoId) !== this.videoId) {
- items.push(remainingItems[randomInt].id ?? remainingItems[randomInt].videoId)
- }
-
+ items.push(remainingItems[randomInt])
remainingItems.splice(randomInt, 1)
- })
+ }
this.randomizedPlaylistItems = items
},
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
index 9c9e195ad30ee..98121b1b00c0b 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
@@ -34,11 +34,11 @@
- {{ currentVideoIndex }} / {{ playlistVideoCount }}
+ {{ currentVideoIndexOneBased }} / {{ playlistVideoCount }}
@@ -116,12 +116,12 @@
@@ -142,7 +142,7 @@
:unique-id="item.uniqueId"
appearance="watchPlaylistItem"
force-list-type="list"
- :initial-visible-state="index < ((currentVideoIndex - 1) + 4) && index > ((currentVideoIndex - 1) - 4)"
+ :initial-visible-state="index < (currentVideoIndexZeroBased + 4) && index > (currentVideoIndexZeroBased - 4)"
@pause-player="$emit('pause-player')"
/>
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index 7217081d29c2e..b6918542d8dc1 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -1592,8 +1592,8 @@ export default defineComponent({
getPlaylistIndex: function () {
return this.$refs.watchVideoPlaylist
? this.getPlaylistReverse()
- ? this.$refs.watchVideoPlaylist.playlistItems.length - this.$refs.watchVideoPlaylist.currentVideoIndex
- : this.$refs.watchVideoPlaylist.currentVideoIndex - 1
+ ? this.$refs.watchVideoPlaylist.playlistItems.length - this.$refs.watchVideoPlaylist.currentVideoIndexOneBased
+ : this.$refs.watchVideoPlaylist.currentVideoIndexZeroBased
: -1
},
From a0223e1ae4813255373fbe1c8b98a99e975ec9f0 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 12 Sep 2023 15:48:45 +0800
Subject: [PATCH 157/236] ! Fix error in online playlist playing
---
.../components/watch-video-playlist/watch-video-playlist.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index ca5408afa4759..4aa5cb9a9a801 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -140,7 +140,10 @@ export default defineComponent({
// Re-fetch from local store when current user playlist updated
this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: false })
},
- uniqueId () {
+ uniqueId (newId, _oldId) {
+ // Playing online video
+ if (newId == null) { return }
+
// Re-fetch from local store when different item played
this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: true })
},
From ab5879ae46150d07303c92d0e4ea6e98071b4a5e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 14 Sep 2023 10:51:19 +0800
Subject: [PATCH 158/236] * Keep partial playlist backward compatibility by
restoring `type` in persisted playlist videos
---
src/renderer/store/modules/playlists.js | 15 +++++++++++++++
src/renderer/store/modules/utils.js | 3 +++
2 files changed, 18 insertions(+)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 5dc27963715dc..318c16706737f 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -135,6 +135,10 @@ const actions = {
if (videoData.uniqueId == null) {
videoData.uniqueId = generateRandomUniqueId()
}
+ // For backward compatibility
+ if (videoData.type == null) {
+ videoData.type = 'video'
+ }
await DBPlaylistHandlers.upsertVideoByPlaylistId(_id, videoData)
commit('addVideo', payload)
} catch (errMessage) {
@@ -152,6 +156,10 @@ const actions = {
if (videoData.uniqueId == null) {
videoData.uniqueId = generateRandomUniqueId()
}
+ // For backward compatibility
+ if (videoData.type == null) {
+ videoData.type = 'video'
+ }
})
await DBPlaylistHandlers.upsertVideosByPlaylistId(_id, videos)
commit('addVideos', payload)
@@ -205,6 +213,13 @@ const actions = {
// Ensure all videos has `uniqueId` property
if (v.uniqueId == null) {
v.uniqueId = generateRandomUniqueId()
+ anythingUpdated = true
+ }
+
+ // For backward compatibility
+ if (v.type == null) {
+ v.type = 'video'
+ anythingUpdated = true
}
})
// Save updated playlist object
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index b583bd4299aab..d63ade3b164fe 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -288,6 +288,9 @@ const actions = {
// `uniqueId` should be generated anyway
// 'uniqueId',
+
+ // `type` should be added in action anyway
+ // 'type',
]
// Using `every` to loop and `return false` to break
videoObjectArray.every((video) => {
From ca5f0455ad0440052b5a22ac6a67f4037fe1e126 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 19 Sep 2023 08:51:06 +0800
Subject: [PATCH 159/236] ! Fix grid item for playlist to hide external player
button for local playlist
---
.../components/ft-list-playlist/ft-list-playlist.js | 6 +++++-
.../components/ft-list-playlist/ft-list-playlist.vue | 2 +-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.js b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
index 654e5c97b9dd2..7d1f72ae92dca 100644
--- a/src/renderer/components/ft-list-playlist/ft-list-playlist.js
+++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
@@ -68,9 +68,13 @@ export default defineComponent({
thumbnailCanBeShown() {
return this.thumbnailPreference !== 'hidden'
},
+
+ isUserPlaylist() {
+ return this.data._id != null
+ },
},
created: function () {
- if (this.data._id != null) {
+ if (this.isUserPlaylist) {
this.parseUserData()
} else if (this.data.dataSource === 'local') {
this.parseLocalData()
diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.vue b/src/renderer/components/ft-list-playlist/ft-list-playlist.vue
index b548406e024f9..93a1cb4913da9 100644
--- a/src/renderer/components/ft-list-playlist/ft-list-playlist.vue
+++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.vue
@@ -55,7 +55,7 @@
Date: Tue, 19 Sep 2023 09:02:11 +0800
Subject: [PATCH 160/236] * Make history rememeber uniqueId (local playlist
video entry) when playing video with local playlist
---
src/datastores/handlers/base.js | 4 ++--
src/datastores/handlers/electron.js | 4 ++--
src/datastores/handlers/web.js | 4 ++--
src/main/index.js | 2 +-
.../components/ft-list-video/ft-list-video.js | 1 +
src/renderer/store/modules/history.js | 11 ++++++-----
src/renderer/views/Watch/Watch.js | 6 +++---
7 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js
index f875b57b3d943..2caf9ded69ed5 100644
--- a/src/datastores/handlers/base.js
+++ b/src/datastores/handlers/base.js
@@ -64,8 +64,8 @@ class History {
return db.history.updateAsync({ videoId }, { $set: { watchProgress } }, { upsert: true })
}
- static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType) {
- return db.history.updateAsync({ videoId }, { $set: { lastViewedPlaylistId, lastViewedPlaylistType } }, { upsert: true })
+ static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId) {
+ return db.history.updateAsync({ videoId }, { $set: { lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId } }, { upsert: true })
}
static delete(videoId) {
diff --git a/src/datastores/handlers/electron.js b/src/datastores/handlers/electron.js
index aea0c0376746b..3b569180ebbfd 100644
--- a/src/datastores/handlers/electron.js
+++ b/src/datastores/handlers/electron.js
@@ -42,12 +42,12 @@ class History {
)
}
- static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType) {
+ static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId) {
return ipcRenderer.invoke(
IpcChannels.DB_HISTORY,
{
action: DBActions.HISTORY.UPDATE_PLAYLIST,
- data: { videoId, lastViewedPlaylistId, lastViewedPlaylistType }
+ data: { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId }
}
)
}
diff --git a/src/datastores/handlers/web.js b/src/datastores/handlers/web.js
index bb74f7160c09c..7702ca239d785 100644
--- a/src/datastores/handlers/web.js
+++ b/src/datastores/handlers/web.js
@@ -33,8 +33,8 @@ class History {
return baseHandlers.history.updateWatchProgress(videoId, watchProgress)
}
- static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType) {
- return baseHandlers.history.updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType)
+ static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId) {
+ return baseHandlers.history.updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId)
}
static delete(videoId) {
diff --git a/src/main/index.js b/src/main/index.js
index a99768d35dfaf..83ea27622a507 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -846,7 +846,7 @@ function runApp() {
return null
case DBActions.HISTORY.UPDATE_PLAYLIST:
- await baseHandlers.history.updateLastViewedPlaylist(data.videoId, data.lastViewedPlaylistId, data.lastViewedPlaylistType)
+ await baseHandlers.history.updateLastViewedPlaylist(data.videoId, data.lastViewedPlaylistId, data.lastViewedPlaylistType, data.lastViewedUniqueId)
syncOtherWindows(
IpcChannels.SYNC_HISTORY,
event,
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 0d1bd5a43f012..dcdcbe1d9a597 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -361,6 +361,7 @@ export default defineComponent({
return {
playlistId: this.historyEntry?.lastViewedPlaylistId,
playlistType: this.historyEntry?.lastViewedPlaylistType,
+ uniqueId: this.historyEntry?.lastViewedUniqueId,
}
},
diff --git a/src/renderer/store/modules/history.js b/src/renderer/store/modules/history.js
index 28f28f313aa0f..bd0923c0ed829 100644
--- a/src/renderer/store/modules/history.js
+++ b/src/renderer/store/modules/history.js
@@ -73,14 +73,14 @@ const actions = {
}
},
- async updateLastViewedPlaylist({ commit }, { videoId, lastViewedPlaylistId, lastViewedPlaylistType }) {
+ async updateLastViewedPlaylist({ commit }, { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId }) {
try {
- await DBHistoryHandlers.updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType)
- commit('updateRecordLastViewedPlaylistIdInHistoryCache', { videoId, lastViewedPlaylistId, lastViewedPlaylistType })
+ await DBHistoryHandlers.updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId)
+ commit('updateRecordLastViewedPlaylistIdInHistoryCache', { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId })
} catch (errMessage) {
console.error(errMessage)
}
- }
+ },
}
const mutations = {
@@ -118,7 +118,7 @@ const mutations = {
vueSet(state.historyCacheById, videoId, targetRecord)
},
- updateRecordLastViewedPlaylistIdInHistoryCache(state, { videoId, lastViewedPlaylistId, lastViewedPlaylistType }) {
+ updateRecordLastViewedPlaylistIdInHistoryCache(state, { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId }) {
const i = state.historyCacheSorted.findIndex((currentRecord) => {
return currentRecord.videoId === videoId
})
@@ -126,6 +126,7 @@ const mutations = {
const targetRecord = Object.assign({}, state.historyCacheSorted[i])
targetRecord.lastViewedPlaylistId = lastViewedPlaylistId
targetRecord.lastViewedPlaylistType = lastViewedPlaylistType
+ targetRecord.lastViewedUniqueId = lastViewedUniqueId
state.historyCacheSorted.splice(i, 1, targetRecord)
vueSet(state.historyCacheById, videoId, targetRecord)
},
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index 1328bc9549e16..4c81cf462cf39 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -1037,13 +1037,13 @@ export default defineComponent({
if (!(this.rememberHistory && this.saveVideoHistoryWithLastViewedPlaylist)) { return }
if (this.isUpcoming || this.isLive) { return }
- const payload = {
+ this.updateLastViewedPlaylist({
videoId: this.videoId,
// Whether there is a playlist ID or not, save it
lastViewedPlaylistId: this.playlistId,
lastViewedPlaylistType: this.playlistType,
- }
- this.updateLastViewedPlaylist(payload)
+ lastViewedUniqueId: this.uniqueId,
+ })
},
handleVideoReady: function () {
From a3381cb501359741777cbbb29aa4c8cd974e487d Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 19 Sep 2023 09:05:52 +0800
Subject: [PATCH 161/236] ! Fix grid item for video in user playlist to hide
external player button
---
src/renderer/components/ft-list-video/ft-list-video.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 0a59c2e5708a2..3834889ef9d8e 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -37,7 +37,7 @@
{{ isLive ? $t("Video.Live") : (isUpcoming ? $t("Video.Upcoming") : duration) }}
Date: Tue, 19 Sep 2023 09:20:10 +0800
Subject: [PATCH 162/236] ! Fix grid item for video in history with user
playlist to hide external player button
---
src/renderer/components/ft-list-video/ft-list-video.js | 4 ++--
1 file changed, 2 insertions(+), 2 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 dcdcbe1d9a597..fa927a732c9ee 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -144,7 +144,7 @@ export default defineComponent({
},
inUserPlaylist: function () {
- return this.playlistType === 'user'
+ return this.playlistTypeFinal === 'user'
},
selectedUserPlaylist: function () {
@@ -349,7 +349,7 @@ export default defineComponent({
if (this.playlistId) {
return {
playlistId: this.playlistId,
- playlistType: null,
+ playlistType: this.playlistType,
uniqueId: this.uniqueId,
}
}
From 2fd43b5108e8e9045107df7aecf04e1388ca6747 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 19 Sep 2023 09:32:34 +0800
Subject: [PATCH 163/236] ! Fix grid item for video in watch page playlist
component with user playlist to hide external player button
---
.../components/watch-video-playlist/watch-video-playlist.js | 5 +++++
.../components/watch-video-playlist/watch-video-playlist.vue | 3 ++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index 4aa5cb9a9a801..dccfc75a175c6 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -70,6 +70,11 @@ export default defineComponent({
selectedUserPlaylistLastUpdatedAt () {
return this.selectedUserPlaylist?.lastUpdatedAt
},
+ playlistType() {
+ if (this.selectedUserPlaylist != null) { return 'user' }
+
+ return ''
+ },
currentVideoIndexZeroBased: function () {
return this.playlistItems.findIndex((item) => {
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
index 98121b1b00c0b..1496179ecc915 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
@@ -135,11 +135,12 @@
Date: Tue, 19 Sep 2023 09:46:50 +0800
Subject: [PATCH 164/236] * Update watch page to clear `uniqueID` from query
when not playing local playlist
---
src/renderer/views/Watch/Watch.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index 4c81cf462cf39..37babf84990d1 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -1102,6 +1102,7 @@ export default defineComponent({
if (this.playlistId == null || this.playlistId.length === 0) {
this.playlistType = ''
+ this.uniqueId = null
this.watchingPlaylist = false
return
}
@@ -1120,6 +1121,7 @@ export default defineComponent({
this.playlistType = this.$route.query.playlistType
if (this.playlistType !== 'user') {
// Remote playlist
+ this.uniqueId = null
this.watchingPlaylist = true
return
}
@@ -1130,6 +1132,7 @@ export default defineComponent({
// Clear playlist data so that watch history will be properly updated
this.playlistId = ''
this.playlistType = ''
+ this.uniqueId = null
}
this.watchingPlaylist = this.selectedUserPlaylist != null
},
From 7863d037ff59dc8dc715bbae56c3b17cd4d297a3 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 19 Sep 2023 09:57:41 +0800
Subject: [PATCH 165/236] ! Fix watch page about user playlist detection on new
window
---
src/renderer/views/Watch/Watch.js | 35 +++++++++++++++++++++----------
1 file changed, 24 insertions(+), 11 deletions(-)
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index 37babf84990d1..0a7984f0ba25d 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -210,6 +210,9 @@ export default defineComponent({
return this.$store.getters.getAllowDashAv1Formats
},
+ userPlaylistsReady: function () {
+ return this.$store.getters.getPlaylistsReady
+ },
selectedUserPlaylist: function () {
if (this.playlistId == null) { return null }
if (this.playlistId === '') { return null }
@@ -247,25 +250,35 @@ export default defineComponent({
}
break
}
- }
+ },
+ userPlaylistsReady() {
+ this.onMountedDependOnLocalStateLoading()
+ },
},
mounted: function () {
this.videoId = this.$route.params.id
this.activeFormat = this.defaultVideoFormat
this.useTheatreMode = this.defaultTheatreMode && this.theatrePossible
- this.checkIfPlaylist()
- this.checkIfTimestamp()
-
- if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
- this.getVideoInformationInvidious()
- } else {
- this.getVideoInformationLocal()
- }
-
- window.addEventListener('beforeunload', this.handleWatchProgress)
+ this.onMountedDependOnLocalStateLoading()
},
methods: {
+ onMountedDependOnLocalStateLoading() {
+ // Stuff that require user playlists to be ready
+ if (!this.userPlaylistsReady) { return }
+
+ this.checkIfPlaylist()
+ this.checkIfTimestamp()
+
+ if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
+ this.getVideoInformationInvidious()
+ } else {
+ this.getVideoInformationLocal()
+ }
+
+ window.addEventListener('beforeunload', this.handleWatchProgress)
+ },
+
changeTimestamp: function (timestamp) {
this.$refs.videoPlayer.player.currentTime(timestamp)
},
From be80686942fbe7596008b442636ede5f3581e797 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 19 Sep 2023 10:14:04 +0800
Subject: [PATCH 166/236] * Reflect playlist updates on watch page playlist
panel, even for currently playing video
---
.../watch-video-playlist.js | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index dccfc75a175c6..264bb1f7b1dd5 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -132,6 +132,9 @@ export default defineComponent({
videoIsLastPlaylistItem: function () {
return this.videoIndexInPlaylistItems === (this.playlistItems.length - 1)
},
+ videoIsNotPlaylistItem: function () {
+ return this.videoIndexInPlaylistItems === -1
+ },
},
watch: {
userPlaylistsReady: function() {
@@ -139,11 +142,12 @@ export default defineComponent({
},
selectedUserPlaylistVideoCount () {
// Re-fetch from local store when current user playlist updated
- this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: false })
+ this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: true })
+ this.shufflePlaylistItems()
},
selectedUserPlaylistLastUpdatedAt () {
// Re-fetch from local store when current user playlist updated
- this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: false })
+ this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: true })
},
uniqueId (newId, _oldId) {
// Playing online video
@@ -277,17 +281,17 @@ export default defineComponent({
playlistId: this.playlistId
}
+ const videoIndex = this.videoIndexInPlaylistItems
+ const targetVideoIndex = (this.videoIsNotPlaylistItem || this.videoIsLastPlaylistItem) ? 0 : videoIndex + 1
if (this.shuffleEnabled) {
- const videoIndex = this.videoIndexInPlaylistItems
let doShufflePlaylistItems = false
if (this.videoIsLastPlaylistItem && !this.loopEnabled) {
showToast(this.$t('The playlist has ended. Enable loop to continue playing'))
return
}
// loopEnabled = true
- if (this.videoIsLastPlaylistItem) { doShufflePlaylistItems = true }
+ if (this.videoIsLastPlaylistItem || this.videoIsNotPlaylistItem) { doShufflePlaylistItems = true }
- const targetVideoIndex = this.videoIsLastPlaylistItem ? 0 : videoIndex + 1
const targetPlaylistItem = this.randomizedPlaylistItems[targetVideoIndex]
this.$router.push(
@@ -299,8 +303,6 @@ export default defineComponent({
showToast(this.$t('Playing Next Video'))
if (doShufflePlaylistItems) { this.shufflePlaylistItems() }
} else {
- const videoIndex = this.videoIndexInPlaylistItems
- const targetVideoIndex = this.videoIsLastPlaylistItem ? 0 : videoIndex + 1
const targetPlaylistItem = this.playlistItems[targetVideoIndex]
const stopDueToLoopDisabled = this.videoIsLastPlaylistItem && !this.loopEnabled
@@ -326,9 +328,9 @@ export default defineComponent({
playlistId: this.playlistId
}
+ const videoIndex = this.videoIndexInPlaylistItems
+ const targetVideoIndex = (this.videoIsFirstPlaylistItem || this.videoIsNotPlaylistItem) ? this.playlistItems.length - 1 : videoIndex - 1
if (this.shuffleEnabled) {
- const videoIndex = this.videoIndexInPlaylistItems
- const targetVideoIndex = this.videoIsFirstPlaylistItem ? this.randomizedPlaylistItems.length - 1 : videoIndex - 1
const targetPlaylistItem = this.randomizedPlaylistItems[targetVideoIndex]
this.$router.push(
@@ -338,8 +340,6 @@ export default defineComponent({
}
)
} else {
- const videoIndex = this.videoIndexInPlaylistItems
- const targetVideoIndex = this.videoIsFirstPlaylistItem ? this.playlistItems.length - 1 : videoIndex - 1
const targetPlaylistItem = this.playlistItems[targetVideoIndex]
this.$router.push(
From 095fb48d7fc687b841c7c68c8e9e074d7094cd9a Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 19 Sep 2023 14:51:03 +0800
Subject: [PATCH 167/236] ! Allow video with local playlist to be played in
external player, but without playlist
Also add missing fix for WatchVideoInfo
---
.../components/ft-list-video/ft-list-video.js | 17 ++++++++++++++---
.../components/ft-list-video/ft-list-video.vue | 2 +-
.../watch-video-info/watch-video-info.js | 17 ++++++++++++++---
3 files changed, 29 insertions(+), 7 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 fa927a732c9ee..b3047b7247121 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -435,7 +435,7 @@ export default defineComponent({
handleExternalPlayer: function () {
this.$emit('pause-player')
- this.openInExternalPlayer({
+ const payload = {
watchProgress: this.watchProgress,
playbackRate: this.defaultPlayback,
videoId: this.id,
@@ -444,8 +444,19 @@ export default defineComponent({
playlistIndex: this.playlistIndex,
playlistReverse: this.playlistReverse,
playlistShuffle: this.playlistShuffle,
- playlistLoop: this.playlistLoop
- })
+ playlistLoop: this.playlistLoop,
+ }
+ // Only play video in non playlist mode when user playlist detected
+ if (!this.inUserPlaylist) {
+ Object.assign(payload, {
+ playlistId: null,
+ playlistIndex: null,
+ playlistReverse: null,
+ playlistShuffle: null,
+ playlistLoop: null,
+ })
+ }
+ this.openInExternalPlayer(payload)
if (this.saveWatchedProgress && !this.watched) {
this.markAsWatched()
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 3834889ef9d8e..0a59c2e5708a2 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -37,7 +37,7 @@
{{ isLive ? $t("Video.Live") : (isUpcoming ? $t("Video.Upcoming") : duration) }}
Date: Tue, 26 Sep 2023 08:52:00 +0800
Subject: [PATCH 168/236] ! Fix external player handling for video in local
playlist
---
src/renderer/components/ft-list-video/ft-list-video.js | 6 +++---
1 file changed, 3 insertions(+), 3 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 b3047b7247121..8edf7eafdd577 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -144,7 +144,7 @@ export default defineComponent({
},
inUserPlaylist: function () {
- return this.playlistTypeFinal === 'user'
+ return this.playlistTypeFinal === 'user' || this.selectedUserPlaylist != null
},
selectedUserPlaylist: function () {
@@ -157,7 +157,7 @@ export default defineComponent({
playlistSharable() {
// `playlistId` can be undefined
// User playlist ID should not be shared
- return this.playlistIdFinal && this.playlistIdFinal.length !== 0 && this.selectedUserPlaylist == null
+ return this.playlistIdFinal && this.playlistIdFinal.length !== 0 && !this.inUserPlaylist
},
invidiousUrl: function () {
@@ -447,7 +447,7 @@ export default defineComponent({
playlistLoop: this.playlistLoop,
}
// Only play video in non playlist mode when user playlist detected
- if (!this.inUserPlaylist) {
+ if (this.inUserPlaylist) {
Object.assign(payload, {
playlistId: null,
playlistIndex: null,
From 25c75ce7fb211e1c24bf01ad6cd383abff0f1521 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 29 Sep 2023 08:55:05 +0800
Subject: [PATCH 169/236] ! Fix ft-video having different URLs in links
---
src/renderer/components/ft-list-video/ft-list-video.js | 7 +++++++
.../components/ft-list-video/ft-list-video.vue | 10 ++--------
2 files changed, 9 insertions(+), 8 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 8edf7eafdd577..4f05dfdafcc16 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -375,6 +375,13 @@ export default defineComponent({
return this.playlistIdTypePairFinal?.uniqueId
},
+ watchPageLinkTo() {
+ // For `router-link` attribute `to`
+ return {
+ path: `/watch/${this.id}`,
+ query: this.watchPageLinkQuery,
+ }
+ },
watchPageLinkQuery() {
const query = {}
if (this.playlistIdFinal) { query.playlistId = this.playlistIdFinal }
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 0a59c2e5708a2..a31a65547b3c8 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -14,10 +14,7 @@
{{ displayTitle }}
From 2656915ddf6e16923af8e31a13f8727842bf93d2 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sun, 8 Oct 2023 08:25:49 +0800
Subject: [PATCH 170/236] yarn run lint-style-fix
---
.../ft-create-playlist-prompt.css | 4 +-
.../ft-playlist-add-video-prompt.scss | 4 +-
.../ft-playlist-selector.scss | 55 +++++++++----------
3 files changed, 30 insertions(+), 33 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.css b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.css
index 987191b0f55d1..dc3f83c4074cc 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.css
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.css
@@ -23,6 +23,6 @@
}
.playlistNameInput {
- width: 80%;
- max-width: 600px;
+ inline-size: 80%;
+ max-inline-size: 600px;
}
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
index 4cc629a8f59f5..bc493b103fa4c 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
@@ -23,7 +23,7 @@
// Style for `ft-prompt`
:deep(.promptCard) {
// Currently only this prompt has enough content to make prompt too high
- max-height: 95%;
+ max-block-size: 95%;
// Some child(s) will grow vertically
display: flex;
@@ -32,7 +32,7 @@
.sortSelect {
/* Put it on the right */
- margin-left: auto;
+ margin-inline-start: auto;
}
.playlists-container {
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
index a451fdc3eb23c..37d75eef84fa2 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
@@ -79,7 +79,7 @@ $watched-transition-duration: 0.5s;
}
.videoWatched {
position: absolute;
- top: 0;
+ inset-block-start: 0;
padding: 2px;
opacity: $thumbnail-overlay-opacity;
color: var(--primary-text-color);
@@ -88,9 +88,10 @@ $watched-transition-duration: 0.5s;
}
.videoDuration {
position: absolute;
- bottom: 4px;
- right: 4px;
- padding: 3px 4px;
+ inset-block-end: 4px;
+ inset-inline-end: 4px;
+ padding-block: 3px;
+ padding-inline: 4px;
line-height: 1.2;
font-size: 15px;
border-radius: 5px;
@@ -110,40 +111,36 @@ $watched-transition-duration: 0.5s;
}
.externalPlayerIcon {
position: absolute;
- bottom: 4px;
- left: 4px;
+ inset-block-end: 4px;
+ inset-inline-start: 4px;
font-size: 17px;
opacity: $thumbnail-overlay-opacity;
}
.playlistIcon {
position: absolute;
- top: 40px;
- right: 3px;
+ inset-block-start: 40px;
+ inset-inline-end: 3px;
font-size: 17px;
opacity: $thumbnail-overlay-opacity;
}
.watchedProgressBar {
- height: 2px;
+ block-size: 2px;
position: absolute;
- bottom: 0;
+ inset-block-end: 0;
background-color: var(--primary-color);
z-index: 2;
}
.videoCountContainer {
position: absolute;
- right: 0;
- top: 0;
- bottom: 0;
- width: 60px;
+ inset-inline-end: 0;
+ inset-block: 0;
+ inline-size: 60px;
font-size: 20px;
.background,
.inner {
position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
+ inset: 0;
}
.background {
background-color: var(--bg-color);
@@ -163,7 +160,7 @@ $watched-transition-duration: 0.5s;
justify-content: center;
.channelImage {
- height: 130px;
+ block-size: 130px;
border-radius: 50%;
}
}
@@ -189,7 +186,7 @@ $watched-transition-duration: 0.5s;
}
}
.infoLine {
- margin-top: 5px;
+ margin-block-start: 5px;
font-size: 14px;
@include is-sidebar-item {
@@ -204,7 +201,7 @@ $watched-transition-duration: 0.5s;
}
.description {
font-size: 14px;
- max-height: 50px;
+ max-block-size: 50px;
overflow-y: hidden;
@include low-contrast-when-watched(var(--secondary-text-color));
}
@@ -212,16 +209,16 @@ $watched-transition-duration: 0.5s;
&.grid {
display: flex;
flex-direction: column;
- width: 245px;
- min-height: 230px;
- padding-bottom: 20px;
+ inline-size: 245px;
+ min-block-size: 230px;
+ padding-block-end: 20px;
.videoThumbnail,
.channelThumbnail {
- margin-bottom: 12px;
+ margin-block-end: 12px;
.thumbnailImage {
- width: 100%;
+ inline-size: 100%;
// Ensure placeholder image displayed at same aspect ratio as most other images
aspect-ratio: 16/9;
}
@@ -230,7 +227,7 @@ $watched-transition-duration: 0.5s;
font-size: 22px;
}
.infoLine {
- margin-top: 8px;
+ margin-block-start: 8px;
font-size: 13px;
}
}
@@ -243,7 +240,7 @@ $watched-transition-duration: 0.5s;
.selectedIcon {
position: absolute;
- top: calc(50% - 25px);
- left: calc(50% - 25px);
+ inset-block-start: calc(50% - 25px);
+ inset-inline-start: calc(50% - 25px);
font-size: 50px;
}
From f733cb5be27a2df07f51a384a273524ad0da810b Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 19 Oct 2023 14:38:57 +0800
Subject: [PATCH 171/236] $ Rename uniqueId to playlistItemId
---
src/datastores/handlers/base.js | 8 +++----
src/datastores/handlers/electron.js | 8 +++----
src/datastores/handlers/web.js | 8 +++----
src/main/index.js | 4 ++--
.../components/data-settings/data-settings.js | 12 +++++-----
.../ft-list-video-lazy/ft-list-video-lazy.js | 2 +-
.../ft-list-video-lazy/ft-list-video-lazy.vue | 2 +-
.../components/ft-list-video/ft-list-video.js | 12 +++++-----
.../components/playlist-info/playlist-info.js | 2 +-
.../playlist-info/playlist-info.vue | 2 +-
.../watch-video-playlist.js | 22 ++++++++---------
.../watch-video-playlist.vue | 4 ++--
src/renderer/store/modules/history.js | 10 ++++----
src/renderer/store/modules/playlists.js | 24 +++++++++----------
src/renderer/store/modules/utils.js | 4 ++--
src/renderer/views/Playlist/Playlist.js | 18 +++++++-------
src/renderer/views/Playlist/Playlist.vue | 12 +++++-----
src/renderer/views/Watch/Watch.js | 12 +++++-----
src/renderer/views/Watch/Watch.vue | 2 +-
19 files changed, 84 insertions(+), 84 deletions(-)
diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js
index 2caf9ded69ed5..070ebda8e8e2a 100644
--- a/src/datastores/handlers/base.js
+++ b/src/datastores/handlers/base.js
@@ -64,8 +64,8 @@ class History {
return db.history.updateAsync({ videoId }, { $set: { watchProgress } }, { upsert: true })
}
- static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId) {
- return db.history.updateAsync({ videoId }, { $set: { lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId } }, { upsert: true })
+ static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId) {
+ return db.history.updateAsync({ videoId }, { $set: { lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId } }, { upsert: true })
}
static delete(videoId) {
@@ -136,10 +136,10 @@ class Playlists {
return db.playlists.removeAsync({ _id, protected: { $ne: true } })
}
- static deleteVideoIdByPlaylistId(_id, uniqueId) {
+ static deleteVideoIdByPlaylistId(_id, playlistItemId) {
return db.playlists.updateAsync(
{ _id },
- { $pull: { videos: { uniqueId } } },
+ { $pull: { videos: { playlistItemId } } },
{ upsert: true }
)
}
diff --git a/src/datastores/handlers/electron.js b/src/datastores/handlers/electron.js
index 3b569180ebbfd..d84ccac13c78d 100644
--- a/src/datastores/handlers/electron.js
+++ b/src/datastores/handlers/electron.js
@@ -42,12 +42,12 @@ class History {
)
}
- static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId) {
+ static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId) {
return ipcRenderer.invoke(
IpcChannels.DB_HISTORY,
{
action: DBActions.HISTORY.UPDATE_PLAYLIST,
- data: { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId }
+ data: { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId }
}
)
}
@@ -160,12 +160,12 @@ class Playlists {
)
}
- static deleteVideoIdByPlaylistId(_id, uniqueId) {
+ static deleteVideoIdByPlaylistId(_id, playlistItemId) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
{
action: DBActions.PLAYLISTS.DELETE_VIDEO_ID,
- data: { _id, uniqueId }
+ data: { _id, playlistItemId }
}
)
}
diff --git a/src/datastores/handlers/web.js b/src/datastores/handlers/web.js
index 7702ca239d785..103d93d441a2b 100644
--- a/src/datastores/handlers/web.js
+++ b/src/datastores/handlers/web.js
@@ -33,8 +33,8 @@ class History {
return baseHandlers.history.updateWatchProgress(videoId, watchProgress)
}
- static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId) {
- return baseHandlers.history.updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId)
+ static updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId) {
+ return baseHandlers.history.updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId)
}
static delete(videoId) {
@@ -97,8 +97,8 @@ class Playlists {
return baseHandlers.playlists.delete(_id)
}
- static deleteVideoIdByPlaylistId(_id, uniqueId) {
- return baseHandlers.playlists.deleteVideoIdByPlaylistId(_id, uniqueId)
+ static deleteVideoIdByPlaylistId(_id, playlistItemId) {
+ return baseHandlers.playlists.deleteVideoIdByPlaylistId(_id, playlistItemId)
}
static deleteVideoIdsByPlaylistId(_id, videoIds) {
diff --git a/src/main/index.js b/src/main/index.js
index 699f24cb06454..5aa7b13c90331 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -864,7 +864,7 @@ function runApp() {
return null
case DBActions.HISTORY.UPDATE_PLAYLIST:
- await baseHandlers.history.updateLastViewedPlaylist(data.videoId, data.lastViewedPlaylistId, data.lastViewedPlaylistType, data.lastViewedUniqueId)
+ await baseHandlers.history.updateLastViewedPlaylist(data.videoId, data.lastViewedPlaylistId, data.lastViewedPlaylistType, data.lastViewedPlaylistItemId)
syncOtherWindows(
IpcChannels.SYNC_HISTORY,
event,
@@ -1012,7 +1012,7 @@ function runApp() {
return null
case DBActions.PLAYLISTS.DELETE_VIDEO_ID:
- await baseHandlers.playlists.deleteVideoIdByPlaylistId(data._id, data.uniqueId)
+ await baseHandlers.playlists.deleteVideoIdByPlaylistId(data._id, data.playlistItemId)
syncOtherWindows(
IpcChannels.SYNC_PLAYLISTS,
event,
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index a2a09b0373038..1099013151f1c 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -914,8 +914,8 @@ export default defineComponent({
'lengthSeconds',
'timeAdded',
- // `uniqueId` should be optional for backward compatibility
- // 'uniqueId',
+ // `playlistItemId` should be optional for backward compatibility
+ // 'playlistItemId',
]
playlists.forEach((playlistData) => {
@@ -959,14 +959,14 @@ export default defineComponent({
if (existingPlaylist !== undefined) {
playlistObject.videos.forEach((video) => {
let videoExists = false
- if (video.uniqueId != null) {
- // Find by `uniqueId` if present
+ if (video.playlistItemId != null) {
+ // Find by `playlistItemId` if present
videoExists = existingPlaylist.videos.some((x) => {
// Allow duplicate (by videoId) videos to be added
- return x.videoId === video.videoId && x.uniqueId === video.uniqueId
+ return x.videoId === video.videoId && x.playlistItemId === video.playlistItemId
})
} else {
- // Older playlist exports have no `uniqueId` but have `timeAdded`
+ // Older playlist exports have no `playlistItemId` but have `timeAdded`
// Which might be duplicate for copied playlists with duplicate `videoId`
videoExists = existingPlaylist.videos.some((x) => {
// Allow duplicate (by videoId) videos to be added
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
index a7a7d71f9922a..7befbc2dbce72 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.js
@@ -35,7 +35,7 @@ export default defineComponent({
type: Boolean,
default: false
},
- uniqueId: {
+ playlistItemId: {
type: String,
default: null,
},
diff --git a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
index bdb98bbf0ce83..197d7226ca079 100644
--- a/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
+++ b/src/renderer/components/ft-list-video-lazy/ft-list-video-lazy.vue
@@ -14,7 +14,7 @@
:playlist-reverse="playlistReverse"
:playlist-shuffle="playlistShuffle"
:playlist-loop="playlistLoop"
- :unique-id="uniqueId"
+ :playlist-item-id="playlistItemId"
:force-list-type="forceListType"
:appearance="appearance"
:always-show-add-to-playlist-button="alwaysShowAddToPlaylistButton"
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 6c5ce05ae0d54..0bd4234d57889 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -30,7 +30,7 @@ export default defineComponent({
type: String,
default: null
},
- uniqueId: {
+ playlistItemId: {
type: String,
default: null
},
@@ -350,7 +350,7 @@ export default defineComponent({
return {
playlistId: this.playlistId,
playlistType: this.playlistType,
- uniqueId: this.uniqueId,
+ playlistItemId: this.playlistItemId,
}
}
@@ -361,7 +361,7 @@ export default defineComponent({
return {
playlistId: this.historyEntry?.lastViewedPlaylistId,
playlistType: this.historyEntry?.lastViewedPlaylistType,
- uniqueId: this.historyEntry?.lastViewedUniqueId,
+ playlistItemId: this.historyEntry?.lastViewedPlaylistItemId,
}
},
@@ -371,8 +371,8 @@ export default defineComponent({
playlistTypeFinal: function () {
return this.playlistIdTypePairFinal?.playlistType
},
- uniqueIdFinal: function () {
- return this.playlistIdTypePairFinal?.uniqueId
+ playlistItemIdFinal: function () {
+ return this.playlistIdTypePairFinal?.playlistItemId
},
watchPageLinkTo() {
@@ -386,7 +386,7 @@ export default defineComponent({
const query = {}
if (this.playlistIdFinal) { query.playlistId = this.playlistIdFinal }
if (this.playlistTypeFinal) { query.playlistType = this.playlistTypeFinal }
- if (this.uniqueIdFinal) { query.uniqueId = this.uniqueIdFinal }
+ if (this.playlistItemIdFinal) { query.playlistItemId = this.playlistItemIdFinal }
return query
},
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 04d45af5f1b90..c9b4fc6bc76a8 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -27,7 +27,7 @@ export default defineComponent({
type: String,
required: true,
},
- firstVideoUniqueId: {
+ firstVideoPlaylistItemId: {
type: String,
required: true,
},
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 21e7e421dbb2c..292bf3245511a 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -8,7 +8,7 @@
path: `/watch/${firstVideoId}`,
query: {
playlistId: id,
- uniqueId: firstVideoUniqueId,
+ playlistItemId: firstVideoPlaylistItemId,
},
}"
tabindex="-1"
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index 2ca5bde134a4d..dfcd0f8a941f9 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -27,7 +27,7 @@ export default defineComponent({
type: String,
required: true,
},
- uniqueId: {
+ playlistItemId: {
type: String,
default: null,
},
@@ -82,8 +82,8 @@ export default defineComponent({
currentVideoIndexZeroBased: function () {
return this.playlistItems.findIndex((item) => {
- if (item.uniqueId != null && this.uniqueId != null) {
- return item.uniqueId === this.uniqueId
+ if (item.playlistItemId != null && this.playlistItemId != null) {
+ return item.playlistItemId === this.playlistItemId
} else if (item.videoId != null) {
return item.videoId === this.videoId
} else {
@@ -121,8 +121,8 @@ export default defineComponent({
const playlistItems = this.shuffleEnabled ? this.randomizedPlaylistItems : this.playlistItems
return playlistItems.findIndex((item) => {
- if (item.uniqueId != null && this.uniqueId != null) {
- return item.uniqueId === this.uniqueId
+ if (item.playlistItemId != null && this.playlistItemId != null) {
+ return item.playlistItemId === this.playlistItemId
} else if (item.videoId != null) {
return item.videoId === this.videoId
} else {
@@ -153,7 +153,7 @@ export default defineComponent({
// Re-fetch from local store when current user playlist updated
this.parseUserPlaylist(this.selectedUserPlaylist, { allowPlayingVideoRemoval: true })
},
- uniqueId (newId, _oldId) {
+ playlistItemId (newId, _oldId) {
// Playing online video
if (newId == null) { return }
@@ -301,7 +301,7 @@ export default defineComponent({
this.$router.push(
{
path: `/watch/${targetPlaylistItem.videoId}`,
- query: Object.assign(playlistInfo, { uniqueId: targetPlaylistItem.uniqueId }),
+ query: Object.assign(playlistInfo, { playlistItemId: targetPlaylistItem.playlistItemId }),
}
)
showToast(this.$t('Playing Next Video'))
@@ -318,7 +318,7 @@ export default defineComponent({
this.$router.push(
{
path: `/watch/${targetPlaylistItem.videoId}`,
- query: Object.assign(playlistInfo, { uniqueId: targetPlaylistItem.uniqueId }),
+ query: Object.assign(playlistInfo, { playlistItemId: targetPlaylistItem.playlistItemId }),
}
)
showToast(this.$t('Playing Next Video'))
@@ -340,7 +340,7 @@ export default defineComponent({
this.$router.push(
{
path: `/watch/${targetPlaylistItem.videoId}`,
- query: Object.assign(playlistInfo, { uniqueId: targetPlaylistItem.uniqueId }),
+ query: Object.assign(playlistInfo, { playlistItemId: targetPlaylistItem.playlistItemId }),
}
)
} else {
@@ -349,7 +349,7 @@ export default defineComponent({
this.$router.push(
{
path: `/watch/${targetPlaylistItem.videoId}`,
- query: Object.assign(playlistInfo, { uniqueId: targetPlaylistItem.uniqueId }),
+ query: Object.assign(playlistInfo, { playlistItemId: targetPlaylistItem.playlistItemId }),
}
)
}
@@ -457,7 +457,7 @@ export default defineComponent({
this.playlistItems = playlist.videos
} else {
// `this.currentVideo` relies on `playlistItems`
- const latestPlaylistContainsCurrentVideo = playlist.videos.find(v => v.uniqueId === this.uniqueId) != null
+ const latestPlaylistContainsCurrentVideo = playlist.videos.find(v => v.playlistItemId === this.playlistItemId) != null
// Only update list of videos if latest video list still contains currently playing video
if (latestPlaylistContainsCurrentVideo) {
this.playlistItems = playlist.videos
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
index 4f9d109b919d8..3104af30e4a6b 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
@@ -118,7 +118,7 @@
>
@@ -140,7 +140,7 @@
:playlist-id="playlistId"
:playlist-type="playlistType"
:playlist-index="reversePlaylist ? playlistItems.length - index - 1 : index"
- :unique-id="item.uniqueId"
+ :playlist-item-id="item.playlistItemId"
:playlist-reverse="reversePlaylist"
:playlist-shuffle="shuffleEnabled"
:playlist-loop="loopEnabled"
diff --git a/src/renderer/store/modules/history.js b/src/renderer/store/modules/history.js
index bd0923c0ed829..1a31f31d0c4d3 100644
--- a/src/renderer/store/modules/history.js
+++ b/src/renderer/store/modules/history.js
@@ -73,10 +73,10 @@ const actions = {
}
},
- async updateLastViewedPlaylist({ commit }, { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId }) {
+ async updateLastViewedPlaylist({ commit }, { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId }) {
try {
- await DBHistoryHandlers.updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId)
- commit('updateRecordLastViewedPlaylistIdInHistoryCache', { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId })
+ await DBHistoryHandlers.updateLastViewedPlaylist(videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId)
+ commit('updateRecordLastViewedPlaylistIdInHistoryCache', { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId })
} catch (errMessage) {
console.error(errMessage)
}
@@ -118,7 +118,7 @@ const mutations = {
vueSet(state.historyCacheById, videoId, targetRecord)
},
- updateRecordLastViewedPlaylistIdInHistoryCache(state, { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedUniqueId }) {
+ updateRecordLastViewedPlaylistIdInHistoryCache(state, { videoId, lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId }) {
const i = state.historyCacheSorted.findIndex((currentRecord) => {
return currentRecord.videoId === videoId
})
@@ -126,7 +126,7 @@ const mutations = {
const targetRecord = Object.assign({}, state.historyCacheSorted[i])
targetRecord.lastViewedPlaylistId = lastViewedPlaylistId
targetRecord.lastViewedPlaylistType = lastViewedPlaylistType
- targetRecord.lastViewedUniqueId = lastViewedUniqueId
+ targetRecord.lastViewedPlaylistItemId = lastViewedPlaylistItemId
state.historyCacheSorted.splice(i, 1, targetRecord)
vueSet(state.historyCacheById, videoId, targetRecord)
},
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 318c16706737f..c33a704b7aead 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -70,8 +70,8 @@ const actions = {
if (videoData.timeAdded == null) {
videoData.timeAdded = new Date().getTime()
}
- if (videoData.uniqueId == null) {
- videoData.uniqueId = generateRandomUniqueId()
+ if (videoData.playlistItemId == null) {
+ videoData.playlistItemId = generateRandomUniqueId()
}
})
}
@@ -132,8 +132,8 @@ const actions = {
if (videoData.timeAdded == null) {
videoData.timeAdded = new Date().getTime()
}
- if (videoData.uniqueId == null) {
- videoData.uniqueId = generateRandomUniqueId()
+ if (videoData.playlistItemId == null) {
+ videoData.playlistItemId = generateRandomUniqueId()
}
// For backward compatibility
if (videoData.type == null) {
@@ -153,8 +153,8 @@ const actions = {
if (videoData.timeAdded == null) {
videoData.timeAdded = new Date().getTime()
}
- if (videoData.uniqueId == null) {
- videoData.uniqueId = generateRandomUniqueId()
+ if (videoData.playlistItemId == null) {
+ videoData.playlistItemId = generateRandomUniqueId()
}
// For backward compatibility
if (videoData.type == null) {
@@ -210,9 +210,9 @@ const actions = {
anythingUpdated = true
}
- // Ensure all videos has `uniqueId` property
- if (v.uniqueId == null) {
- v.uniqueId = generateRandomUniqueId()
+ // Ensure all videos has `playlistItemId` property
+ if (v.playlistItemId == null) {
+ v.playlistItemId = generateRandomUniqueId()
anythingUpdated = true
}
@@ -325,8 +325,8 @@ const actions = {
async removeVideo({ commit }, payload) {
try {
- const { _id, uniqueId } = payload
- await DBPlaylistHandlers.deleteVideoIdByPlaylistId(_id, uniqueId)
+ const { _id, playlistItemId } = payload
+ await DBPlaylistHandlers.deleteVideoIdByPlaylistId(_id, playlistItemId)
commit('removeVideo', payload)
} catch (errMessage) {
console.error(errMessage)
@@ -394,7 +394,7 @@ const mutations = {
removeVideo(state, payload) {
const playlist = state.playlists.find(playlist => playlist._id === payload._id)
if (playlist) {
- playlist.videos = playlist.videos.filter(video => video.uniqueId !== payload.uniqueId)
+ playlist.videos = playlist.videos.filter(video => video.playlistItemId !== payload.playlistItemId)
}
},
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index 22030368d0644..3cf25602f2cdc 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -287,8 +287,8 @@ const actions = {
// Not when a prompt is displayed
// 'timeAdded',
- // `uniqueId` should be generated anyway
- // 'uniqueId',
+ // `playlistItemId` should be generated anyway
+ // 'playlistItemId',
// `type` should be added in action anyway
// 'type',
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 96b3ab917d9d8..c9f65b31bf841 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -44,7 +44,7 @@ export default defineComponent({
playlistTitle: '',
playlistDescription: '',
firstVideoId: '',
- firstVideoUniqueId: '',
+ firstVideoPlaylistItemId: '',
playlistThumbnail: '',
viewCount: 0,
videoCount: 0,
@@ -273,10 +273,10 @@ export default defineComponent({
if (playlist.videos.length > 0) {
this.firstVideoId = playlist.videos[0].videoId
- this.firstVideoUniqueId = playlist.videos[0].uniqueId
+ this.firstVideoPlaylistItemId = playlist.videos[0].playlistItemId
} else {
this.firstVideoId = ''
- this.firstVideoUniqueId = ''
+ this.firstVideoPlaylistItemId = ''
}
this.viewCount = 0
this.videoCount = playlist.videos.length
@@ -324,10 +324,10 @@ export default defineComponent({
})
},
- moveVideoUp: function (videoId, uniqueId) {
+ moveVideoUp: function (videoId, playlistItemId) {
const playlistItems = [].concat(this.playlistItems)
const videoIndex = playlistItems.findIndex((video) => {
- return video.videoId === videoId && video.uniqueId === uniqueId
+ return video.videoId === videoId && video.playlistItemId === playlistItemId
})
if (videoIndex === 0) {
@@ -356,10 +356,10 @@ export default defineComponent({
}
},
- moveVideoDown: function (videoId, uniqueId) {
+ moveVideoDown: function (videoId, playlistItemId) {
const playlistItems = [].concat(this.playlistItems)
const videoIndex = playlistItems.findIndex((video) => {
- return video.videoId === videoId && video.uniqueId === uniqueId
+ return video.videoId === videoId && video.playlistItemId === playlistItemId
})
if (videoIndex + 1 === playlistItems.length || videoIndex + 1 > playlistItems.length) {
@@ -388,12 +388,12 @@ export default defineComponent({
}
},
- removeVideoFromPlaylist: function (videoId, uniqueId) {
+ removeVideoFromPlaylist: function (videoId, playlistItemId) {
try {
this.removeVideo({
_id: this.playlistId,
videoId: videoId,
- uniqueId: uniqueId,
+ playlistItemId: playlistItemId,
})
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: this.playlistId })
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index d94852bc73dd9..7ff8f7aca6fc8 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -9,7 +9,7 @@
v-if="!isLoading"
:id="playlistId"
:first-video-id="firstVideoId"
- :first-video-unique-id="firstVideoUniqueId"
+ :first-video-playlist-item-id="firstVideoPlaylistItemId"
:playlist-thumbnail="playlistThumbnail"
:title="playlistTitle"
:channel-name="channelName"
@@ -40,7 +40,7 @@
>
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index 93233184ccae4..28e989ee9e0b0 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -122,7 +122,7 @@ export default defineComponent({
watchingPlaylist: false,
playlistId: '',
playlistType: '',
- uniqueId: null,
+ playlistItemId: null,
timestamp: null,
playNextTimeout: null,
playNextCountDownIntervalId: null,
@@ -1081,7 +1081,7 @@ export default defineComponent({
// Whether there is a playlist ID or not, save it
lastViewedPlaylistId: this.playlistId,
lastViewedPlaylistType: this.playlistType,
- lastViewedUniqueId: this.uniqueId,
+ lastViewedPlaylistItemId: this.playlistItemId,
})
},
@@ -1137,11 +1137,11 @@ export default defineComponent({
}
this.playlistId = this.$route.query.playlistId
- this.uniqueId = this.$route.query.uniqueId
+ this.playlistItemId = this.$route.query.playlistItemId
if (this.playlistId == null || this.playlistId.length === 0) {
this.playlistType = ''
- this.uniqueId = null
+ this.playlistItemId = null
this.watchingPlaylist = false
return
}
@@ -1160,7 +1160,7 @@ export default defineComponent({
this.playlistType = this.$route.query.playlistType
if (this.playlistType !== 'user') {
// Remote playlist
- this.uniqueId = null
+ this.playlistItemId = null
this.watchingPlaylist = true
return
}
@@ -1171,7 +1171,7 @@ export default defineComponent({
// Clear playlist data so that watch history will be properly updated
this.playlistId = ''
this.playlistType = ''
- this.uniqueId = null
+ this.playlistItemId = null
}
this.watchingPlaylist = this.selectedUserPlaylist != null
},
diff --git a/src/renderer/views/Watch/Watch.vue b/src/renderer/views/Watch/Watch.vue
index 21dba1c046e0e..b905411938262 100644
--- a/src/renderer/views/Watch/Watch.vue
+++ b/src/renderer/views/Watch/Watch.vue
@@ -173,7 +173,7 @@
:watch-view-loading="isLoading"
:playlist-id="playlistId"
:video-id="videoId"
- :unique-id="uniqueId"
+ :playlist-item-id="playlistItemId"
class="watchVideoSideBar watchVideoPlaylist"
:class="{ theatrePlaylist: useTheatreMode }"
@pause-player="pausePlayer"
From 847ae77d82dde1857bbaf843d38f17d334397715 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 19 Oct 2023 14:43:23 +0800
Subject: [PATCH 172/236] * Ensure local playlist ID won't conflict with remote
playlist ID
---
src/renderer/store/modules/playlists.js | 2 +-
src/renderer/views/Watch/Watch.js | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index c33a704b7aead..25fc48f2d0ac7 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -2,7 +2,7 @@ import crypto from 'crypto'
import { DBPlaylistHandlers } from '../../../datastores/handlers/index'
function generateRandomPlaylistId() {
- return `${Date.now()}-${Math.floor(Math.random() * 10000)}`
+ return `ft-playlist--${generateRandomUniqueId()}`
}
function generateRandomPlaylistName() {
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index 28e989ee9e0b0..93f397210f6da 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -1149,7 +1149,6 @@ export default defineComponent({
// `playlistId` present
if (this.selectedUserPlaylist != null) {
// If playlist ID matches a user playlist, it must be user playlist
- // (Assuming FT never generates an ID same as a remote playlist)
this.playlistType = 'user'
this.watchingPlaylist = true
return
From 8bc5f2de82004bd04396b2f2abad5d40ff1b2336 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 19 Oct 2023 16:26:56 +0800
Subject: [PATCH 173/236] - Remove import video while creating playlist related
code
---
.../ft-create-playlist-prompt/ft-create-playlist-prompt.js | 6 +-----
.../ft-create-playlist-prompt/ft-create-playlist-prompt.vue | 6 ------
.../ft-playlist-add-video-prompt.js | 1 -
src/renderer/store/modules/utils.js | 4 ++--
src/renderer/views/UserPlaylists/UserPlaylists.js | 1 -
5 files changed, 3 insertions(+), 15 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index 10689810a4f16..96ffb97c873c9 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -31,9 +31,6 @@ export default Vue.extend({
newPlaylistVideoObject: function () {
return this.$store.getters.getNewPlaylistVideoObject
},
- videoImportLength: function () {
- return this.newPlaylistVideoObject.videos.length
- },
},
mounted: function () {
this.lastActiveElement = document.activeElement
@@ -62,12 +59,11 @@ export default Vue.extend({
return
}
- const videosObject = (this.videoImportLength > 0 ? this.newPlaylistVideoObject.videos : [])
const playlistObject = {
playlistName: this.playlistName,
protected: false,
description: '',
- videos: videosObject,
+ videos: [],
}
try {
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
index 247715c280022..90433a2d8f368 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
@@ -18,12 +18,6 @@
@click="createNewPlaylist"
/>
-
- {{ videoImportLength }} video(s) will also be imported when created
-
Date: Thu, 19 Oct 2023 16:23:16 +0800
Subject: [PATCH 174/236] * Make text translatable
---
.../ft-create-playlist-prompt.vue | 8 ++---
.../ft-list-video/ft-list-video.vue | 8 ++---
.../ft-playlist-add-video-prompt.vue | 16 +++++----
.../playlist-info/playlist-info.vue | 20 +++++------
.../privacy-settings/privacy-settings.vue | 4 +--
.../watch-video-info/watch-video-info.vue | 2 +-
src/renderer/views/Playlist/Playlist.vue | 2 +-
.../views/UserPlaylists/UserPlaylists.vue | 2 +-
static/locales/en-US.yaml | 33 +++++++++++++++++++
9 files changed, 66 insertions(+), 29 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
index 90433a2d8f368..ea85bf3012560 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
@@ -3,12 +3,12 @@
@click="hideCreatePlaylistPrompt"
>
- New Playlist Name
+ {{ $t('User Playlists.CreatePlaylistPrompt.New Playlist Name') }}
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 a31a65547b3c8..58e91cb2b11bf 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -47,7 +47,7 @@
- Select a Playlist to add your {{ toBeAddedToPlaylistVideoCount }} video(s) to
+ {{ $tc('User Playlists.AddVideoPrompt.Select a playlist to add your N videos to', toBeAddedToPlaylistVideoCount, {
+ videoCount: toBeAddedToPlaylistVideoCount,
+ }) }}
- {{ selectedPlaylistCount }} Selected
+ {{ $tc('User Playlists.AddVideoPrompt.N playlists selected', selectedPlaylistCount, {
+ playlistCount: selectedPlaylistCount,
+ }) }}
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 292bf3245511a..5ebcafb703db0 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -25,7 +25,7 @@
- This playlist currently has no videos.
+ {{ $t("User Playlists['This playlist currently has no videos.']") }}
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index 9bbe7bb64836a..7743c2d0753ec 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -42,7 +42,7 @@
v-if="fullData.length === 0"
>
- You have no playlist. Click on the create new playlist button to create a new one.
+ {{ $t("User Playlists['You have no playlist. Click on the create new playlist button to create a new one.']") }}
Date: Sat, 21 Oct 2023 15:05:54 +0800
Subject: [PATCH 175/236] * Make sort option text translatable
---
.../ft-playlist-add-video-prompt.js | 30 +++++++++------
.../ft-playlist-add-video-prompt.vue | 2 +-
.../views/UserPlaylists/UserPlaylists.js | 37 ++++++++++++-------
.../views/UserPlaylists/UserPlaylists.vue | 2 +-
static/locales/en-US.yaml | 15 ++++++++
5 files changed, 59 insertions(+), 27 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index f4201dcd288c8..bd2da4f32cc8a 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -21,16 +21,6 @@ const SORT_BY_VALUES = {
LatestUpdatedFirst: 'latest_updated_first',
EarliestUpdatedFirst: 'earliest_updated_first',
}
-const SORT_BY_NAMES = {
- NameAscending: 'A-Z',
- NameDescending: 'Z-A',
-
- LatestCreatedFirst: 'Recently Created',
- EarliestCreatedFirst: 'Earliest Created',
-
- LatestUpdatedFirst: 'Recently Updated',
- EarliestUpdatedFirst: 'Earliest Updated',
-}
export default Vue.extend({
name: 'FtPlaylistAddVideoPrompt',
@@ -139,7 +129,25 @@ export default Vue.extend({
},
sortBySelectNames() {
- return Object.keys(SORT_BY_VALUES).map(k => SORT_BY_NAMES[k])
+ return Object.values(SORT_BY_VALUES).map((k) => {
+ switch (k) {
+ case SORT_BY_VALUES.NameAscending:
+ return this.$t('User Playlists.Sort By.NameAscending')
+ case SORT_BY_VALUES.NameDescending:
+ return this.$t('User Playlists.Sort By.NameDescending')
+ case SORT_BY_VALUES.LatestCreatedFirst:
+ return this.$t('User Playlists.Sort By.LatestCreatedFirst')
+ case SORT_BY_VALUES.EarliestCreatedFirst:
+ return this.$t('User Playlists.Sort By.EarliestCreatedFirst')
+ case SORT_BY_VALUES.LatestUpdatedFirst:
+ return this.$t('User Playlists.Sort By.LatestUpdatedFirst')
+ case SORT_BY_VALUES.EarliestUpdatedFirst:
+ return this.$t('User Playlists.Sort By.EarliestUpdatedFirst')
+ default:
+ console.error(`Unknown sortBy: ${k}`)
+ return k
+ }
+ })
},
sortBySelectValues() {
return Object.values(SORT_BY_VALUES)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index c8e1f2443fa75..773b406fe429d 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -28,7 +28,7 @@
:value="sortBy"
:select-names="sortBySelectNames"
:select-values="sortBySelectValues"
- :placeholder="'Sort By'"
+ :placeholder="$t('User Playlists.Sort By.Sort By')"
@change="sortBy = $event"
/>
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index 9f9c28019be4b..3f98d0c746c3f 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -24,19 +24,6 @@ const SORT_BY_VALUES = {
LatestPlayedFirst: 'latest_played_first',
EarliestPlayedFirst: 'earliest_played_first',
}
-const SORT_BY_NAMES = {
- NameAscending: 'A-Z',
- NameDescending: 'Z-A',
-
- LatestCreatedFirst: 'Recently Created',
- EarliestCreatedFirst: 'Earliest Created',
-
- LatestUpdatedFirst: 'Recently Updated',
- EarliestUpdatedFirst: 'Earliest Updated',
-
- LatestPlayedFirst: 'Recently Played',
- EarliestPlayedFirst: 'Earliest Played',
-}
export default defineComponent({
name: 'UserPlaylists',
@@ -149,7 +136,29 @@ export default defineComponent({
},
sortBySelectNames() {
- return Object.keys(SORT_BY_VALUES).map(k => SORT_BY_NAMES[k])
+ return Object.values(SORT_BY_VALUES).map((k) => {
+ switch (k) {
+ case SORT_BY_VALUES.NameAscending:
+ return this.$t('User Playlists.Sort By.NameAscending')
+ case SORT_BY_VALUES.NameDescending:
+ return this.$t('User Playlists.Sort By.NameDescending')
+ case SORT_BY_VALUES.LatestCreatedFirst:
+ return this.$t('User Playlists.Sort By.LatestCreatedFirst')
+ case SORT_BY_VALUES.EarliestCreatedFirst:
+ return this.$t('User Playlists.Sort By.EarliestCreatedFirst')
+ case SORT_BY_VALUES.LatestUpdatedFirst:
+ return this.$t('User Playlists.Sort By.LatestUpdatedFirst')
+ case SORT_BY_VALUES.EarliestUpdatedFirst:
+ return this.$t('User Playlists.Sort By.EarliestUpdatedFirst')
+ case SORT_BY_VALUES.LatestPlayedFirst:
+ return this.$t('User Playlists.Sort By.LatestPlayedFirst')
+ case SORT_BY_VALUES.EarliestPlayedFirst:
+ return this.$t('User Playlists.Sort By.EarliestPlayedFirst')
+ default:
+ console.error(`Unknown sortBy: ${k}`)
+ return k
+ }
+ })
},
sortBySelectValues() {
return Object.values(SORT_BY_VALUES)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index 7743c2d0753ec..5a39a0180989d 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -34,7 +34,7 @@
:value="sortBy"
:select-names="sortBySelectNames"
:select-values="sortBySelectValues"
- :placeholder="'Sort By'"
+ :placeholder="$t('User Playlists.Sort By.Sort By')"
@change="sortBy = $event"
/>
diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml
index ba1ac1eb344b6..036b82fffd013 100644
--- a/static/locales/en-US.yaml
+++ b/static/locales/en-US.yaml
@@ -162,6 +162,21 @@ User Playlists:
Delete Playlist: Delete Playlist
Are you sure you want to delete this playlist? This cannot be undone.: Are you sure you want to delete this playlist? This cannot be undone.
+ Sort By:
+ Sort By: Sort By
+
+ NameAscending: 'A-Z'
+ NameDescending: 'Z-A'
+
+ LatestCreatedFirst: 'Recently Created'
+ EarliestCreatedFirst: 'Earliest Created'
+
+ LatestUpdatedFirst: 'Recently Updated'
+ EarliestUpdatedFirst: 'Earliest Updated'
+
+ LatestPlayedFirst: 'Recently Played'
+ EarliestPlayedFirst: 'Earliest Played'
+
AddVideoPrompt:
Select a playlist to add your N videos to: 'Select a playlist to add your video to | Select a playlist to add your {videoCount} videos to'
N playlists selected: '{playlistCount} Selected'
From 2803d212fed652e937c40a5046f2b1a2745ac7a1 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 27 Oct 2023 08:22:52 +0800
Subject: [PATCH 176/236] ! Fix reverse condition
---
src/renderer/components/watch-video-info/watch-video-info.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index 9aa46d495feff..5ec0e40836b90 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -259,7 +259,7 @@ export default defineComponent({
playlistLoop: this.getPlaylistLoop(),
}
// Only play video in non playlist mode when user playlist detected
- if (!this.inUserPlaylist) {
+ if (this.inUserPlaylist) {
Object.assign(payload, {
playlistId: null,
playlistIndex: null,
From 9b2162c68be0f57317bbe4c005082e8515578d73 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 27 Oct 2023 08:24:28 +0800
Subject: [PATCH 177/236] $ Just use ?.
---
.../ft-create-playlist-prompt/ft-create-playlist-prompt.js | 4 +---
.../ft-playlist-add-video-prompt.js | 4 +---
src/renderer/components/ft-prompt/ft-prompt.js | 4 +---
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index 96ffb97c873c9..f745913f01d64 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -40,9 +40,7 @@ export default Vue.extend({
this.$refs.playlistNameInput.focus()
},
destroyed() {
- if (this.lastActiveElement != null) {
- this.lastActiveElement.focus()
- }
+ this.lastActiveElement?.focus()
},
methods: {
createNewPlaylist: function () {
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index bd2da4f32cc8a..6c3f22018e289 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -196,9 +196,7 @@ export default Vue.extend({
this.$refs.searchBar.focus()
},
destroyed() {
- if (this.lastActiveElement != null) {
- this.lastActiveElement.focus()
- }
+ this.lastActiveElement?.focus()
},
methods: {
hide: function () {
diff --git a/src/renderer/components/ft-prompt/ft-prompt.js b/src/renderer/components/ft-prompt/ft-prompt.js
index 7d87c4c671679..ca689a9bd5e68 100644
--- a/src/renderer/components/ft-prompt/ft-prompt.js
+++ b/src/renderer/components/ft-prompt/ft-prompt.js
@@ -68,9 +68,7 @@ export default defineComponent({
this.focusItem(0)
},
destroyed() {
- if (this.lastActiveElement != null) {
- this.lastActiveElement.focus()
- }
+ this.lastActiveElement?.focus()
},
methods: {
hide: function() {
From 204da2d5120630a210e36898bd4dc2a19a64cb78 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 28 Oct 2023 09:55:31 +0800
Subject: [PATCH 178/236] Code review changes
---
.../ft-create-playlist-prompt.js | 4 ++--
...video-prompt.scss => ft-playlist-add-video-prompt.css} | 8 ++++----
.../ft-playlist-add-video-prompt.js | 4 ++--
.../ft-playlist-add-video-prompt.vue | 4 ++--
.../ft-playlist-selector/ft-playlist-selector.js | 6 +++---
.../components/ft-share-button/ft-share-button.js | 3 +--
src/renderer/components/playlist-info/playlist-info.js | 2 +-
.../watch-video-playlist/watch-video-playlist.js | 3 +--
src/renderer/views/Playlist/Playlist.js | 3 +--
src/renderer/views/Watch/Watch.js | 3 +--
10 files changed, 18 insertions(+), 22 deletions(-)
rename src/renderer/components/ft-playlist-add-video-prompt/{ft-playlist-add-video-prompt.scss => ft-playlist-add-video-prompt.css} (85%)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index f745913f01d64..967c72e5c7a31 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -1,4 +1,4 @@
-import Vue from 'vue'
+import { defineComponent } from 'vue'
import { mapActions } from 'vuex'
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
import FtPrompt from '../ft-prompt/ft-prompt.vue'
@@ -9,7 +9,7 @@ import {
showToast,
} from '../../helpers/utils'
-export default Vue.extend({
+export default defineComponent({
name: 'FtCreatePlaylistPrompt',
components: {
FtFlexBox,
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
similarity index 85%
rename from src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
rename to src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
index bc493b103fa4c..9eaf79f2b33bd 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.scss
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
@@ -20,12 +20,12 @@
text-align: center;
}
-// Style for `ft-prompt`
+/* Style for `ft-prompt` */
:deep(.promptCard) {
- // Currently only this prompt has enough content to make prompt too high
+ /* Currently only this prompt has enough content to make prompt too high */
max-block-size: 95%;
- // Some child(s) will grow vertically
+ /* Some child(s) will grow vertically */
display: flex;
flex-direction: column;
}
@@ -38,7 +38,7 @@
.playlists-container {
box-shadow: inset 0 0 5px rgba(0,0,0,.5);
- // Use remaining height
+ /* Use remaining height */
flex-grow: 1;
overflow-y: scroll;
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 6c3f22018e289..fc46912ada43d 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -1,4 +1,4 @@
-import Vue from 'vue'
+import { defineComponent } from 'vue'
import { mapActions } from 'vuex'
import debounce from 'lodash.debounce'
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
@@ -22,7 +22,7 @@ const SORT_BY_VALUES = {
EarliestUpdatedFirst: 'earliest_updated_first',
}
-export default Vue.extend({
+export default defineComponent({
name: 'FtPlaylistAddVideoPrompt',
components: {
'ft-flex-box': FtFlexBox,
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 773b406fe429d..2c82b04247441 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -35,7 +35,7 @@
-
+
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
index e865056593e9f..50a5008932e1c 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js
@@ -1,8 +1,8 @@
-import Vue from 'vue'
+import { defineComponent } from 'vue'
import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
import { mapActions } from 'vuex'
-export default Vue.extend({
+export default defineComponent({
name: 'FtPlaylistSelector',
components: {
'ft-icon-button': FtIconButton
@@ -47,7 +47,7 @@ export default Vue.extend({
return `${this.title.substring(0, 255)}...`
},
},
- mounted: function () {
+ created: function () {
this.parseUserData()
},
methods: {
diff --git a/src/renderer/components/ft-share-button/ft-share-button.js b/src/renderer/components/ft-share-button/ft-share-button.js
index 1ecbf7a59d0e8..1cb7c2a58e0dc 100644
--- a/src/renderer/components/ft-share-button/ft-share-button.js
+++ b/src/renderer/components/ft-share-button/ft-share-button.js
@@ -63,8 +63,7 @@ export default defineComponent({
},
selectedUserPlaylist: function () {
- if (this.playlistId == null) { return null }
- if (this.playlistId === '') { return null }
+ if (this.playlistId == null || this.playlistId === '') { return null }
return this.$store.getters.getPlaylist(this.playlistId)
},
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index c9b4fc6bc76a8..a50c7e51f5185 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -183,7 +183,7 @@ export default defineComponent({
return !this.hideSharingActions
},
},
- mounted: function () {
+ created: function () {
this.newTitle = this.title
this.newDescription = this.description
},
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index dfcd0f8a941f9..8e67137f2952f 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -63,8 +63,7 @@ export default defineComponent({
return this.$store.getters.getPlaylistsReady
},
selectedUserPlaylist: function () {
- if (this.playlistId == null) { return null }
- if (this.playlistId === '') { return null }
+ if (this.playlistId == null || this.playlistId === '') { return null }
return this.$store.getters.getPlaylist(this.playlistId)
},
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index c9f65b31bf841..1039cd691b7f1 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -80,8 +80,7 @@ export default defineComponent({
return this.$store.getters.getPlaylistsReady
},
selectedUserPlaylist: function () {
- if (this.playlistId == null) { return null }
- if (this.playlistId === '') { return null }
+ if (this.playlistId == null || this.playlistId === '') { return null }
return this.$store.getters.getPlaylist(this.playlistId)
},
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index 93f397210f6da..f2482a3aebb43 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -220,8 +220,7 @@ export default defineComponent({
return this.$store.getters.getPlaylistsReady
},
selectedUserPlaylist: function () {
- if (this.playlistId == null) { return null }
- if (this.playlistId === '') { return null }
+ if (this.playlistId == null || this.playlistId === '') { return null }
return this.$store.getters.getPlaylist(this.playlistId)
},
From 7788e62d69fef7100b806bafc19c5b8b796bb164 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 28 Oct 2023 10:00:00 +0800
Subject: [PATCH 179/236] Spaces
---
.../ft-playlist-selector.scss | 50 ++++++++++++++++---
1 file changed, 42 insertions(+), 8 deletions(-)
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
index 37d75eef84fa2..10c15ae191d4a 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
@@ -62,6 +62,7 @@ $watched-transition-duration: 0.5s;
opacity: 0.3;
}
}
+
&.selected {
background-color: var(--bg-color);
@include low-contrast-when-watched(var(--primary-text-color));
@@ -71,12 +72,14 @@ $watched-transition-duration: 0.5s;
transition-duration: $watched-transition-duration;
}
}
+
.videoThumbnail {
position: relative;
.thumbnailLink {
display: flex;
}
+
.videoWatched {
position: absolute;
inset-block-start: 0;
@@ -86,21 +89,26 @@ $watched-transition-duration: 0.5s;
background-color: var(--bg-color);
pointer-events: none;
}
+
.videoDuration {
position: absolute;
- inset-block-end: 4px;
- inset-inline-end: 4px;
- padding-block: 3px;
- padding-inline: 4px;
- line-height: 1.2;
- font-size: 15px;
+
border-radius: 5px;
margin: 0;
+
opacity: $thumbnail-overlay-opacity;
color: var(--primary-text-color);
background-color: var(--card-bg-color);
pointer-events: none;
+ inset-block-end: 4px;
+ inset-inline-end: 4px;
+ padding-block: 3px;
+ padding-inline: 4px;
+
+ line-height: 1.2;
+ font-size: 15px;
+
&.live {
background-color: #f22;
color: #fff;
@@ -109,32 +117,44 @@ $watched-transition-duration: 0.5s;
font-size: 12px;
}
}
+
.externalPlayerIcon {
position: absolute;
+
inset-block-end: 4px;
inset-inline-start: 4px;
+
font-size: 17px;
opacity: $thumbnail-overlay-opacity;
}
+
.playlistIcon {
position: absolute;
+
inset-block-start: 40px;
inset-inline-end: 3px;
+
font-size: 17px;
opacity: $thumbnail-overlay-opacity;
}
+
.watchedProgressBar {
- block-size: 2px;
position: absolute;
+ z-index: 2;
+
+ block-size: 2px;
inset-block-end: 0;
+
background-color: var(--primary-color);
- z-index: 2;
}
+
.videoCountContainer {
position: absolute;
+
inset-inline-end: 0;
inset-block: 0;
inline-size: 60px;
+
font-size: 20px;
.background,
@@ -142,19 +162,23 @@ $watched-transition-duration: 0.5s;
position: absolute;
inset: 0;
}
+
.background {
background-color: var(--bg-color);
opacity: 0.9;
}
+
.inner {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
+
color: var(--primary-text-color);
}
}
}
+
.channelThumbnail {
display: flex;
justify-content: center;
@@ -164,6 +188,7 @@ $watched-transition-duration: 0.5s;
border-radius: 50%;
}
}
+
.info {
flex: 1;
position: relative;
@@ -171,9 +196,11 @@ $watched-transition-duration: 0.5s;
.optionsButton {
float: right; // ohhhh man, float was finally the right choice for something;
}
+
.externalPlayerButton {
float: right;
}
+
.title {
font-size: 20px;
@include low-contrast-when-watched(var(--primary-text-color));
@@ -185,6 +212,7 @@ $watched-transition-duration: 0.5s;
font-size: 15px;
}
}
+
.infoLine {
margin-block-start: 5px;
font-size: 14px;
@@ -199,6 +227,7 @@ $watched-transition-duration: 0.5s;
@include low-contrast-when-watched(var(--secondary-text-color));
}
}
+
.description {
font-size: 14px;
max-block-size: 50px;
@@ -206,9 +235,11 @@ $watched-transition-duration: 0.5s;
@include low-contrast-when-watched(var(--secondary-text-color));
}
}
+
&.grid {
display: flex;
flex-direction: column;
+
inline-size: 245px;
min-block-size: 230px;
padding-block-end: 20px;
@@ -228,6 +259,7 @@ $watched-transition-duration: 0.5s;
}
.infoLine {
margin-block-start: 8px;
+
font-size: 13px;
}
}
@@ -240,7 +272,9 @@ $watched-transition-duration: 0.5s;
.selectedIcon {
position: absolute;
+
inset-block-start: calc(50% - 25px);
inset-inline-start: calc(50% - 25px);
+
font-size: 50px;
}
From 68a9bde2caeeffd96b8cb09a7f523d713e6534d0 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 28 Oct 2023 10:04:43 +0800
Subject: [PATCH 180/236] beforeDestroy
---
.../ft-create-playlist-prompt/ft-create-playlist-prompt.js | 2 +-
.../ft-playlist-add-video-prompt.js | 2 +-
src/renderer/components/ft-prompt/ft-prompt.js | 4 +---
3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index 967c72e5c7a31..dde0fcbc667e6 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -39,7 +39,7 @@ export default defineComponent({
// Faster to input required playlist name
this.$refs.playlistNameInput.focus()
},
- destroyed() {
+ beforeDestroy() {
this.lastActiveElement?.focus()
},
methods: {
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index fc46912ada43d..64a06f9756484 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -195,7 +195,7 @@ export default defineComponent({
// User might want to search first if they have many playlists
this.$refs.searchBar.focus()
},
- destroyed() {
+ beforeDestroy() {
this.lastActiveElement?.focus()
},
methods: {
diff --git a/src/renderer/components/ft-prompt/ft-prompt.js b/src/renderer/components/ft-prompt/ft-prompt.js
index ca689a9bd5e68..fab05c6daa5cb 100644
--- a/src/renderer/components/ft-prompt/ft-prompt.js
+++ b/src/renderer/components/ft-prompt/ft-prompt.js
@@ -54,6 +54,7 @@ export default defineComponent({
},
beforeDestroy: function () {
document.removeEventListener('keydown', this.closeEventFunction, true)
+ this.lastActiveElement?.focus()
},
mounted: function () {
this.lastActiveElement = document.activeElement
@@ -67,9 +68,6 @@ export default defineComponent({
})
this.focusItem(0)
},
- destroyed() {
- this.lastActiveElement?.focus()
- },
methods: {
hide: function() {
this.$emit('click', null)
From ed6beb33b18f428e475f7b15f97c2c92011e4ac5 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 28 Oct 2023 10:04:54 +0800
Subject: [PATCH 181/236] Remove unused methods
---
.../watch-video-info/watch-video-info.js | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js
index 5ec0e40836b90..2a123929937e0 100644
--- a/src/renderer/components/watch-video-info/watch-video-info.js
+++ b/src/renderer/components/watch-video-info/watch-video-info.js
@@ -271,20 +271,6 @@ export default defineComponent({
this.openInExternalPlayer(payload)
},
- handleFormatChange: function (format) {
- switch (format) {
- case 'dash':
- this.$parent.enableDashFormat()
- break
- case 'legacy':
- this.$parent.enableLegacyFormat()
- break
- case 'audio':
- this.$parent.enableAudioFormat()
- break
- }
- },
-
handleDownload: function (index) {
const selectedDownloadLinkOption = this.downloadLinkOptions[index]
const url = selectedDownloadLinkOption.value
From a03261632081bf028cd4eba20cd5abd88f21b298 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 28 Oct 2023 10:07:24 +0800
Subject: [PATCH 182/236] Remove infoData
---
src/renderer/views/Playlist/Playlist.js | 30 +------------------------
1 file changed, 1 insertion(+), 29 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 1039cd691b7f1..89983e156771b 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -166,21 +166,6 @@ export default defineComponent({
channelName = subtitle.substring(0, index).trim()
}
- this.infoData = {
- id: this.playlistId,
- title: result.info.title,
- description: result.info.description ?? '',
- firstVideoId: result.items[0].id,
- playlistThumbnail: result.info.thumbnails[0].url,
- viewCount: extractNumberFromString(result.info.views),
- videoCount: extractNumberFromString(result.info.total_items),
- lastUpdated: result.info.last_updated ?? '',
- channelName,
- channelThumbnail: result.info.author?.best_thumbnail?.url ?? '',
- channelId: result.info.author?.id,
- infoSource: 'local'
- }
-
this.playlistTitle = result.info.title
this.playlistDescription = result.info.description ?? ''
this.firstVideoId = result.items[0].id
@@ -219,19 +204,6 @@ export default defineComponent({
getPlaylistInvidious: function () {
invidiousGetPlaylistInfo(this.playlistId).then((result) => {
- this.infoData = {
- id: result.playlistId,
- title: result.title,
- description: result.description,
- firstVideoId: result.videos[0].videoId,
- viewCount: result.viewCount,
- videoCount: result.videoCount,
- channelName: result.author,
- channelThumbnail: youtubeImageUrlToInvidious(result.authorThumbnails[2].url, this.currentInvidiousInstance),
- channelId: result.authorId,
- infoSource: 'invidious'
- }
-
this.playlistTitle = result.title
this.playlistDescription = result.description
this.firstVideoId = result.videos[0].videoId
@@ -292,7 +264,7 @@ export default defineComponent({
},
getNextPage: function () {
- switch (this.infoData.infoSource) {
+ switch (this.infoSource) {
case 'local':
this.getNextPageLocal()
break
From cb874e3b405df882074603febb13651250b7f2bb Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 1 Nov 2023 08:46:05 +0800
Subject: [PATCH 183/236] filter > find
---
src/renderer/store/modules/playlists.js | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 25fc48f2d0ac7..acc8cad86041a 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -228,18 +228,16 @@ const actions = {
}
})
- const findFavorites = payload.filter((playlist) => {
+ const favoritesPlaylist = payload.find((playlist) => {
return playlist.playlistName === 'Favorites' || playlist._id === 'favorites'
})
- const findWatchLater = payload.filter((playlist) => {
+ const watchLaterPlaylist = payload.find((playlist) => {
return playlist.playlistName === 'Watch Later' || playlist._id === 'watchLater'
})
const defaultFavoritesPlaylist = state.defaultPlaylists.find((e) => e._id === 'favorites')
- if (findFavorites.length > 0) {
+ if (favoritesPlaylist != null) {
// Update existing matching playlist only if it exists
- const favoritesPlaylist = findFavorites[0]
-
if (favoritesPlaylist._id !== defaultFavoritesPlaylist._id || favoritesPlaylist.protected !== defaultFavoritesPlaylist.protected) {
const oldId = favoritesPlaylist._id
favoritesPlaylist._id = defaultFavoritesPlaylist._id
@@ -258,10 +256,8 @@ const actions = {
}
const defaultWatchLaterPlaylist = state.defaultPlaylists.find((e) => e._id === 'watchLater')
- if (findWatchLater.length > 0) {
+ if (watchLaterPlaylist != null) {
// Update existing matching playlist only if it exists
- const watchLaterPlaylist = findWatchLater[0]
-
if (watchLaterPlaylist._id !== defaultWatchLaterPlaylist._id || watchLaterPlaylist.protected !== defaultWatchLaterPlaylist.protected) {
const oldId = watchLaterPlaylist._id
watchLaterPlaylist._id = defaultWatchLaterPlaylist._id
From 2700b2b05d7e879ea9659060ee213fbbb2173665 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 1 Nov 2023 08:49:13 +0800
Subject: [PATCH 184/236] avoid importing `crypto` from NodeJS
---
src/renderer/store/modules/playlists.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index acc8cad86041a..ad79751850abc 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -1,4 +1,3 @@
-import crypto from 'crypto'
import { DBPlaylistHandlers } from '../../../datastores/handlers/index'
function generateRandomPlaylistId() {
@@ -10,7 +9,8 @@ function generateRandomPlaylistName() {
}
function generateRandomUniqueId() {
- return crypto.randomUUID()
+ // To avoid importing `crypto` from NodeJS
+ return crypto.randomUUID ? crypto.randomUUID() : `id-${Date.now()}-${Math.floor(Math.random() * 10000)}`
}
const state = {
From af13308c3fc14a7698d69db6f681a0b8b5413039 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 1 Nov 2023 08:51:10 +0800
Subject: [PATCH 185/236] Compress CSS ruleset
---
src/renderer/scss-partials/_ft-list-item.scss | 15 +++------------
1 file changed, 3 insertions(+), 12 deletions(-)
diff --git a/src/renderer/scss-partials/_ft-list-item.scss b/src/renderer/scss-partials/_ft-list-item.scss
index e7782a8be5491..cbe5f45ac084a 100644
--- a/src/renderer/scss-partials/_ft-list-item.scss
+++ b/src/renderer/scss-partials/_ft-list-item.scss
@@ -157,18 +157,9 @@ $watched-transition-duration: 0.5s;
grid-auto-flow: column;
justify-content: flex-end;
}
- .addToPlaylistIcon {
- font-size: 17px;
- block-size: fit-content;
- }
- .trashIcon {
- font-size: 17px;
- block-size: fit-content;
- }
- .upArrowIcon {
- font-size: 17px;
- block-size: fit-content;
- }
+ .addToPlaylistIcon,
+ .trashIcon,
+ .upArrowIcon,
.downArrowIcon {
font-size: 17px;
block-size: fit-content;
From b668af14f85eee41e820243d6577fe464855c19d Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 1 Nov 2023 08:53:05 +0800
Subject: [PATCH 186/236] $ Remove useless prefix from key
---
.../components/watch-video-playlist/watch-video-playlist.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
index 3104af30e4a6b..730a54b0cb56f 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
@@ -118,7 +118,7 @@
>
From 976f6c7c1c32f1b2507f732bcc1f572ff19ed1fa Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 1 Nov 2023 08:56:58 +0800
Subject: [PATCH 187/236] Use template for element with v-if only
---
.../components/watch-video-playlist/watch-video-playlist.vue | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
index 730a54b0cb56f..a718bd8c44c3c 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
@@ -17,7 +17,7 @@
{{ playlistTitle }}
-
{{ channelName }} -
-
+
From d321aece0b87a50db122e7a82d978f0f507d9bbf Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 1 Nov 2023 09:08:29 +0800
Subject: [PATCH 188/236] Make playlist selector look more selectable (cursor:
pointer)
---
.../ft-playlist-add-video-prompt.css | 5 +++++
.../ft-playlist-add-video-prompt.vue | 18 +++++++++++-------
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
index 9eaf79f2b33bd..1803d371594e5 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
@@ -43,3 +43,8 @@
overflow-y: scroll;
}
+
+.playlist-selector-container {
+ /* Make them look selectable */
+ cursor: pointer;
+}
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 2c82b04247441..ac3664498a894 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -33,15 +33,19 @@
/>
-
+ class="playlist-selector-container"
+ >
+
+
From a14e0dfd4d910cd2b2f9bd5822fdb61717ec804d Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 2 Nov 2023 09:55:06 +0800
Subject: [PATCH 189/236] Translate toast messages and fix remove watched
videos from playlist
---
.../ft-create-playlist-prompt.js | 10 +++---
.../ft-playlist-add-video-prompt.js | 7 ++--
.../components/playlist-info/playlist-info.js | 32 +++++++++----------
.../privacy-settings/privacy-settings.js | 2 +-
.../watch-video-playlist.js | 2 +-
src/renderer/views/Playlist/Playlist.js | 12 +++----
static/locales/en-US.yaml | 25 +++++++++++++++
7 files changed, 60 insertions(+), 30 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index dde0fcbc667e6..09999f1610850 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -45,7 +45,7 @@ export default defineComponent({
methods: {
createNewPlaylist: function () {
if (this.playlistName === '') {
- showToast('Playlist name cannot be empty. Please input a name.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["Playlist name cannot be empty. Please input a name."]'))
return
}
@@ -53,7 +53,7 @@ export default defineComponent({
return playlist.playlistName === this.playlistName
})
if (nameExists !== -1) {
- showToast('There is already a playlist with this name. Please pick a different name.')
+ showToast(this.$t('User Playlists.CreatePlaylistPrompt.Toast["There is already a playlist with this name. Please pick a different name."]'))
return
}
@@ -66,9 +66,11 @@ export default defineComponent({
try {
this.addPlaylist(playlistObject)
- showToast(`Playlist ${this.playlistName} has been successfully created.`)
+ showToast(this.$t('User Playlists.CreatePlaylistPrompt.Toast["Playlist {playlistName} has been successfully created."]', {
+ playlistName: this.playlistName,
+ }))
} catch (e) {
- showToast('There was an issue with creating the playlist.')
+ showToast(this.$t('User Playlists.CreatePlaylistPrompt.Toast["There was an issue with creating the playlist."]'))
console.error(e)
} finally {
this.hideCreatePlaylistPrompt()
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 64a06f9756484..9ad1c79267510 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -216,7 +216,7 @@ export default defineComponent({
const addedPlaylistIds = new Set()
if (this.selectedPlaylistIdList.length === 0) {
- showToast('You haven\'t selected any playlist yet.')
+ showToast(this.$t('User Playlists.AddVideoPrompt.Toast["You haven\'t selected any playlist yet."]'))
return
}
@@ -234,7 +234,10 @@ export default defineComponent({
this.updatePlaylist({ _id: playlist._id })
})
- showToast(`${this.toBeAddedToPlaylistVideoCount} video(s) added to ${addedPlaylistIds.size} playlist(s).`)
+ showToast(this.$t('User Playlists.AddVideoPrompt.Toast["{videoCount} video(s) added to {playlistCount} playlist(s)."]', {
+ videoCount: this.toBeAddedToPlaylistVideoCount,
+ playlistCount: addedPlaylistIds.size,
+ }))
this.hide()
},
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index a50c7e51f5185..d4d877cc2b3d9 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -102,8 +102,8 @@ export default defineComponent({
return this.$store.getters.getCurrentInvidiousInstance
},
- historyCache: function () {
- return this.$store.getters.getHistoryCache
+ historyCacheById: function () {
+ return this.$store.getters.getHistoryCacheById
},
thumbnailPreference: function () {
@@ -190,7 +190,7 @@ export default defineComponent({
methods: {
toggleCopyVideosPrompt: function (force = false) {
if (this.moreVideoDataAvailable && !force) {
- showToast('Some videos in the playlist are not loaded yet. Click here to copy anyway.', 5000, () => {
+ 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)
})
return
@@ -204,7 +204,7 @@ export default defineComponent({
savePlaylistInfo: function () {
if (this.newTitle === '') {
- showToast('Playlist name cannot be empty. Please input a name.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["Playlist name cannot be empty. Please input a name."]'))
return
}
@@ -217,9 +217,9 @@ export default defineComponent({
}
try {
this.updatePlaylist(playlist)
- showToast('Playlist has been updated.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["Playlist has been updated."]'))
} catch (e) {
- showToast('There was an issue with updating this playlist.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["There was an issue with updating this playlist."]'))
console.error(e)
} finally {
this.exitEditMode()
@@ -248,17 +248,13 @@ export default defineComponent({
handleRemoveVideosOnWatchPromptAnswer: function (option) {
if (option === 'yes') {
const videosToWatch = this.selectedUserPlaylist.videos.filter((video) => {
- const watchedIndex = this.historyCache.findIndex((history) => {
- return history.videoId === video.videoId
- })
-
- return watchedIndex === -1
+ return this.historyCacheById[video.videoId] == null
})
const videosRemoved = this.selectedUserPlaylist.videos.length - videosToWatch.length
if (videosRemoved === 0) {
- showToast('There were no videos to remove.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["There were no videos to remove."]'))
this.showRemoveVideosOnWatchPrompt = false
return
}
@@ -272,9 +268,11 @@ export default defineComponent({
}
try {
this.updatePlaylist(playlist)
- showToast(`${videosRemoved} video(s) have been removed.`)
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["{videoCount} video(s) have been removed."]', {
+ videoCount: videosRemoved,
+ }))
} catch (e) {
- showToast('There was an issue with updating this playlist.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["There was an issue with updating this playlist."]'))
console.error(e)
}
}
@@ -284,7 +282,7 @@ export default defineComponent({
handleDeletePlaylistPromptAnswer: function (option) {
if (option === 'yes') {
if (this.selectedUserPlaylist.protected) {
- showToast('This playlist is protected and cannot be removed.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["This playlist is protected and cannot be removed."]'))
} else {
this.removePlaylist(this.id)
this.$router.push(
@@ -292,7 +290,9 @@ export default defineComponent({
path: '/userPlaylists'
}
)
- showToast(`${this.title} has been deleted.`)
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["Playlist {playlistName} has been deleted."]', {
+ playlistName: this.title,
+ }))
}
}
this.showDeletePlaylistPrompt = false
diff --git a/src/renderer/components/privacy-settings/privacy-settings.js b/src/renderer/components/privacy-settings/privacy-settings.js
index b057ac9167d20..e6615e3bfbde9 100644
--- a/src/renderer/components/privacy-settings/privacy-settings.js
+++ b/src/renderer/components/privacy-settings/privacy-settings.js
@@ -120,7 +120,7 @@ export default defineComponent({
if (option !== 'yes') { return }
this.removeAllPlaylists()
- showToast('All playlists have been removed')
+ showToast(this.$t('Settings.Privacy Settings.All playlists have been removed'))
},
...mapActions([
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index 8e67137f2952f..4fc24f84701d7 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -325,7 +325,7 @@ export default defineComponent({
},
playPreviousVideo: function () {
- showToast('Playing previous video')
+ showToast(this.$t('Playing Previous Video'))
const playlistInfo = {
playlistId: this.playlistId
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 89983e156771b..92e22c6523e2f 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -302,7 +302,7 @@ export default defineComponent({
})
if (videoIndex === 0) {
- showToast('This video cannot be moved up.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["This video cannot be moved up."]'))
return
}
@@ -322,7 +322,7 @@ export default defineComponent({
this.updatePlaylist(playlist)
this.playlistItems = playlistItems
} catch (e) {
- showToast('There was an issue with updating this playlist.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["There was an issue with updating this playlist."]'))
console.error(e)
}
},
@@ -334,7 +334,7 @@ export default defineComponent({
})
if (videoIndex + 1 === playlistItems.length || videoIndex + 1 > playlistItems.length) {
- showToast('This video cannot be moved down.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["This video cannot be moved down."]'))
return
}
@@ -354,7 +354,7 @@ export default defineComponent({
this.updatePlaylist(playlist)
this.playlistItems = playlistItems
} catch (e) {
- showToast('There was an issue with updating this playlist.')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["There was an issue with updating this playlist."]'))
console.error(e)
}
},
@@ -368,9 +368,9 @@ export default defineComponent({
})
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: this.playlistId })
- showToast('Video has been removed')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast.Video has been removed'))
} catch (e) {
- showToast('There was a problem with removing this video')
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast.There was a problem with removing this video'))
console.error(e)
}
},
diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml
index 036b82fffd013..f109f0a8b1463 100644
--- a/static/locales/en-US.yaml
+++ b/static/locales/en-US.yaml
@@ -177,14 +177,38 @@ User Playlists:
LatestPlayedFirst: 'Recently Played'
EarliestPlayedFirst: 'Earliest Played'
+ SinglePlaylistView:
+ Toast:
+ This video cannot be moved up.: This video cannot be moved up.
+ This video cannot be moved down.: This video cannot be moved down.
+ Video has been removed: Video has been removed
+ There was a problem with removing this video: There was a problem with removing this video
+
+ Some videos in the playlist are not loaded yet. Click here to copy anyway.: Some videos in the playlist are not loaded yet. Click here to copy anyway.
+ Playlist name cannot be empty. Please input a name.: Playlist name cannot be empty. Please input a name.
+ Playlist has been updated.: Playlist has been updated.
+ There was an issue with updating this playlist.: There was an issue with updating this playlist.
+ "{videoCount} video(s) have been removed.": "{videoCount} video(s) have been removed."
+ There were no videos to remove.: There were no videos to remove.
+ This playlist is protected and cannot be removed.: This playlist is protected and cannot be removed.
+ Playlist {playlistName} has been deleted.: Playlist {playlistName} has been deleted.
AddVideoPrompt:
Select a playlist to add your N videos to: 'Select a playlist to add your video to | Select a playlist to add your {videoCount} videos to'
N playlists selected: '{playlistCount} Selected'
Search in Playlists: Search in Playlists
Save: Save
+
+ Toast:
+ You haven't selected any playlist yet.: You haven't selected any playlist yet.
+ "{videoCount} video(s) added to {playlistCount} playlist(s).": "{videoCount} video(s) added to {playlistCount} playlist(s)."
CreatePlaylistPrompt:
New Playlist Name: New Playlist Name
Create: Create
+
+ Toast:
+ There is already a playlist with this name. Please pick a different name.: There is already a playlist with this name. Please pick a different name.
+ Playlist {playlistName} has been successfully created.: Playlist {playlistName} has been successfully created.
+ There was an issue with creating the playlist.: There was an issue with creating the playlist.
History:
# On History Page
History: History
@@ -377,6 +401,7 @@ Settings:
you sure you want to remove all subscriptions and profiles? This cannot be
undone.
Remove All Playlists: Remove All Playlists
+ All playlists have been removed: All playlists have been removed
Are you sure you want to remove all your playlists?: Are you sure you want to remove all your playlists?
Subscription Settings:
Subscription Settings: Subscription Settings
From 91a3395f1e7e8f592221b361fb144cd74d722202 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 8 Nov 2023 15:23:08 +0800
Subject: [PATCH 190/236] ! Fix translation
---
src/renderer/components/playlist-info/playlist-info.vue | 4 ++--
src/renderer/views/UserPlaylists/UserPlaylists.vue | 2 +-
static/locales/en-US.yaml | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 5ebcafb703db0..58fc479d5d9ba 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -152,14 +152,14 @@
Date: Thu, 16 Nov 2023 15:21:00 +0800
Subject: [PATCH 191/236] - Remove unused methods
---
src/renderer/store/modules/playlists.js | 2 --
src/renderer/views/UserPlaylists/UserPlaylists.js | 4 ----
2 files changed, 6 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index ad79751850abc..26b8ffa527e07 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -40,11 +40,9 @@ const state = {
const getters = {
getPlaylistsReady: () => state.playlistsReady,
getAllPlaylists: () => state.playlists,
- getFavorites: () => state.playlists.find(playlist => playlist._id === 'favorites'),
getPlaylist: (state) => (playlistId) => {
return state.playlists.find(playlist => playlist._id === playlistId)
},
- getWatchLater: () => state.playlists.find(playlist => playlist._id === 'watchLater')
}
const actions = {
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.js b/src/renderer/views/UserPlaylists/UserPlaylists.js
index 3f98d0c746c3f..95e2d01c862cc 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.js
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.js
@@ -54,10 +54,6 @@ export default defineComponent({
return this.$i18n.locale.replace('_', '-')
},
- favoritesPlaylist: function () {
- return this.$store.getters.getFavorites
- },
-
allPlaylists: function () {
const playlists = this.$store.getters.getAllPlaylists
return [].concat(playlists).sort((a, b) => {
From 834cdc522cdc1cb3eb782bc0332f5c02970d7a24 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sun, 19 Nov 2023 16:24:32 +0800
Subject: [PATCH 192/236] $ Remove workaround for issue which cannot be
reproduced anymore
---
.../ft-playlist-add-video-prompt.js | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 9ad1c79267510..1f2e4a4603516 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -120,10 +120,6 @@ export default defineComponent({
})
},
- createPlaylistPromptShown: function () {
- return this.$store.getters.getShowCreatePlaylistPrompt
- },
-
tabindex() {
return this.interactionsLocked ? -1 : 0
},
@@ -176,17 +172,6 @@ export default defineComponent({
// Allow search and easier deselecting new created playlist
this.$refs.searchBar.focus()
},
-
- createPlaylistPromptShown(value) {
- // Lock interactions when create playlist prompt opened
- this.interactionsLocked = value
-
- if (!value) {
- // create playlist prompt closing
- // Solution/Workaround for strange click event
- this.preventOpenCreatePlaylistPromptOnce = true
- }
- },
},
mounted: function () {
this.lastActiveElement = document.activeElement
From 1cd9f7547459da1fd3828c608c46868e33893de3 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sun, 19 Nov 2023 16:31:38 +0800
Subject: [PATCH 193/236] $ Remove remaining useless code following last commit
removing workaround
---
.../ft-playlist-add-video-prompt.js | 8 --------
1 file changed, 8 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 1f2e4a4603516..bf47e109da4a7 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -41,7 +41,6 @@ export default defineComponent({
lastShownAt: Date.now(),
lastActiveElement: null,
interactionsLocked: false,
- preventOpenCreatePlaylistPromptOnce: false,
sortBy: SORT_BY_VALUES.LatestUpdatedFirst,
}
},
@@ -227,13 +226,6 @@ export default defineComponent({
},
openCreatePlaylistPrompt: function () {
- // Solution/Workaround for strange click event
- // Prevents prompt from reopening right after close
- if (this.preventOpenCreatePlaylistPromptOnce) {
- this.preventOpenCreatePlaylistPromptOnce = false
- return
- }
-
this.showCreatePlaylistPrompt({
title: this.newPlaylistDefaultProperties.title || '',
})
From cae3db7c6f5ae4be371d6173bf62829571cba37b Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sun, 19 Nov 2023 16:32:32 +0800
Subject: [PATCH 194/236] you have no playlist > you have no playlists
---
src/renderer/views/UserPlaylists/UserPlaylists.vue | 2 +-
static/locales/en-US.yaml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index 7e1d53f5d464c..b4dedbb6c63c3 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -42,7 +42,7 @@
v-if="fullData.length === 0"
>
- {{ $t("User Playlists['You have no playlist. Click on the create new playlist button to create a new one.']") }}
+ {{ $t("User Playlists['You have no playlists. Click on the create new playlist button to create a new one.']") }}
Date: Sun, 19 Nov 2023 16:39:24 +0800
Subject: [PATCH 195/236] CSS use var --horizontal-directionality-coefficient
---
src/renderer/views/Playlist/Playlist.scss | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/views/Playlist/Playlist.scss b/src/renderer/views/Playlist/Playlist.scss
index 7658b6beb17ae..ce4c347a11217 100644
--- a/src/renderer/views/Playlist/Playlist.scss
+++ b/src/renderer/views/Playlist/Playlist.scss
@@ -54,7 +54,7 @@
}
.playlistItem-enter, .playlistItem-leave-to {
opacity: 0;
- transform: translateX(10%);
+ transform: translate(calc(10% * var(--horizontal-directionality-coefficient)));
}
.videoIndex {
From 00c66f28121f3bee52cbec6802d4bdb5c5d78780 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sun, 19 Nov 2023 16:49:00 +0800
Subject: [PATCH 196/236] * Update danger buttons color to primary (like clear
search cache button)
---
src/renderer/components/playlist-info/playlist-info.vue | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 58fc479d5d9ba..c7d99b86a0177 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -132,14 +132,14 @@
v-if="!editMode && infoSource === 'user' && videoCount > 0"
:title="$t('User Playlists.Remove Watched Videos')"
:icon="['fas', 'eye-slash']"
- theme="secondary"
+ theme="primary"
@click="showRemoveVideosOnWatchPrompt = true"
/>
Date: Sun, 19 Nov 2023 16:55:20 +0800
Subject: [PATCH 197/236] ! Fix playlist icon container size
---
src/renderer/scss-partials/_ft-list-item.scss | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/scss-partials/_ft-list-item.scss b/src/renderer/scss-partials/_ft-list-item.scss
index cbe5f45ac084a..1721483727f9f 100644
--- a/src/renderer/scss-partials/_ft-list-item.scss
+++ b/src/renderer/scss-partials/_ft-list-item.scss
@@ -156,13 +156,13 @@ $watched-transition-duration: 0.5s;
display: grid;
grid-auto-flow: column;
justify-content: flex-end;
+ block-size: fit-content;
}
.addToPlaylistIcon,
.trashIcon,
.upArrowIcon,
.downArrowIcon {
font-size: 17px;
- block-size: fit-content;
}
.watchedProgressBar {
From 69acc98922975e1fa971198d5b292658dc3a7ced Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sun, 19 Nov 2023 16:58:47 +0800
Subject: [PATCH 198/236] ! Fix sorting in add video to playlist prompt when
filtered
---
.../ft-playlist-add-video-prompt.js | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index bf47e109da4a7..4b2bde21370f1 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -113,9 +113,6 @@ export default defineComponent({
if (typeof (playlist.playlistName) !== 'string') { return false }
return playlist.playlistName.toLowerCase().includes(this.processedQuery)
- }).sort((a, b) => {
- // Latest updated first
- return b.lastUpdatedAt - a.lastUpdatedAt
})
},
From 0ef1f8b5022fd422e6d4963ff5d0c2fb69c6dc50 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 20 Nov 2023 11:55:47 +0800
Subject: [PATCH 199/236] $- Update ft-inputs to removed prop input-tabindex
---
.../ft-create-playlist-prompt.vue | 1 -
src/renderer/components/ft-input/ft-input.js | 7 +------
src/renderer/components/ft-input/ft-input.vue | 1 -
.../ft-playlist-add-video-prompt.js | 5 -----
.../ft-playlist-add-video-prompt.vue | 1 -
src/renderer/components/playlist-info/playlist-info.vue | 2 --
6 files changed, 1 insertion(+), 16 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
index ea85bf3012560..33a1bf851d553 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue
@@ -9,7 +9,6 @@
{
switch (k) {
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index ac3664498a894..037f65dd1d925 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -18,7 +18,6 @@
:placeholder="$t('User Playlists.AddVideoPrompt.Search in Playlists')"
:show-clear-text-button="true"
:show-action-button="false"
- :input-tabindex="tabindex"
@input="(input) => updateQueryDebounce(input)"
@clear="updateQueryDebounce('')"
/>
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index c7d99b86a0177..bb6d0a7e776fa 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -26,7 +26,6 @@
v-if="editMode"
ref="playlistTitleInput"
:placeholder="$t('User Playlists.Playlist Name')"
- :input-tabindex="0"
:show-action-button="false"
:show-label="false"
:value="newTitle"
@@ -54,7 +53,6 @@
Date: Tue, 21 Nov 2023 10:05:43 +0800
Subject: [PATCH 200/236] ! Fix vue warning
---
.../ft-playlist-add-video-prompt.vue | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 037f65dd1d925..49b84f675d666 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -38,7 +38,7 @@
class="playlist-selector-container"
>
From d8b149c24d5af18316dc582f4bbc24221e558c79 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 20 Nov 2023 22:13:32 +0800
Subject: [PATCH 201/236] + Add toggle to export playlist for older FT
---
.../components/data-settings/data-settings.js | 57 ++++++++++++++++++-
.../data-settings/data-settings.vue | 11 +++-
static/locales/en-US.yaml | 7 +++
3 files changed, 72 insertions(+), 3 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index 1099013151f1c..4d772feea67de 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -4,6 +4,7 @@ import { mapActions, mapMutations } from 'vuex'
import FtButton from '../ft-button/ft-button.vue'
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
import FtPrompt from '../ft-prompt/ft-prompt.vue'
+import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue'
import { MAIN_PROFILE_ID } from '../../../constants'
import { calculateColorLuminance, getRandomColor } from '../../helpers/colors'
@@ -27,7 +28,8 @@ export default defineComponent({
'ft-settings-section': FtSettingsSection,
'ft-button': FtButton,
'ft-flex-box': FtFlexBox,
- 'ft-prompt': FtPrompt
+ 'ft-prompt': FtPrompt,
+ 'ft-toggle-switch': FtToggleSwitch,
},
data: function () {
return {
@@ -38,7 +40,9 @@ export default defineComponent({
'youtube',
'youtubeold',
'newpipe'
- ]
+ ],
+
+ shouldExportPlaylistForOlderVersions: false,
}
},
computed: {
@@ -1015,6 +1019,55 @@ export default defineComponent({
await this.promptAndWriteToFile(options, JSON.stringify(this.allPlaylists), 'All playlists has been successfully exported')
},
+ exportPlaylistsForOlderVersionsSometimes: function () {
+ if (this.shouldExportPlaylistForOlderVersions) {
+ this.exportPlaylistsForOlderVersions()
+ } else {
+ this.exportPlaylists()
+ }
+ },
+
+ exportPlaylistsForOlderVersions: async function () {
+ const dateStr = getTodayDateStrLocalTimezone()
+ const exportFileName = 'freetube-playlists-for-single-favorites-playlist-' + dateStr + '.db'
+
+ const options = {
+ defaultPath: exportFileName,
+ filters: [
+ {
+ name: 'Database File',
+ extensions: ['db']
+ }
+ ]
+ }
+
+ const favoritesPlaylistData = {
+ playlistName: 'Favorites',
+ protected: true,
+ videos: [],
+ }
+
+ this.allPlaylists.forEach((playlist) => {
+ playlist.videos.forEach((video) => {
+ const videoAlreadyAdded = favoritesPlaylistData.videos.some((v) => {
+ return v.videoId === video.videoId
+ })
+ if (videoAlreadyAdded) { return }
+
+ favoritesPlaylistData.videos.push(
+ Object.assign({
+ // The "required" keys during import (but actually unused) in older versions
+ isLive: false,
+ paid: false,
+ published: '',
+ }, video)
+ )
+ })
+ })
+
+ await this.promptAndWriteToFile(options, JSON.stringify([favoritesPlaylistData]), 'All playlists has been successfully exported')
+ },
+
convertOldFreeTubeFormatToNew(oldData) {
const convertedData = []
for (const channel of oldData) {
diff --git a/src/renderer/components/data-settings/data-settings.vue b/src/renderer/components/data-settings/data-settings.vue
index f9ad92d72087a..c41a5a20661cd 100644
--- a/src/renderer/components/data-settings/data-settings.vue
+++ b/src/renderer/components/data-settings/data-settings.vue
@@ -42,7 +42,16 @@
/>
+
+
+
Date: Wed, 22 Nov 2023 14:12:22 +0800
Subject: [PATCH 202/236] * Update tooltip text
---
.../components/data-settings/data-settings.vue | 1 +
.../components/ft-toggle-switch/ft-toggle-switch.js | 6 +++++-
.../components/ft-toggle-switch/ft-toggle-switch.vue | 1 +
src/renderer/components/ft-tooltip/ft-tooltip.css | 4 ++++
src/renderer/components/ft-tooltip/ft-tooltip.js | 6 +++++-
src/renderer/components/ft-tooltip/ft-tooltip.vue | 5 ++++-
static/locales/en-US.yaml | 12 +++++++-----
7 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.vue b/src/renderer/components/data-settings/data-settings.vue
index c41a5a20661cd..ef1b08377de3a 100644
--- a/src/renderer/components/data-settings/data-settings.vue
+++ b/src/renderer/components/data-settings/data-settings.vue
@@ -51,6 +51,7 @@
:compact="true"
:default-value="shouldExportPlaylistForOlderVersions"
:tooltip="$t('Settings.Data Settings.Export Playlists For Older FreeTube Versions.Tooltip')"
+ :tooltip-allow-newlines="true"
@change="shouldExportPlaylistForOlderVersions = !shouldExportPlaylistForOlderVersions"
/>
diff --git a/src/renderer/components/ft-toggle-switch/ft-toggle-switch.js b/src/renderer/components/ft-toggle-switch/ft-toggle-switch.js
index 0e61f0c464447..06eecd61080c7 100644
--- a/src/renderer/components/ft-toggle-switch/ft-toggle-switch.js
+++ b/src/renderer/components/ft-toggle-switch/ft-toggle-switch.js
@@ -30,7 +30,11 @@ export default defineComponent({
tooltipPosition: {
type: String,
default: 'bottom-left'
- }
+ },
+ tooltipAllowNewlines: {
+ type: Boolean,
+ default: false,
+ },
},
data: function () {
return {
diff --git a/src/renderer/components/ft-toggle-switch/ft-toggle-switch.vue b/src/renderer/components/ft-toggle-switch/ft-toggle-switch.vue
index c57aa4ab054f0..318c7622843dd 100644
--- a/src/renderer/components/ft-toggle-switch/ft-toggle-switch.vue
+++ b/src/renderer/components/ft-toggle-switch/ft-toggle-switch.vue
@@ -29,6 +29,7 @@
class="selectTooltip"
:position="tooltipPosition"
:tooltip="tooltip"
+ :allow-newlines="tooltipAllowNewlines"
/>
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.css b/src/renderer/components/ft-tooltip/ft-tooltip.css
index 1e43b784ef521..8b0375ef59802 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.css
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.css
@@ -92,6 +92,10 @@
transform: translate(calc(-50% * var(--horizontal-directionality-coefficient)), 1em);
}
+.text.allowNewlines {
+ white-space: pre;
+}
+
.tooltip {
display: inline-block;
position: relative;
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.js b/src/renderer/components/ft-tooltip/ft-tooltip.js
index 2b4e61a835c69..66ba1d1dd6209 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.js
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.js
@@ -13,7 +13,11 @@ export default defineComponent({
tooltip: {
type: String,
required: true
- }
+ },
+ allowNewlines: {
+ type: Boolean,
+ default: false,
+ },
},
data() {
const id = `ft-tooltip-${++idCounter}`
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.vue b/src/renderer/components/ft-tooltip/ft-tooltip.vue
index fa8c1b7bc756a..96cea67ff25d1 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.vue
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.vue
@@ -10,7 +10,10 @@
{{ tooltip }}
diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml
index 61d1d39874200..e5fb65c9b1b04 100644
--- a/static/locales/en-US.yaml
+++ b/static/locales/en-US.yaml
@@ -472,11 +472,13 @@ Settings:
Export Playlists: Export Playlists
Export Playlists For Older FreeTube Versions:
Label: Export Playlists For Older FreeTube Versions
- Tooltip: Older FreeTube versions cannot import playlist exports from newer versions
- due to old code and assumption on single playlist.
- Enable this option & export playlists if you intend to downgrade FreeTube.
- You should also remove all playlists after export & before downgrade
- to ensure that the older versions of FreeTube would regenerate playlist data compatible for those versions.
+ # |- = Keep newlines, No newline at end
+ Tooltip: |-
+ This option exports videos from all playlists into one playlist named `Favorites`.
+ How to export & import videos in playlists for an older version of FreeTube:
+ 1. Export your playlists with this option enabled.
+ 2. Delete all of your existing playlists using the Remove All Playlists option under Privacy Settings.
+ 3. Launch the older version of FreeTube and import the exported playlists."
Profile object has insufficient data, skipping item: Profile object has insufficient
data, skipping item
All subscriptions and profiles have been successfully imported: All subscriptions
From 050eddce943322cb761ae6625d5e85e632c8396a Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 23 Nov 2023 08:21:25 +0800
Subject: [PATCH 203/236] ! Fix vue warning
---
.../ft-playlist-add-video-prompt.vue | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 49b84f675d666..ea389f120411c 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -51,17 +51,17 @@
From f1225cfc97d1cba95654013100abbcba4cfe246a Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 23 Nov 2023 08:27:17 +0800
Subject: [PATCH 204/236] * Update text align
---
src/renderer/components/ft-tooltip/ft-tooltip.css | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.css b/src/renderer/components/ft-tooltip/ft-tooltip.css
index 8b0375ef59802..ea7d5714f1524 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.css
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.css
@@ -94,6 +94,7 @@
.text.allowNewlines {
white-space: pre;
+ text-align: start;
}
.tooltip {
From fe8440de244fcfef2322638f8f5323d5c8494b85 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 23 Nov 2023 08:35:02 +0800
Subject: [PATCH 205/236] * Remove the extra surrounding spaces
---
src/renderer/components/ft-tooltip/ft-tooltip.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.vue b/src/renderer/components/ft-tooltip/ft-tooltip.vue
index 96cea67ff25d1..8b38b62d28064 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.vue
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.vue
@@ -15,8 +15,8 @@
allowNewlines,
}"
role="tooltip"
+ v-text="tooltip"
>
- {{ tooltip }}
From 1a96092d6fae0aeef0e53ba2dd48fe86a93fe57e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 23 Nov 2023 08:38:19 +0800
Subject: [PATCH 206/236] Backtick > quote
---
static/locales/en-US.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml
index e5fb65c9b1b04..dbb5a810b393f 100644
--- a/static/locales/en-US.yaml
+++ b/static/locales/en-US.yaml
@@ -474,7 +474,7 @@ Settings:
Label: Export Playlists For Older FreeTube Versions
# |- = Keep newlines, No newline at end
Tooltip: |-
- This option exports videos from all playlists into one playlist named `Favorites`.
+ This option exports videos from all playlists into one playlist named 'Favorites'.
How to export & import videos in playlists for an older version of FreeTube:
1. Export your playlists with this option enabled.
2. Delete all of your existing playlists using the Remove All Playlists option under Privacy Settings.
From 69d64aa55f058058743db878c81cb4eb5a6bcb22 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 23 Nov 2023 08:42:59 +0800
Subject: [PATCH 207/236] - Remove useless prop
---
src/renderer/components/ft-button/ft-button.js | 7 +------
src/renderer/components/ft-button/ft-button.vue | 1 -
.../ft-create-playlist-prompt.vue | 2 --
.../ft-playlist-add-video-prompt.vue | 3 ---
4 files changed, 1 insertion(+), 12 deletions(-)
diff --git a/src/renderer/components/ft-button/ft-button.js b/src/renderer/components/ft-button/ft-button.js
index 2ebab33a56250..808b8949b2b4b 100644
--- a/src/renderer/components/ft-button/ft-button.js
+++ b/src/renderer/components/ft-button/ft-button.js
@@ -18,11 +18,6 @@ export default defineComponent({
id: {
type: String,
default: ''
- },
- tabindex: {
- type: Number,
- // Relies on template to not output tabindex on values < -1
- default: -2,
- },
+ }
}
})
diff --git a/src/renderer/components/ft-button/ft-button.vue b/src/renderer/components/ft-button/ft-button.vue
index d0107780768c0..88a340248188e 100644
--- a/src/renderer/components/ft-button/ft-button.vue
+++ b/src/renderer/components/ft-button/ft-button.vue
@@ -2,7 +2,6 @@
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index ea389f120411c..ae6b936604edf 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -51,17 +51,14 @@
From fd74dc97e61abdff72207b9b816859908b1a3c62 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 23 Nov 2023 09:29:28 +0800
Subject: [PATCH 208/236] Fix tootip in lower width view
---
src/renderer/components/ft-tooltip/ft-tooltip.css | 7 ++++++-
src/renderer/components/ft-tooltip/ft-tooltip.vue | 3 +--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.css b/src/renderer/components/ft-tooltip/ft-tooltip.css
index ea7d5714f1524..304b6f9b63e13 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.css
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.css
@@ -93,8 +93,13 @@
}
.text.allowNewlines {
- white-space: pre;
+ white-space: pre-wrap;
text-align: start;
+
+ @media only screen and (min-width: 1000px) {
+ /* Enough space to NOT wrap */
+ white-space: pre;
+ }
}
.tooltip {
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.vue b/src/renderer/components/ft-tooltip/ft-tooltip.vue
index 8b38b62d28064..494ee5af1f98c 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.vue
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.vue
@@ -16,8 +16,7 @@
}"
role="tooltip"
v-text="tooltip"
- >
-
+ />
From 73626f66cd528406a988c89cb7067a240744755b Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 23 Nov 2023 09:32:33 +0800
Subject: [PATCH 209/236] Update default filename
---
src/renderer/components/data-settings/data-settings.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index 4d772feea67de..c921f29ac3352 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -1029,7 +1029,7 @@ export default defineComponent({
exportPlaylistsForOlderVersions: async function () {
const dateStr = getTodayDateStrLocalTimezone()
- const exportFileName = 'freetube-playlists-for-single-favorites-playlist-' + dateStr + '.db'
+ const exportFileName = 'freetube-playlists-as-single-favorites-playlist-' + dateStr + '.db'
const options = {
defaultPath: exportFileName,
From 7d932b936c7814349e50204a7979d2d0f5b0ea73 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 23 Nov 2023 11:41:58 +0800
Subject: [PATCH 210/236] * Make tooltip auto-wrap
---
.../components/ft-tooltip/ft-tooltip.css | 10 ++---
.../components/ft-tooltip/ft-tooltip.js | 45 ++++++++++++++++++-
.../components/ft-tooltip/ft-tooltip.vue | 2 +
3 files changed, 49 insertions(+), 8 deletions(-)
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.css b/src/renderer/components/ft-tooltip/ft-tooltip.css
index 304b6f9b63e13..e0f5ba3b56fd4 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.css
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.css
@@ -93,13 +93,11 @@
}
.text.allowNewlines {
- white-space: pre-wrap;
+ white-space: pre;
text-align: start;
-
- @media only screen and (min-width: 1000px) {
- /* Enough space to NOT wrap */
- white-space: pre;
- }
+}
+.text.allowNewlines.wrap {
+ white-space: pre-wrap;
}
.tooltip {
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.js b/src/renderer/components/ft-tooltip/ft-tooltip.js
index 66ba1d1dd6209..bf2c5334ac5cf 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.js
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.js
@@ -2,6 +2,26 @@ import { defineComponent } from 'vue'
let idCounter = 0
+function isOutOfViewport(el) {
+ if (el == null) { return {} }
+
+ const bounding = el.getBoundingClientRect()
+ const out = {}
+
+ out.top = bounding.top < 0
+ out.left = bounding.left < 0
+ out.bottom = bounding.bottom > (window.innerHeight || document.documentElement.clientHeight)
+ out.right = bounding.right > (window.innerWidth || document.documentElement.clientWidth)
+ out.horizontal = out.left || out.right
+ out.veritical = out.top || out.bottom
+ out.any = out.top || out.left || out.bottom || out.right
+ out.all = out.top && out.left && out.bottom && out.right
+
+ out.bounding = bounding
+
+ return out
+}
+
export default defineComponent({
name: 'FtTooltip',
props: {
@@ -23,7 +43,28 @@ export default defineComponent({
const id = `ft-tooltip-${++idCounter}`
return {
- id
+ id,
+ isTooltipOutOfViewportResult: {}
}
- }
+ },
+ computed: {
+ tooltipOutsideViewPort() {
+ return this.isTooltipOutOfViewportResult.horizontal
+ },
+ },
+ mounted() {
+ this.updateSizeRelatedStates()
+ window.addEventListener('resize', this.updateSizeRelatedStates)
+ },
+ destroyed() {
+ window.removeEventListener('resize', this.updateSizeRelatedStates)
+ },
+ methods: {
+ updateSizeRelatedStates() {
+ if (this.allowNewlines) {
+ // Only when newlines allowed have issue with wrapping
+ this.isTooltipOutOfViewportResult = isOutOfViewport(this.$refs.tooltip)
+ }
+ },
+ },
})
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.vue b/src/renderer/components/ft-tooltip/ft-tooltip.vue
index 494ee5af1f98c..6996d28363094 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.vue
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.vue
@@ -9,10 +9,12 @@
Date: Wed, 22 Nov 2023 22:16:02 -0600
Subject: [PATCH 211/236] Revert "* Make tooltip auto-wrap"
This reverts commit 7d932b936c7814349e50204a7979d2d0f5b0ea73.
---
.../components/ft-tooltip/ft-tooltip.css | 10 +++--
.../components/ft-tooltip/ft-tooltip.js | 45 +------------------
.../components/ft-tooltip/ft-tooltip.vue | 2 -
3 files changed, 8 insertions(+), 49 deletions(-)
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.css b/src/renderer/components/ft-tooltip/ft-tooltip.css
index e0f5ba3b56fd4..304b6f9b63e13 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.css
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.css
@@ -93,11 +93,13 @@
}
.text.allowNewlines {
- white-space: pre;
- text-align: start;
-}
-.text.allowNewlines.wrap {
white-space: pre-wrap;
+ text-align: start;
+
+ @media only screen and (min-width: 1000px) {
+ /* Enough space to NOT wrap */
+ white-space: pre;
+ }
}
.tooltip {
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.js b/src/renderer/components/ft-tooltip/ft-tooltip.js
index bf2c5334ac5cf..66ba1d1dd6209 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.js
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.js
@@ -2,26 +2,6 @@ import { defineComponent } from 'vue'
let idCounter = 0
-function isOutOfViewport(el) {
- if (el == null) { return {} }
-
- const bounding = el.getBoundingClientRect()
- const out = {}
-
- out.top = bounding.top < 0
- out.left = bounding.left < 0
- out.bottom = bounding.bottom > (window.innerHeight || document.documentElement.clientHeight)
- out.right = bounding.right > (window.innerWidth || document.documentElement.clientWidth)
- out.horizontal = out.left || out.right
- out.veritical = out.top || out.bottom
- out.any = out.top || out.left || out.bottom || out.right
- out.all = out.top && out.left && out.bottom && out.right
-
- out.bounding = bounding
-
- return out
-}
-
export default defineComponent({
name: 'FtTooltip',
props: {
@@ -43,28 +23,7 @@ export default defineComponent({
const id = `ft-tooltip-${++idCounter}`
return {
- id,
- isTooltipOutOfViewportResult: {}
+ id
}
- },
- computed: {
- tooltipOutsideViewPort() {
- return this.isTooltipOutOfViewportResult.horizontal
- },
- },
- mounted() {
- this.updateSizeRelatedStates()
- window.addEventListener('resize', this.updateSizeRelatedStates)
- },
- destroyed() {
- window.removeEventListener('resize', this.updateSizeRelatedStates)
- },
- methods: {
- updateSizeRelatedStates() {
- if (this.allowNewlines) {
- // Only when newlines allowed have issue with wrapping
- this.isTooltipOutOfViewportResult = isOutOfViewport(this.$refs.tooltip)
- }
- },
- },
+ }
})
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.vue b/src/renderer/components/ft-tooltip/ft-tooltip.vue
index 6996d28363094..494ee5af1f98c 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.vue
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.vue
@@ -9,12 +9,10 @@
Date: Wed, 22 Nov 2023 22:28:34 -0600
Subject: [PATCH 212/236] Adjust tooltip styling
---
src/renderer/components/ft-tooltip/ft-tooltip.css | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/renderer/components/ft-tooltip/ft-tooltip.css b/src/renderer/components/ft-tooltip/ft-tooltip.css
index 304b6f9b63e13..40c5a9199414b 100644
--- a/src/renderer/components/ft-tooltip/ft-tooltip.css
+++ b/src/renderer/components/ft-tooltip/ft-tooltip.css
@@ -95,11 +95,11 @@
.text.allowNewlines {
white-space: pre-wrap;
text-align: start;
+ inline-size: 55vw;
+}
- @media only screen and (min-width: 1000px) {
- /* Enough space to NOT wrap */
- white-space: pre;
- }
+@media only screen and (max-width: 1100px) {
+ inline-size: 40vw;
}
.tooltip {
From 64fa30831d62ddac1248a0c4f3ba6951ff008f96 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 30 Nov 2023 09:28:53 +0800
Subject: [PATCH 213/236] * Wait for local playlist loading only when playing
with a user playlist
---
src/renderer/views/Watch/Watch.js | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index f2482a3aebb43..1d64605865155 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -128,6 +128,8 @@ export default defineComponent({
playNextCountDownIntervalId: null,
infoAreaSticky: true,
commentsEnabled: true,
+
+ onMountedRun: false,
}
},
computed: {
@@ -216,11 +218,15 @@ export default defineComponent({
return this.$store.getters.getAllowDashAv1Formats
},
+ inUserPlaylist: function () {
+ return this.playlistType === 'user'
+ },
userPlaylistsReady: function () {
return this.$store.getters.getPlaylistsReady
},
selectedUserPlaylist: function () {
if (this.playlistId == null || this.playlistId === '') { return null }
+ if (!this.inUserPlaylist) { return null }
return this.$store.getters.getPlaylist(this.playlistId)
},
@@ -269,8 +275,12 @@ export default defineComponent({
},
methods: {
onMountedDependOnLocalStateLoading() {
+ // Prevent running twice
+ if (this.onMountedRun) { return }
// Stuff that require user playlists to be ready
- if (!this.userPlaylistsReady) { return }
+ if (this.inUserPlaylist && !this.userPlaylistsReady) { return }
+
+ this.onMountedRun = true
this.checkIfPlaylist()
this.checkIfTimestamp()
From 4e10de44df0a722c8d88338de67351a672b3b024 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 30 Nov 2023 09:49:04 +0800
Subject: [PATCH 214/236] * Wait for local playlist loading only when playing
with a user playlist requested
Request user playlist can still be absent (but not requested for no playlist or remote playlist)
---
.../components/playlist-info/playlist-info.js | 12 ++++++++++--
.../components/playlist-info/playlist-info.vue | 1 +
src/renderer/views/Watch/Watch.js | 8 ++++----
3 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index d4d877cc2b3d9..903eabf995eb3 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -166,8 +166,16 @@ export default defineComponent({
}
},
+ isUserPlaylist() {
+ return this.infoSource === 'user'
+ },
+
+ videoPlaylistType() {
+ return this.isUserPlaylist ? 'user' : ''
+ },
+
deletePlaylistButtonVisible: function() {
- if (this.infoSource !== 'user') { return false }
+ if (!this.isUserPlaylist) { return false }
// Cannot delete during edit
if (this.editMode) { return false }
@@ -177,7 +185,7 @@ export default defineComponent({
sharePlaylistButtonVisible: function() {
// Only online playlists can be shared
- if (this.infoSource === 'user') { return false }
+ if (this.isUserPlaylist) { return false }
// Cannot delete protected playlist
return !this.hideSharingActions
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index bb6d0a7e776fa..4e9bd938c044c 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -8,6 +8,7 @@
path: `/watch/${firstVideoId}`,
query: {
playlistId: id,
+ playlistType: videoPlaylistType,
playlistItemId: firstVideoPlaylistItemId,
},
}"
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index 1d64605865155..e69add667f787 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -218,15 +218,15 @@ export default defineComponent({
return this.$store.getters.getAllowDashAv1Formats
},
- inUserPlaylist: function () {
- return this.playlistType === 'user'
+ isUserPlaylistRequested: function () {
+ return this.$route.query.playlistType === 'user'
},
userPlaylistsReady: function () {
return this.$store.getters.getPlaylistsReady
},
selectedUserPlaylist: function () {
if (this.playlistId == null || this.playlistId === '') { return null }
- if (!this.inUserPlaylist) { return null }
+ if (!this.isUserPlaylistRequested) { return null }
return this.$store.getters.getPlaylist(this.playlistId)
},
@@ -278,7 +278,7 @@ export default defineComponent({
// Prevent running twice
if (this.onMountedRun) { return }
// Stuff that require user playlists to be ready
- if (this.inUserPlaylist && !this.userPlaylistsReady) { return }
+ if (this.isUserPlaylistRequested && !this.userPlaylistsReady) { return }
this.onMountedRun = true
From 2b3ad17b424e445941c83016def4e5258eaf11dc Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 1 Dec 2023 09:30:54 +0800
Subject: [PATCH 215/236] ! Fix single playlist view cover image having link
when no video
---
src/renderer/components/playlist-info/playlist-info.js | 6 +++++-
src/renderer/components/playlist-info/playlist-info.scss | 5 ++++-
src/renderer/components/playlist-info/playlist-info.vue | 8 ++++++++
3 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 903eabf995eb3..63e1572e067d2 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -141,8 +141,12 @@ export default defineComponent({
]
},
+ firstVideoIdExists() {
+ return this.firstVideoId !== ''
+ },
+
thumbnail: function () {
- if (this.thumbnailPreference === 'hidden' || this.firstVideoId === '') {
+ if (this.thumbnailPreference === 'hidden' || !this.firstVideoIdExists) {
return require('../../assets/img/thumbnail_placeholder.svg')
}
diff --git a/src/renderer/components/playlist-info/playlist-info.scss b/src/renderer/components/playlist-info/playlist-info.scss
index c659de9a5ff86..3fb13c0c0fe8a 100644
--- a/src/renderer/components/playlist-info/playlist-info.scss
+++ b/src/renderer/components/playlist-info/playlist-info.scss
@@ -2,8 +2,11 @@
inline-size: 100%;
}
-.playlistThumbnail img {
+.playlistThumbnail .firstVideoLink {
cursor: pointer;
+}
+
+.playlistThumbnail img {
inline-size: 100%;
// Ensure placeholder image displayed at same aspect ratio as most other images
aspect-ratio: 16/9;
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 4e9bd938c044c..f481205053a4e 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -4,6 +4,8 @@
class="playlistThumbnail"
>
+
From a94f70766ae36f583ad8b591d7d7c74db8defd5e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 1 Dec 2023 18:21:42 +0800
Subject: [PATCH 216/236] ! Workaround create playlist prompt won't close when
enter pressed in input box
---
.../ft-create-playlist-prompt.js | 6 ------
.../ft-playlist-add-video-prompt.js | 13 +++++++++++++
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
index 09999f1610850..1beac5852a38a 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.js
@@ -21,7 +21,6 @@ export default defineComponent({
data: function () {
return {
playlistName: '',
- lastActiveElement: null,
}
},
computed: {
@@ -33,15 +32,10 @@ export default defineComponent({
},
},
mounted: function () {
- this.lastActiveElement = document.activeElement
-
this.playlistName = this.newPlaylistVideoObject.title
// Faster to input required playlist name
this.$refs.playlistNameInput.focus()
},
- beforeDestroy() {
- this.lastActiveElement?.focus()
- },
methods: {
createNewPlaylist: function () {
if (this.playlistName === '') {
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index cb103bebdd4d9..698ca9639ed15 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -44,6 +44,10 @@ export default defineComponent({
}
},
computed: {
+ showingCreatePlaylistPrompt: function () {
+ return this.$store.getters.getShowCreatePlaylistPrompt
+ },
+
allPlaylists: function () {
const playlists = this.$store.getters.getAllPlaylists
return [].concat(playlists).sort((a, b) => {
@@ -163,6 +167,15 @@ export default defineComponent({
// Allow search and easier deselecting new created playlist
this.$refs.searchBar.focus()
},
+
+ showingCreatePlaylistPrompt(val) {
+ if (val) { return }
+
+ // Only care when CreatePlaylistPrompt hidden
+ // Shift focus from button to prevent unwanted click event
+ // due to enter key press in CreatePlaylistPrompt
+ this.$refs.searchBar.focus()
+ },
},
mounted: function () {
this.lastActiveElement = document.activeElement
From 44ed286848e3cdf4c52f29a867fe09964adffd78 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Fri, 1 Dec 2023 18:38:58 +0800
Subject: [PATCH 217/236] ! Fix clear text button style
---
src/renderer/components/ft-input/ft-input.css | 8 ++++++++
src/renderer/components/ft-input/ft-input.js | 6 +++++-
src/renderer/components/ft-input/ft-input.vue | 3 ++-
src/renderer/views/UserPlaylists/UserPlaylists.vue | 1 +
4 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/ft-input/ft-input.css b/src/renderer/components/ft-input/ft-input.css
index 8a26d5824eaae..cbe199a101e43 100644
--- a/src/renderer/components/ft-input/ft-input.css
+++ b/src/renderer/components/ft-input/ft-input.css
@@ -51,15 +51,23 @@
inset-inline-start: 0;
/* To be higher than `.inputWrapper` */
z-index: 1;
+
margin-block: 0;
margin-inline: 3px;
padding: 10px;
border-radius: 100%;
+
color: var(--primary-text-color);
opacity: 0;
+
transition: background 0.2s ease-in;
}
+.clearInputTextButton.verticallyCentered {
+ inset-block: 0;
+ margin-block: auto;
+}
+
.clearInputTextButton.visible:hover {
background-color: var(--side-nav-hover-color);
color: var(--side-nav-hover-text-color);
diff --git a/src/renderer/components/ft-input/ft-input.js b/src/renderer/components/ft-input/ft-input.js
index fb0cb9cd7ed02..c8374f2db3979 100644
--- a/src/renderer/components/ft-input/ft-input.js
+++ b/src/renderer/components/ft-input/ft-input.js
@@ -38,6 +38,10 @@ export default defineComponent({
type: Boolean,
default: false
},
+ clearInputTextButtonVerticallyCentered: {
+ type: Boolean,
+ default: false
+ },
showLabel: {
type: Boolean,
default: false
@@ -61,7 +65,7 @@ export default defineComponent({
tooltip: {
type: String,
default: ''
- }
+ },
},
data: function () {
let actionIcon = ['fas', 'search']
diff --git a/src/renderer/components/ft-input/ft-input.vue b/src/renderer/components/ft-input/ft-input.vue
index c9a7c8523a14f..99c72f63f2bd2 100644
--- a/src/renderer/components/ft-input/ft-input.vue
+++ b/src/renderer/components/ft-input/ft-input.vue
@@ -29,7 +29,8 @@
:icon="['fas', 'times-circle']"
class="clearInputTextButton"
:class="{
- visible: inputDataPresent
+ visible: inputDataPresent,
+ verticallyCentered: clearInputTextButtonVerticallyCentered,
}"
tabindex="0"
role="button"
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index b4dedbb6c63c3..6421913991b96 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -24,6 +24,7 @@
ref="searchBar"
:placeholder="$t('User Playlists.Search bar placeholder')"
:show-clear-text-button="true"
+ :clear-input-text-button-vertically-centered="true"
:show-action-button="false"
@input="(input) => query = input"
@clear="query = ''"
From c3af940cd00b40c85ae40933499ac696c3d3177a Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 2 Dec 2023 11:42:37 +0800
Subject: [PATCH 218/236] ! Fix copying playlist twice to the same user
playlist produces same playlistItemId
---
src/renderer/store/modules/utils.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index d80f59c11c81a..db239685a4bba 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -331,6 +331,9 @@ const actions = {
throw new Error(errorMsgText)
}
+ // Ensures `playlistItemId` is generated on addVideos
+ videoObjectArray.forEach(v => delete v.playlistItemId)
+
commit('setShowAddToPlaylistPrompt', true)
commit('setToBeAddedToPlaylistVideoList', videoObjectArray)
if (newPlaylistDefaultProperties != null) {
From d5a55777e4d0055274f621e40f354b24ba0984a5 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 2 Dec 2023 11:48:28 +0800
Subject: [PATCH 219/236] ! Fix add video to playlist prompt input box style
---
.../ft-playlist-add-video-prompt.vue | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index ae6b936604edf..0b47a810e8f43 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -17,6 +17,7 @@
ref="searchBar"
:placeholder="$t('User Playlists.AddVideoPrompt.Search in Playlists')"
:show-clear-text-button="true"
+ :clear-input-text-button-vertically-centered="true"
:show-action-button="false"
@input="(input) => updateQueryDebounce(input)"
@clear="updateQueryDebounce('')"
From 9538968bf079a55814bb9008b31ddefe00395c57 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 2 Dec 2023 14:30:27 +0800
Subject: [PATCH 220/236] ! Fix workaround for "create playlist prompt won't
close when enter pressed in input box"
---
.../ft-playlist-add-video-prompt.vue | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 0b47a810e8f43..436f840660889 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -13,7 +13,6 @@
}) }}
Date: Sat, 2 Dec 2023 14:40:35 +0800
Subject: [PATCH 221/236] ! Ensure add video to playlist prompt updated when a
playlist deleted (in another window)
---
.../ft-playlist-add-video-prompt.js | 20 +++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 698ca9639ed15..119e2b6c9938f 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -146,11 +146,12 @@ export default defineComponent({
},
watch: {
allPlaylistsLength(val, oldVal) {
- // When playlist length changed, a playlist removed or added
- // Only cares about playlist added
- if (val < oldVal) { return }
+ const allPlaylistIds = []
+ // Add new playlists to selected
this.allPlaylists.forEach((playlist) => {
+ allPlaylistIds.push(playlist._id)
+
// Old playlists don't have `createdAt`
if (playlist.createdAt == null) { return }
// Only playlists created after this prompt shown should be considered
@@ -163,9 +164,16 @@ export default defineComponent({
this.selectedPlaylistIdList.push(playlist._id)
})
- // Focus back to search input
- // Allow search and easier deselecting new created playlist
- this.$refs.searchBar.focus()
+ // Remove deleted playlist from deleted
+ this.selectedPlaylistIdList = this.selectedPlaylistIdList.filter(playlistId => {
+ return allPlaylistIds.includes(playlistId)
+ })
+
+ if (val > oldVal) {
+ // Focus back to search input only when playlist added
+ // Allow search and easier deselecting new created playlist
+ this.$refs.searchBar.focus()
+ }
},
showingCreatePlaylistPrompt(val) {
From e576a1cc570d9c8902a711368bd99c71af4ed385 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 2 Dec 2023 14:50:10 +0800
Subject: [PATCH 222/236] ! Avoid saving and displaying unwanted video
attributes into playlists
---
src/renderer/store/modules/playlists.js | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index 26b8ffa527e07..ac0060e28fd51 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -158,6 +158,15 @@ const actions = {
if (videoData.type == null) {
videoData.type = 'video'
}
+ // Undesired attributes, even with `null` values
+ [
+ 'description',
+ 'viewCount',
+ ].forEach(attrName => {
+ if (typeof videoData[attrName] !== 'undefined') {
+ delete videoData[attrName]
+ }
+ })
})
await DBPlaylistHandlers.upsertVideosByPlaylistId(_id, videos)
commit('addVideos', payload)
@@ -219,6 +228,17 @@ const actions = {
v.type = 'video'
anythingUpdated = true
}
+
+ // Undesired attributes, even with `null` values
+ [
+ 'description',
+ 'viewCount',
+ ].forEach(attrName => {
+ if (typeof v[attrName] !== 'undefined') {
+ delete v[attrName]
+ anythingUpdated = true
+ }
+ })
})
// Save updated playlist object
if (anythingUpdated) {
From c0912ce50aa69c8929d9bc07b81da1cfd8faba80 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 2 Dec 2023 15:24:35 +0800
Subject: [PATCH 223/236] ! Fix playlist view for deleted user playlists
---
.../ft-list-playlist/ft-list-playlist.js | 10 ++++++++++
.../ft-list-playlist/ft-list-playlist.vue | 4 ++--
src/renderer/views/Playlist/Playlist.js | 20 ++++++++++++++++---
static/locales/en-US.yaml | 2 ++
4 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.js b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
index 7d1f72ae92dca..30ff916bc3372 100644
--- a/src/renderer/components/ft-list-playlist/ft-list-playlist.js
+++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.js
@@ -72,6 +72,16 @@ export default defineComponent({
isUserPlaylist() {
return this.data._id != null
},
+
+ playlistPageLinkTo() {
+ // For `router-link` attribute `to`
+ return {
+ path: `/playlist/${this.playlistId}`,
+ query: {
+ playlistType: this.isUserPlaylist ? 'user' : '',
+ },
+ }
+ },
},
created: function () {
if (this.isUserPlaylist) {
diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.vue b/src/renderer/components/ft-list-playlist/ft-list-playlist.vue
index 27b39a516e1d2..503c800c6484f 100644
--- a/src/renderer/components/ft-list-playlist/ft-list-playlist.vue
+++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.vue
@@ -12,7 +12,7 @@
>
@@ -36,7 +36,7 @@
{{ titleForDisplay }}
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index 92e22c6523e2f..c67def8cbe368 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -80,6 +80,7 @@ export default defineComponent({
return this.$store.getters.getPlaylistsReady
},
selectedUserPlaylist: function () {
+ if (!this.isUserPlaylistRequested) { return null }
if (this.playlistId == null || this.playlistId === '') { return null }
return this.$store.getters.getPlaylist(this.playlistId)
@@ -101,6 +102,10 @@ export default defineComponent({
moreVideoDataAvailable() {
return this.continuationData !== null
},
+
+ isUserPlaylistRequested: function () {
+ return this.$route.query.playlistType === 'user'
+ },
},
watch: {
$route () {
@@ -109,6 +114,8 @@ export default defineComponent({
},
userPlaylistsReady () {
// Fetch from local store when playlist data ready
+ if (!this.isUserPlaylistRequested) { return }
+
this.getPlaylistInfoDebounce()
},
selectedUserPlaylist () {
@@ -137,10 +144,14 @@ export default defineComponent({
getPlaylistInfo: function () {
this.isLoading = true
// `selectedUserPlaylist` result accuracy relies on data being ready
- if (!this.userPlaylistsReady) { return }
+ if (this.isUserPlaylistRequested && !this.userPlaylistsReady) { return }
- if (this.selectedUserPlaylist != null) {
- this.parseUserPlaylist(this.selectedUserPlaylist)
+ if (this.isUserPlaylistRequested) {
+ if (this.selectedUserPlaylist != null) {
+ this.parseUserPlaylist(this.selectedUserPlaylist)
+ } else {
+ this.showUserPlaylistNotFound()
+ }
return
}
@@ -262,6 +273,9 @@ export default defineComponent({
this.isLoading = false
},
+ showUserPlaylistNotFound() {
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast.This playlist does not exist'))
+ },
getNextPage: function () {
switch (this.infoSource) {
diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml
index beb3ec2da90c9..6b6c82cd277f1 100644
--- a/static/locales/en-US.yaml
+++ b/static/locales/en-US.yaml
@@ -193,6 +193,8 @@ User Playlists:
There were no videos to remove.: There were no videos to remove.
This playlist is protected and cannot be removed.: This playlist is protected and cannot be removed.
Playlist {playlistName} has been deleted.: Playlist {playlistName} has been deleted.
+
+ This playlist does not exist: This playlist does not exist
AddVideoPrompt:
Select a playlist to add your N videos to: 'Select a playlist to add your video to | Select a playlist to add your {videoCount} videos to'
N playlists selected: '{playlistCount} Selected'
From fcde4abb71f5d71374b7d124c57c60c25ec96912 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 4 Dec 2023 11:31:43 +0800
Subject: [PATCH 224/236] ! Fix copying playlist twice to the same user
playlist produces same playlistItemId
Real fix
Cause of issue: updating property of input objects (which is shared across multiple run)
---
src/renderer/store/modules/playlists.js | 18 +++++++++++-------
src/renderer/store/modules/utils.js | 3 ---
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/src/renderer/store/modules/playlists.js b/src/renderer/store/modules/playlists.js
index ac0060e28fd51..0f55dcfbace12 100644
--- a/src/renderer/store/modules/playlists.js
+++ b/src/renderer/store/modules/playlists.js
@@ -145,15 +145,17 @@ const actions = {
},
async addVideos({ commit }, payload) {
+ // Assumes videos are added NOT from export
+ // Since this action will ensure uniqueness of `playlistItemId` of added video entries
try {
const { _id, videos } = payload
- videos.forEach((videoData) => {
+ 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()
}
- if (videoData.playlistItemId == null) {
- videoData.playlistItemId = generateRandomUniqueId()
- }
+ videoData.playlistItemId = generateRandomUniqueId()
// For backward compatibility
if (videoData.type == null) {
videoData.type = 'video'
@@ -167,9 +169,11 @@ const actions = {
delete videoData[attrName]
}
})
+
+ return videoData
})
- await DBPlaylistHandlers.upsertVideosByPlaylistId(_id, videos)
- commit('addVideos', payload)
+ await DBPlaylistHandlers.upsertVideosByPlaylistId(_id, newVideoObjects)
+ commit('addVideos', { _id, videos: newVideoObjects })
} catch (errMessage) {
console.error(errMessage)
}
@@ -390,7 +394,7 @@ const mutations = {
addVideos(state, payload) {
const playlist = state.playlists.find(playlist => playlist._id === payload._id)
if (playlist) {
- playlist.videos = playlist.videos.concat(payload.videos)
+ playlist.videos = [].concat(playlist.videos).concat(payload.videos)
}
},
diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js
index db239685a4bba..d80f59c11c81a 100644
--- a/src/renderer/store/modules/utils.js
+++ b/src/renderer/store/modules/utils.js
@@ -331,9 +331,6 @@ const actions = {
throw new Error(errorMsgText)
}
- // Ensures `playlistItemId` is generated on addVideos
- videoObjectArray.forEach(v => delete v.playlistItemId)
-
commit('setShowAddToPlaylistPrompt', true)
commit('setToBeAddedToPlaylistVideoList', videoObjectArray)
if (newPlaylistDefaultProperties != null) {
From f76b5fe99b2778e01550416917c9cff41a75867e Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Mon, 4 Dec 2023 11:43:11 +0800
Subject: [PATCH 225/236] ! Fix search suggestions being blocked by playlist
info component in single playlist view
---
src/renderer/views/Playlist/Playlist.scss | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/renderer/views/Playlist/Playlist.scss b/src/renderer/views/Playlist/Playlist.scss
index f34b27c5d9554..b9c6bf2c08407 100644
--- a/src/renderer/views/Playlist/Playlist.scss
+++ b/src/renderer/views/Playlist/Playlist.scss
@@ -12,8 +12,8 @@
position: sticky;
inset-block-start: 96px;
/* This is needed to make prompt always above video entries */
- /* High value used to avoid further issues */
- z-index: 100;
+ /* Value being too high would block search suggestions */
+ z-index: 1;
inline-size: 30%;
}
From b255d44bd3cf37baf677ddd27e6b493dfdfcd976 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 5 Dec 2023 09:20:50 +0800
Subject: [PATCH 226/236] ! Fix warning when reversing playlist in watch view
---
.../components/watch-video-playlist/watch-video-playlist.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index 4fc24f84701d7..859775d7f8d2d 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -263,7 +263,9 @@ export default defineComponent({
showToast(this.$t('The playlist has been reversed'))
this.reversePlaylist = !this.reversePlaylist
- this.playlistItems = this.playlistItems.reverse()
+ // Create a new array to avoid changing array in data store state
+ // it could be user playlist or cache playlist
+ this.playlistItems = [].concat(this.playlistItems).reverse()
setTimeout(() => {
this.isLoading = false
}, 1)
From dd6dfef526e04444572b220f1b47836bc54c2ff1 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 7 Dec 2023 08:32:45 +0800
Subject: [PATCH 227/236] ! Fix prompt in playlist view (playlistinfo
component) not above sidebar
---
src/renderer/components/playlist-info/playlist-info.js | 8 ++++++++
src/renderer/views/Playlist/Playlist.js | 2 ++
src/renderer/views/Playlist/Playlist.scss | 5 +++++
src/renderer/views/Playlist/Playlist.vue | 5 +++++
4 files changed, 20 insertions(+)
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 63e1572e067d2..8ff2a210ffbcf 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -195,6 +195,14 @@ export default defineComponent({
return !this.hideSharingActions
},
},
+ watch: {
+ showDeletePlaylistPrompt(shown) {
+ this.$emit(shown ? 'prompt-open' : 'prompt-close')
+ },
+ showRemoveVideosOnWatchPrompt(shown) {
+ this.$emit(shown ? 'prompt-open' : 'prompt-close')
+ },
+ },
created: function () {
this.newTitle = this.title
this.newDescription = this.description
diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js
index c67def8cbe368..53f7e82611da5 100644
--- a/src/renderer/views/Playlist/Playlist.js
+++ b/src/renderer/views/Playlist/Playlist.js
@@ -58,6 +58,8 @@ export default defineComponent({
isLoadingMore: false,
getPlaylistInfoDebounce: function() {},
playlistInEditMode: false,
+
+ promptOpen: false,
}
},
computed: {
diff --git a/src/renderer/views/Playlist/Playlist.scss b/src/renderer/views/Playlist/Playlist.scss
index b9c6bf2c08407..13fd09464488b 100644
--- a/src/renderer/views/Playlist/Playlist.scss
+++ b/src/renderer/views/Playlist/Playlist.scss
@@ -15,6 +15,11 @@
/* Value being too high would block search suggestions */
z-index: 1;
inline-size: 30%;
+
+ &.promptOpen {
+ // Otherwise sidebar would be above the prompt
+ z-index: 200;
+ }
}
.playlistItems {
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index 01c9eabfc7125..7b4e995aea300 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -23,8 +23,13 @@
:info-source="infoSource"
:more-video-data-available="moreVideoDataAvailable"
class="playlistInfo"
+ :class="{
+ promptOpen,
+ }"
@enter-edit-mode="playlistInEditMode = true"
@exit-edit-mode="playlistInEditMode = false"
+ @prompt-open="promptOpen = true"
+ @prompt-close="promptOpen = false"
/>
Date: Sat, 9 Dec 2023 18:12:23 +0800
Subject: [PATCH 228/236] Remove CSS top comments absent in other CSS files
---
.../ft-create-playlist-prompt.css | 20 -------------------
.../ft-playlist-add-video-prompt.css | 14 -------------
2 files changed, 34 deletions(-)
diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.css b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.css
index dc3f83c4074cc..667067465ab81 100644
--- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.css
+++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.css
@@ -1,23 +1,3 @@
-/*
- This file is part of FreeTube.
- FreeTube is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- FreeTube is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with FreeTube. If not, see .
-*/
-
-/*
-* Credit goes to pavelvaravko for making this css.
-* https://codepen.io/pavelvaravko/pen/qjojOr
-*/
-
-/* select starting stylings ------------------------------*/
.center {
text-align: center;
}
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
index 1803d371594e5..7fccec88d65f4 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css
@@ -1,17 +1,3 @@
-/*
- This file is part of FreeTube.
- FreeTube is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- FreeTube is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with FreeTube. If not, see .
-*/
-
.heading {
text-align: center;
}
From ce82d671f5a8576507c626a4ecc8d6f4f3f244de Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 9 Dec 2023 19:24:51 +0800
Subject: [PATCH 229/236] Remove not useful comment for CSS
---
.../components/ft-playlist-selector/ft-playlist-selector.scss | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
index 10c15ae191d4a..b9ee47faf8abe 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
@@ -194,7 +194,7 @@ $watched-transition-duration: 0.5s;
position: relative;
.optionsButton {
- float: right; // ohhhh man, float was finally the right choice for something;
+ float: right;
}
.externalPlayerButton {
From 1ce980f94d9daf7f9957b8dcf576b9c379cd9659 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sat, 9 Dec 2023 22:04:10 +0800
Subject: [PATCH 230/236] Float with variable
Co-authored-by: Jason <84899178+jasonhenriquez@users.noreply.github.com>
---
.../components/ft-playlist-selector/ft-playlist-selector.scss | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
index b9ee47faf8abe..ddc2c7c410eeb 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
@@ -194,11 +194,11 @@ $watched-transition-duration: 0.5s;
position: relative;
.optionsButton {
- float: right;
+ float: var(--float-right-ltr-rtl-value);
}
.externalPlayerButton {
- float: right;
+ float: var(--float-right-ltr-rtl-value);
}
.title {
From 0958cb5d98ccae18ba7a00f173c63c539247f044 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Tue, 12 Dec 2023 08:25:47 +0800
Subject: [PATCH 231/236] Revert "! Fix clear text button style"
This reverts commit 44ed286848e3cdf4c52f29a867fe09964adffd78.
---
src/renderer/components/ft-input/ft-input.css | 8 --------
src/renderer/components/ft-input/ft-input.js | 6 +-----
src/renderer/components/ft-input/ft-input.vue | 3 +--
src/renderer/views/UserPlaylists/UserPlaylists.vue | 1 -
4 files changed, 2 insertions(+), 16 deletions(-)
diff --git a/src/renderer/components/ft-input/ft-input.css b/src/renderer/components/ft-input/ft-input.css
index c2e7b54eb9cb4..4d383d327244e 100644
--- a/src/renderer/components/ft-input/ft-input.css
+++ b/src/renderer/components/ft-input/ft-input.css
@@ -51,23 +51,15 @@
inset-inline-start: 0;
/* To be higher than `.inputWrapper` */
z-index: 1;
-
margin-block: 0;
margin-inline: 3px;
padding: 10px;
border-radius: 100%;
-
color: var(--primary-text-color);
opacity: 0;
-
transition: background 0.2s ease-in;
}
-.clearInputTextButton.verticallyCentered {
- inset-block: 0;
- margin-block: auto;
-}
-
.clearInputTextButton.visible:hover {
background-color: var(--side-nav-hover-color);
color: var(--side-nav-hover-text-color);
diff --git a/src/renderer/components/ft-input/ft-input.js b/src/renderer/components/ft-input/ft-input.js
index 1bb9650418915..1787f4cb8507a 100644
--- a/src/renderer/components/ft-input/ft-input.js
+++ b/src/renderer/components/ft-input/ft-input.js
@@ -38,10 +38,6 @@ export default defineComponent({
type: Boolean,
default: false
},
- clearInputTextButtonVerticallyCentered: {
- type: Boolean,
- default: false
- },
showLabel: {
type: Boolean,
default: false
@@ -65,7 +61,7 @@ export default defineComponent({
tooltip: {
type: String,
default: ''
- },
+ }
},
data: function () {
let actionIcon = ['fas', 'search']
diff --git a/src/renderer/components/ft-input/ft-input.vue b/src/renderer/components/ft-input/ft-input.vue
index 99c72f63f2bd2..c9a7c8523a14f 100644
--- a/src/renderer/components/ft-input/ft-input.vue
+++ b/src/renderer/components/ft-input/ft-input.vue
@@ -29,8 +29,7 @@
:icon="['fas', 'times-circle']"
class="clearInputTextButton"
:class="{
- visible: inputDataPresent,
- verticallyCentered: clearInputTextButtonVerticallyCentered,
+ visible: inputDataPresent
}"
tabindex="0"
role="button"
diff --git a/src/renderer/views/UserPlaylists/UserPlaylists.vue b/src/renderer/views/UserPlaylists/UserPlaylists.vue
index 6421913991b96..b4dedbb6c63c3 100644
--- a/src/renderer/views/UserPlaylists/UserPlaylists.vue
+++ b/src/renderer/views/UserPlaylists/UserPlaylists.vue
@@ -24,7 +24,6 @@
ref="searchBar"
:placeholder="$t('User Playlists.Search bar placeholder')"
:show-clear-text-button="true"
- :clear-input-text-button-vertically-centered="true"
:show-action-button="false"
@input="(input) => query = input"
@clear="query = ''"
From ce1741521de5820d42a02536fddab1eb3c123578 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 14 Dec 2023 08:13:30 +0800
Subject: [PATCH 232/236] Missing change for Revert "! Fix clear text button
style"
---
.../ft-playlist-add-video-prompt.vue | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
index 436f840660889..3364d0d54b1ac 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue
@@ -16,7 +16,6 @@
ref="searchBar"
:placeholder="$t('User Playlists.AddVideoPrompt.Search in Playlists')"
:show-clear-text-button="true"
- :clear-input-text-button-vertically-centered="true"
:show-action-button="false"
@input="(input) => updateQueryDebounce(input)"
@clear="updateQueryDebounce('')"
From e73d83ef717ec588d7138f97506ac72a9e331b20 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Thu, 14 Dec 2023 08:29:15 +0800
Subject: [PATCH 233/236] $ Remove unused style for ft-playlist-selector
---
.../ft-playlist-selector.scss | 199 +-----------------
.../ft-playlist-selector.vue | 4 +-
2 files changed, 6 insertions(+), 197 deletions(-)
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
index ddc2c7c410eeb..a90ee4aff8f60 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.scss
@@ -1,153 +1,18 @@
-$thumbnail-overlay-opacity: 0.85;
-$watched-transition-duration: 0.5s;
-
-@mixin is-result {
- @at-root {
- .result#{&} {
- @content;
- }
- }
-}
-
-@mixin is-watch-playlist-item {
- @at-root {
- .watchPlaylistItem#{&} {
- @content;
- }
- }
-}
-
-@mixin is-recommendation {
- @at-root {
- .recommendation#{&} {
- @content;
- }
- }
-}
-
-@mixin is-sidebar-item {
- @at-root {
- .watchPlaylistItem#{&},
- .recommendation#{&} {
- @content;
- }
- }
-}
-
-@mixin low-contrast-when-watched($col) {
- color: $col;
-
- @at-root {
- .watched &,
- .watched#{&} {
- color: var(--tertiary-text-color);
- }
- .watched:hover &,
- .watched:hover#{&} {
- color: $col;
- transition-duration: $watched-transition-duration;
- }
- }
-}
-
-
-.ft-list-item {
+.ft-playlist-selector {
padding: 6px;
- &:hover {
- background-color: var(--bg-color);
- @include low-contrast-when-watched(var(--primary-text-color));
-
- .thumbnailImage {
- opacity: 0.3;
- }
- }
-
+ &:hover ,
&.selected {
background-color: var(--bg-color);
- @include low-contrast-when-watched(var(--primary-text-color));
.thumbnailImage {
opacity: 0.3;
- transition-duration: $watched-transition-duration;
}
}
- .videoThumbnail {
+ .thumbnail {
position: relative;
- .thumbnailLink {
- display: flex;
- }
-
- .videoWatched {
- position: absolute;
- inset-block-start: 0;
- padding: 2px;
- opacity: $thumbnail-overlay-opacity;
- color: var(--primary-text-color);
- background-color: var(--bg-color);
- pointer-events: none;
- }
-
- .videoDuration {
- position: absolute;
-
- border-radius: 5px;
- margin: 0;
-
- opacity: $thumbnail-overlay-opacity;
- color: var(--primary-text-color);
- background-color: var(--card-bg-color);
- pointer-events: none;
-
- inset-block-end: 4px;
- inset-inline-end: 4px;
- padding-block: 3px;
- padding-inline: 4px;
-
- line-height: 1.2;
- font-size: 15px;
-
- &.live {
- background-color: #f22;
- color: #fff;
- }
- @include is-watch-playlist-item {
- font-size: 12px;
- }
- }
-
- .externalPlayerIcon {
- position: absolute;
-
- inset-block-end: 4px;
- inset-inline-start: 4px;
-
- font-size: 17px;
- opacity: $thumbnail-overlay-opacity;
- }
-
- .playlistIcon {
- position: absolute;
-
- inset-block-start: 40px;
- inset-inline-end: 3px;
-
- font-size: 17px;
- opacity: $thumbnail-overlay-opacity;
- }
-
- .watchedProgressBar {
- position: absolute;
- z-index: 2;
-
- block-size: 2px;
- inset-block-end: 0;
-
- background-color: var(--primary-color);
- }
-
.videoCountContainer {
position: absolute;
@@ -179,60 +44,15 @@ $watched-transition-duration: 0.5s;
}
}
- .channelThumbnail {
- display: flex;
- justify-content: center;
-
- .channelImage {
- block-size: 130px;
- border-radius: 50%;
- }
- }
-
.info {
flex: 1;
position: relative;
- .optionsButton {
- float: var(--float-right-ltr-rtl-value);
- }
-
- .externalPlayerButton {
- float: var(--float-right-ltr-rtl-value);
- }
-
.title {
font-size: 20px;
- @include low-contrast-when-watched(var(--primary-text-color));
text-decoration: none;
word-wrap: break-word;
word-break: break-word;
-
- @include is-sidebar-item {
- font-size: 15px;
- }
- }
-
- .infoLine {
- margin-block-start: 5px;
- font-size: 14px;
-
- @include is-sidebar-item {
- font-size: 12px;
- }
- & {
- @include low-contrast-when-watched(var(--secondary-text-color));
- }
- .channelName {
- @include low-contrast-when-watched(var(--secondary-text-color));
- }
- }
-
- .description {
- font-size: 14px;
- max-block-size: 50px;
- overflow-y: hidden;
- @include low-contrast-when-watched(var(--secondary-text-color));
}
}
@@ -244,8 +64,7 @@ $watched-transition-duration: 0.5s;
min-block-size: 230px;
padding-block-end: 20px;
- .videoThumbnail,
- .channelThumbnail {
+ .thumbnail {
margin-block-end: 12px;
.thumbnailImage {
@@ -257,19 +76,9 @@ $watched-transition-duration: 0.5s;
.title {
font-size: 22px;
}
- .infoLine {
- margin-block-start: 8px;
-
- font-size: 13px;
- }
}
}
-.videoWatched,
-.live {
- text-transform: uppercase;
-}
-
.selectedIcon {
position: absolute;
diff --git a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue
index f9129085a9062..aa63385fe781d 100644
--- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue
+++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue
@@ -1,13 +1,13 @@
Date: Sat, 16 Dec 2023 11:05:42 +0800
Subject: [PATCH 234/236] Apply changes from review
---
src/renderer/components/data-settings/data-settings.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js
index c1e2ed2d851e0..4f036a9f8001d 100644
--- a/src/renderer/components/data-settings/data-settings.js
+++ b/src/renderer/components/data-settings/data-settings.js
@@ -945,9 +945,8 @@ export default defineComponent({
})
playlistObject[key] = videoArray
- } else if (ignoredKeys.includes(key)) {
+ } else if (!ignoredKeys.includes(key)) {
// Do nothing for keys to be ignored
- } else {
playlistObject[key] = playlistData[key]
}
})
From e7729eecc4c88a28c0385b267ac233603eeba006 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Sun, 17 Dec 2023 20:43:54 +0800
Subject: [PATCH 235/236] * Use $tc for translation entries with different
value according to count values
---
.../ft-playlist-add-video-prompt.js | 5 ++++-
src/renderer/components/playlist-info/playlist-info.js | 8 ++++----
static/locales/en-US.yaml | 5 +++--
3 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
index 119e2b6c9938f..958fe07ffcca3 100644
--- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
+++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js
@@ -231,7 +231,10 @@ export default defineComponent({
this.updatePlaylist({ _id: playlist._id })
})
- showToast(this.$t('User Playlists.AddVideoPrompt.Toast["{videoCount} video(s) added to {playlistCount} playlist(s)."]', {
+ const translationEntryKey = addedPlaylistIds.size === 1
+ ? 'User Playlists.AddVideoPrompt.Toast.{videoCount} video(s) added to 1 playlist'
+ : 'User Playlists.AddVideoPrompt.Toast.{videoCount} video(s) added to {playlistCount} playlists'
+ showToast(this.$tc(translationEntryKey, this.toBeAddedToPlaylistVideoCount, {
videoCount: this.toBeAddedToPlaylistVideoCount,
playlistCount: addedPlaylistIds.size,
}))
diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 8ff2a210ffbcf..7d593ddc44627 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -271,9 +271,9 @@ export default defineComponent({
return this.historyCacheById[video.videoId] == null
})
- const videosRemoved = this.selectedUserPlaylist.videos.length - videosToWatch.length
+ const removedVideosCount = this.selectedUserPlaylist.videos.length - videosToWatch.length
- if (videosRemoved === 0) {
+ if (removedVideosCount === 0) {
showToast(this.$t('User Playlists.SinglePlaylistView.Toast["There were no videos to remove."]'))
this.showRemoveVideosOnWatchPrompt = false
return
@@ -288,8 +288,8 @@ export default defineComponent({
}
try {
this.updatePlaylist(playlist)
- showToast(this.$t('User Playlists.SinglePlaylistView.Toast["{videoCount} video(s) have been removed."]', {
- videoCount: videosRemoved,
+ showToast(this.$tc('User Playlists.SinglePlaylistView.Toast.{videoCount} video(s) have been removed', removedVideosCount, {
+ videoCount: removedVideosCount,
}))
} catch (e) {
showToast(this.$t('User Playlists.SinglePlaylistView.Toast["There was an issue with updating this playlist."]'))
diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml
index 6b6c82cd277f1..c26943a73c73c 100644
--- a/static/locales/en-US.yaml
+++ b/static/locales/en-US.yaml
@@ -189,7 +189,7 @@ User Playlists:
Playlist name cannot be empty. Please input a name.: Playlist name cannot be empty. Please input a name.
Playlist has been updated.: Playlist has been updated.
There was an issue with updating this playlist.: There was an issue with updating this playlist.
- "{videoCount} video(s) have been removed.": "{videoCount} video(s) have been removed."
+ "{videoCount} video(s) have been removed": "1 video has been removed | {videoCount} videos have been removed"
There were no videos to remove.: There were no videos to remove.
This playlist is protected and cannot be removed.: This playlist is protected and cannot be removed.
Playlist {playlistName} has been deleted.: Playlist {playlistName} has been deleted.
@@ -203,7 +203,8 @@ User Playlists:
Toast:
You haven't selected any playlist yet.: You haven't selected any playlist yet.
- "{videoCount} video(s) added to {playlistCount} playlist(s).": "{videoCount} video(s) added to {playlistCount} playlist(s)."
+ "{videoCount} video(s) added to 1 playlist": "1 video added to 1 playlist | {videoCount} videos added to 1 playlist"
+ "{videoCount} video(s) added to {playlistCount} playlists": "1 video added to {playlistCount} playlists | {videoCount} videos added to {playlistCount} playlists"
CreatePlaylistPrompt:
New Playlist Name: New Playlist Name
Create: Create
From 6647099ba099093c7824dfdc9e8dbeb4b96c8de8 Mon Sep 17 00:00:00 2001
From: PikachuEXE
Date: Wed, 20 Dec 2023 14:28:09 +0800
Subject: [PATCH 236/236] ! Fix playlist link in watch view
---
.../watch-video-playlist.js | 34 +++++++++++++++----
.../watch-video-playlist.vue | 2 +-
src/renderer/views/Watch/Watch.vue | 1 +
3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
index 859775d7f8d2d..5e74cb10ea55f 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js
@@ -23,6 +23,10 @@ export default defineComponent({
type: String,
required: true,
},
+ playlistType: {
+ type: String,
+ default: null
+ },
videoId: {
type: String,
required: true,
@@ -48,6 +52,8 @@ export default defineComponent({
playlistTitle: '',
playlistItems: [],
randomizedPlaylistItems: [],
+
+ getPlaylistInfoRun: false,
}
},
computed: {
@@ -59,6 +65,9 @@ export default defineComponent({
return this.$store.getters.getBackendFallback
},
+ isUserPlaylist: function () {
+ return this.playlistType === 'user'
+ },
userPlaylistsReady: function () {
return this.$store.getters.getPlaylistsReady
},
@@ -73,11 +82,6 @@ export default defineComponent({
selectedUserPlaylistLastUpdatedAt () {
return this.selectedUserPlaylist?.lastUpdatedAt
},
- playlistType() {
- if (this.selectedUserPlaylist != null) { return 'user' }
-
- return ''
- },
currentVideoIndexZeroBased: function () {
return this.playlistItems.findIndex((item) => {
@@ -138,6 +142,16 @@ export default defineComponent({
videoIsNotPlaylistItem: function () {
return this.videoIndexInPlaylistItems === -1
},
+
+ playlistPageLinkTo() {
+ // For `router-link` attribute `to`
+ return {
+ path: `/playlist/${this.playlistId}`,
+ query: {
+ playlistType: this.isUserPlaylist ? 'user' : '',
+ },
+ }
+ },
},
watch: {
userPlaylistsReady: function() {
@@ -202,7 +216,7 @@ export default defineComponent({
this.getPlaylistInformationLocal()
}
}
- }
+ },
},
mounted: function () {
const cachedPlaylist = this.$store.getters.getCachedPlaylist
@@ -225,8 +239,13 @@ export default defineComponent({
},
methods: {
getPlaylistInfoWithDelay: function () {
+ if (this.getPlaylistInfoRun) { return }
+
this.isLoading = true
- if (!this.userPlaylistsReady) { return }
+ // `selectedUserPlaylist` result accuracy relies on data being ready
+ if (this.isUserPlaylist && !this.userPlaylistsReady) { return }
+
+ this.getPlaylistInfoRun = true
if (this.selectedUserPlaylist != null) {
this.parseUserPlaylist(this.selectedUserPlaylist)
@@ -358,6 +377,7 @@ export default defineComponent({
loadCachedPlaylistInformation: async function (cachedPlaylist) {
this.isLoading = true
+ this.getPlaylistInfoRun = true
this.setCachedPlaylist(null)
this.playlistTitle = cachedPlaylist.title
diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
index a718bd8c44c3c..7380d033fcf30 100644
--- a/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
+++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.vue
@@ -12,7 +12,7 @@
>
{{ playlistTitle }}
diff --git a/src/renderer/views/Watch/Watch.vue b/src/renderer/views/Watch/Watch.vue
index b905411938262..707090c04dc24 100644
--- a/src/renderer/views/Watch/Watch.vue
+++ b/src/renderer/views/Watch/Watch.vue
@@ -172,6 +172,7 @@
ref="watchVideoPlaylist"
:watch-view-loading="isLoading"
:playlist-id="playlistId"
+ :playlist-type="playlistType"
:video-id="videoId"
:playlist-item-id="playlistItemId"
class="watchVideoSideBar watchVideoPlaylist"