diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 5b23fa15ce04d..c98be4ed1e186 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -110,6 +110,7 @@ export default defineComponent({
editMode: false,
showDeletePlaylistPrompt: false,
showRemoveVideosOnWatchPrompt: false,
+ showRemoveDuplicateVideosPrompt: false,
newTitle: '',
newDescription: '',
deletePlaylistPromptValues: [
@@ -165,6 +166,20 @@ export default defineComponent({
this.$t('Cancel')
]
},
+ removeVideosOnWatchPromptLabelText() {
+ return this.$tc(
+ 'User Playlists.Are you sure you want to remove {playlistItemCount} watched videos from this playlist? This cannot be undone',
+ this.userPlaylistWatchedVideoCount,
+ { playlistItemCount: this.userPlaylistWatchedVideoCount },
+ )
+ },
+ removeDuplicateVideosPromptLabelText() {
+ return this.$tc(
+ 'User Playlists.Are you sure you want to remove {playlistItemCount} duplicate videos from this playlist? This cannot be undone',
+ this.userPlaylistDuplicateItemCount,
+ { playlistItemCount: this.userPlaylistDuplicateItemCount },
+ )
+ },
firstVideoIdExists() {
return this.firstVideoId !== ''
@@ -211,6 +226,38 @@ export default defineComponent({
return this.isUserPlaylist ? 'user' : ''
},
+ userPlaylistAnyVideoWatched() {
+ if (!this.isUserPlaylist) { return false }
+
+ const historyCacheById = this.$store.getters.getHistoryCacheById
+ return this.selectedUserPlaylist.videos.some((video) => {
+ return typeof historyCacheById[video.videoId] !== 'undefined'
+ })
+ },
+ // `userPlaylistAnyVideoWatched` is faster than this & this is only needed when prompt shown
+ userPlaylistWatchedVideoCount() {
+ if (!this.isUserPlaylist) { return false }
+
+ const historyCacheById = this.$store.getters.getHistoryCacheById
+ return this.selectedUserPlaylist.videos.reduce((count, video) => {
+ return typeof historyCacheById[video.videoId] !== 'undefined' ? count + 1 : count
+ }, 0)
+ },
+
+ userPlaylistUniqueVideoIds() {
+ if (!this.isUserPlaylist) { return new Set() }
+
+ return this.selectedUserPlaylist.videos.reduce((set, video) => {
+ set.add(video.videoId)
+ return set
+ }, new Set())
+ },
+ userPlaylistDuplicateItemCount() {
+ if (this.userPlaylistUniqueVideoIds.size === 0) { return 0 }
+
+ return this.selectedUserPlaylist.videos.length - this.userPlaylistUniqueVideoIds.size
+ },
+
deletePlaylistButtonVisible: function() {
if (!this.isUserPlaylist) { return false }
// Cannot delete during edit
@@ -334,6 +381,43 @@ export default defineComponent({
this.$emit('exit-edit-mode')
},
+ handleRemoveDuplicateVideosPromptAnswer(option) {
+ this.showRemoveDuplicateVideosPrompt = false
+ if (option !== 'delete') { return }
+
+ const videoIdsAdded = new Set()
+ const newVideoItems = this.selectedUserPlaylist.videos.reduce((ary, video) => {
+ if (videoIdsAdded.has(video.videoId)) { return ary }
+
+ ary.push(video)
+ videoIdsAdded.add(video.videoId)
+ return ary
+ }, [])
+
+ const removedVideosCount = this.userPlaylistDuplicateItemCount
+ if (removedVideosCount === 0) {
+ showToast(this.$t('User Playlists.SinglePlaylistView.Toast["There were no videos to remove."]'))
+ return
+ }
+
+ const playlist = {
+ playlistName: this.title,
+ protected: this.selectedUserPlaylist.protected,
+ description: this.description,
+ videos: newVideoItems,
+ _id: this.id,
+ }
+ try {
+ this.updatePlaylist(playlist)
+ 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."]'))
+ console.error(e)
+ }
+ },
+
handleRemoveVideosOnWatchPromptAnswer: function (option) {
this.showRemoveVideosOnWatchPrompt = false
if (option !== 'delete') { return }
@@ -346,7 +430,6 @@ export default defineComponent({
if (removedVideosCount === 0) {
showToast(this.$t('User Playlists.SinglePlaylistView.Toast["There were no videos to remove."]'))
- this.showRemoveVideosOnWatchPrompt = false
return
}
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index a5e6c3b33c707..7c9cc37c0c85a 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -153,7 +153,14 @@
@click="toggleCopyVideosPrompt"
/>
+
+
diff --git a/src/renderer/main.js b/src/renderer/main.js
index 4eaa8845c68d5..39276b2d47770 100644
--- a/src/renderer/main.js
+++ b/src/renderer/main.js
@@ -89,6 +89,7 @@ import {
faTimesCircle,
faTrash,
faUsers,
+ faUsersSlash,
} from '@fortawesome/free-solid-svg-icons'
import {
faBookmark as farBookmark
@@ -187,6 +188,7 @@ library.add(
faTimesCircle,
faTrash,
faUsers,
+ faUsersSlash,
// solid icons
farBookmark,
diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml
index c1bf4dec855bb..76f3bb32c368b 100644
--- a/static/locales/en-US.yaml
+++ b/static/locales/en-US.yaml
@@ -185,10 +185,12 @@ User Playlists:
Cancel: Cancel
Edit Playlist Info: Edit Playlist Info
Copy Playlist: Copy Playlist
+ Remove Duplicate Videos: Remove Duplicate Videos
Remove Watched Videos: Remove Watched Videos
Enable Quick Bookmark With This Playlist: Enable Quick Bookmark With This Playlist
Quick Bookmark Enabled: Quick Bookmark Enabled
- Are you sure you want to remove all watched videos from this playlist? This cannot be undone: Are you sure you want to remove all watched videos from this playlist? This cannot be undone.
+ Are you sure you want to remove {playlistItemCount} duplicate videos from this playlist? This cannot be undone: Are you sure you want to remove 1 duplicate video from this playlist? This cannot be undone. | Are you sure you want to remove {playlistItemCount} duplicate videos from this playlist? This cannot be undone.
+ Are you sure you want to remove {playlistItemCount} watched videos from this playlist? This cannot be undone: Are you sure you want to remove 1 watched video from this playlist? This cannot be undone. | Are you sure you want to remove {playlistItemCount} watched videos from this playlist? This cannot be undone.
Delete Playlist: Delete Playlist
Cannot delete the quick bookmark target playlist.: Cannot delete the quick bookmark target 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.