From 8280cdf38b75f412b14762c63d93509fce53d122 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Tue, 30 Apr 2024 10:08:07 +0800 Subject: [PATCH 1/7] * Make adding duplicate disabled by default --- .../ft-playlist-add-video-prompt.css | 12 +++-- .../ft-playlist-add-video-prompt.js | 47 ++++++++++++++++++- .../ft-playlist-add-video-prompt.vue | 17 ++++++- .../ft-playlist-selector.js | 6 +++ static/locales/en-US.yaml | 2 +- static/locales/en_GB.yaml | 2 +- 6 files changed, 76 insertions(+), 10 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 aa18554033106..5c22f9d84728f 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 @@ -24,16 +24,16 @@ .optionsRow { display: grid; - grid-template-columns: repeat(2, 1fr); + grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); grid-template-rows: 1fr; align-items: center; } @media only screen and (width <= 800px) { .optionsRow { - /* Switch to 2 rows from 2 columns */ + /* Switch to rows from columns */ grid-template-columns: auto; - grid-template-rows: auto auto; + grid-template-rows: repeat(auto-fit, auto); align-items: stretch; } } @@ -51,7 +51,11 @@ overflow-y: scroll; } -.playlist-selector-container { +.playlist-selector-container:not(.disabled) { /* Make them look selectable */ cursor: pointer; } + +.playlist-selector-container.disabled { + opacity: 0.5; +} 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 3e51d789a959f..d1b61318a7267 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 @@ -45,6 +45,7 @@ export default defineComponent({ updateQueryDebounce: function() {}, lastShownAt: Date.now(), sortBy: SORT_BY_VALUES.LatestUpdatedFirst, + addingDuplicateVideosEnabled: false, } }, computed: { @@ -111,6 +112,9 @@ export default defineComponent({ toBeAddedToPlaylistVideoList: function () { return this.$store.getters.getToBeAddedToPlaylistVideoList }, + toBeAddedToPlaylistVideoIdList: function () { + return this.toBeAddedToPlaylistVideoList.map((v) => v.videoId) + }, newPlaylistDefaultProperties: function () { return this.$store.getters.getNewPlaylistDefaultProperties }, @@ -161,6 +165,23 @@ export default defineComponent({ sortBySelectValues() { return Object.values(SORT_BY_VALUES) }, + + playlistIdsContainingVideosToBeAdded() { + const ids = [] + + this.allPlaylists.forEach((playlist) => { + const playlistVideoIds = playlist.videos.map((v) => v.videoId) + + if (this.toBeAddedToPlaylistVideoIdList.every((vid) => playlistVideoIds.includes(vid))) { + ids.push(playlist._id) + } + }) + + return ids + }, + anyPlaylistContainsVideosToBeAdded() { + return this.playlistIdsContainingVideosToBeAdded.length > 0 + }, }, watch: { allPlaylistsLength(val, oldVal) { @@ -202,6 +223,16 @@ export default defineComponent({ // due to enter key press in CreatePlaylistPrompt nextTick(() => this.$refs.searchBar.focus()) }, + + addingDuplicateVideosEnabled(val) { + if (val) { return } + + // Only care when addingDuplicateVideosEnabled disabled + // Remove disabled playlists + this.selectedPlaylistIdList = this.selectedPlaylistIdList.filter(playlistId => { + return !this.playlistIdsContainingVideosToBeAdded.includes(playlistId) + }) + }, }, mounted: function () { this.updateQueryDebounce = debounce(this.updateQuery, 500) @@ -238,10 +269,16 @@ export default defineComponent({ const playlist = this.allPlaylists.find((list) => list._id === selectedPlaylistId) if (playlist == null) { return } + // Use [].concat to avoid `do not mutate vuex store state outside mutation handlers` + let videosToBeAdded = [].concat(this.toBeAddedToPlaylistVideoList) + if (!this.addingDuplicateVideosEnabled) { + const playlistVideoIds = playlist.videos.map((v) => v.videoId) + videosToBeAdded = videosToBeAdded.filter((v) => !playlistVideoIds.includes(v.videoId)) + } + this.addVideos({ _id: playlist._id, - // Use [].concat to avoid `do not mutate vuex store state outside mutation handlers` - videos: [].concat(this.toBeAddedToPlaylistVideoList), + videos: videosToBeAdded, }) addedPlaylistIds.add(playlist._id) // Update playlist's `lastUpdatedAt` @@ -281,6 +318,12 @@ export default defineComponent({ getIconForSortPreference: (s) => getIconForSortPreference(s), + playlistDisabled(playlistId) { + if (this.addingDuplicateVideosEnabled) { return false } + + return this.playlistIdsContainingVideosToBeAdded.includes(playlistId) + }, + ...mapActions([ 'addVideos', 'updatePlaylist', 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 3ab9a13fa907b..7bbb722f619d3 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,11 +28,20 @@ class="optionsRow" > +
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 dbb64c2717976..d8e2385f7018f 100644 --- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js +++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js @@ -24,6 +24,10 @@ export default defineComponent({ type: Boolean, required: true, }, + disabled: { + type: Boolean, + required: true, + }, }, emits: ['selected'], data: function () { @@ -100,6 +104,8 @@ export default defineComponent({ }, toggleSelection: function () { + if (this.disabled) { return } + this.$emit('selected', this.index) }, diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml index 3517fb1071f9a..4e4e6222f2f71 100644 --- a/static/locales/en-US.yaml +++ b/static/locales/en-US.yaml @@ -218,7 +218,7 @@ User Playlists: Search in Playlists: Search in Playlists Save: Save - Added {count} Times: 'Added {count} Time | Added {count} Times' + Added {count} Times: 'Already Added | Added {count} Times' Toast: You haven't selected any playlist yet.: You haven't selected any playlist yet. diff --git a/static/locales/en_GB.yaml b/static/locales/en_GB.yaml index 52d9655e17f2a..54ac1924e4c13 100644 --- a/static/locales/en_GB.yaml +++ b/static/locales/en_GB.yaml @@ -190,7 +190,7 @@ User Playlists: playlists 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 - Added {count} Times: Added {count} time | Added {count} times + Added {count} Times: Already Added | Added {count} times CreatePlaylistPrompt: New Playlist Name: New Playlist name Create: Create From 4cd99fcab472ddb84ae2801f2403747b4676c164 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Tue, 16 Jan 2024 15:12:32 +0800 Subject: [PATCH 2/7] * Make additional text work for multi video adding --- .../ft-playlist-add-video-prompt.vue | 1 + .../ft-playlist-selector.js | 36 ++++++++++++++++++- .../ft-playlist-selector.vue | 2 +- static/locales/en-US.yaml | 2 ++ 4 files changed, 39 insertions(+), 2 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 7bbb722f619d3..ffc704659a4c8 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 @@ -69,6 +69,7 @@ :index="index" :selected="selectedPlaylistIdList.includes(playlist._id)" :disabled="playlistDisabled(playlist._id)" + :adding-duplicate-videos-enabled="addingDuplicateVideosEnabled" @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 d8e2385f7018f..3016a10a4125a 100644 --- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js +++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.js @@ -28,6 +28,10 @@ export default defineComponent({ type: Boolean, required: true, }, + addingDuplicateVideosEnabled: { + type: Boolean, + required: true, + }, }, emits: ['selected'], data: function () { @@ -80,10 +84,40 @@ export default defineComponent({ count: this.loneVideoPresenceCountInPlaylist, }) }, + multiVideoPresenceCountInPlaylist() { + if (this.toBeAddedToPlaylistVideoList.length < 2) { return null } + + // Count of to be added videos already present in this playlist + const v = this.toBeAddedToPlaylistVideoList.reduce((accumulator, toBeAddedToVideo) => { + return this.playlist.videos.some((pv) => pv.videoId === toBeAddedToVideo.videoId) + ? accumulator + 1 + : accumulator + }, 0) + // Don't display zero value + return v === 0 ? null : v + }, + multiVideoPresenceCountInPlaylistText() { + if (this.multiVideoPresenceCountInPlaylist == null) { return null } + + if (this.addingDuplicateVideosEnabled || this.toBeAddedToPlaylistVideoList.length === this.multiVideoPresenceCountInPlaylist) { + return this.$t('User Playlists.AddVideoPrompt.{videoCount}/{totalVideoCount} Videos Already Added', { + videoCount: this.multiVideoPresenceCountInPlaylist, + totalVideoCount: this.toBeAddedToPlaylistVideoList.length, + }) + } + + return this.$t('User Playlists.AddVideoPrompt.{videoCount}/{totalVideoCount} Videos Will Be Added', { + videoCount: this.toBeAddedToPlaylistVideoList.length - this.multiVideoPresenceCountInPlaylist, + totalVideoCount: this.toBeAddedToPlaylistVideoList.length, + }) + }, + videoPresenceCountInPlaylistText() { + return this.loneVideoPresenceCountInPlaylistText ?? this.multiVideoPresenceCountInPlaylistText + }, videoPresenceCountInPlaylistTextVisible() { if (!this.videoPresenceCountInPlaylistTextShouldBeVisible) { return false } - return this.loneVideoPresenceCountInPlaylistText != null + return this.videoPresenceCountInPlaylistText != null }, }, created: function () { 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 060043169c60f..4f5bc69a6521d 100644 --- a/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue +++ b/src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue @@ -45,7 +45,7 @@ v-if="videoPresenceCountInPlaylistTextVisible" class="videoPresenceCount" > - {{ loneVideoPresenceCountInPlaylistText }} + {{ videoPresenceCountInPlaylistText }} diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml index 4e4e6222f2f71..a94f8dd3d1401 100644 --- a/static/locales/en-US.yaml +++ b/static/locales/en-US.yaml @@ -219,6 +219,8 @@ User Playlists: Save: Save Added {count} Times: 'Already Added | Added {count} Times' + "{videoCount}/{totalVideoCount} Videos Will Be Added": '{videoCount}/{totalVideoCount} Videos Will Be Added' + "{videoCount}/{totalVideoCount} Videos Already Added": '{videoCount}/{totalVideoCount} Videos Already Added' Toast: You haven't selected any playlist yet.: You haven't selected any playlist yet. From f76c50fe6ee8710f45d7caf2c96b8f52e8ac06b0 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Sun, 5 May 2024 08:26:54 +0800 Subject: [PATCH 3/7] * Put controls toward the end --- .../ft-playlist-add-video-prompt.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 5c22f9d84728f..15d8b4f6c7500 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 @@ -24,9 +24,11 @@ .optionsRow { display: grid; - grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); + grid-template-columns: repeat(3, auto); + column-gap: 32px; grid-template-rows: 1fr; align-items: center; + justify-content: end; } @media only screen and (width <= 800px) { @@ -35,6 +37,7 @@ grid-template-columns: auto; grid-template-rows: repeat(auto-fit, auto); align-items: stretch; + justify-content: initial; } } From d717d96e739e968c54f2838456bc97fee62bd217 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Thu, 23 May 2024 10:15:51 +0800 Subject: [PATCH 4/7] * Add new label text to translation file --- .../ft-playlist-add-video-prompt.vue | 2 +- static/locales/en-US.yaml | 1 + 2 files changed, 2 insertions(+), 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 ffc704659a4c8..28688ad4c5322 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 @@ -37,7 +37,7 @@ Date: Sat, 25 May 2024 10:44:40 +0800 Subject: [PATCH 5/7] * Use set instead of array for performance --- .../ft-playlist-add-video-prompt.js | 4 ++-- 1 file changed, 2 insertions(+), 2 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 d1b61318a7267..c1808e6a52ed9 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 @@ -170,9 +170,9 @@ export default defineComponent({ const ids = [] this.allPlaylists.forEach((playlist) => { - const playlistVideoIds = playlist.videos.map((v) => v.videoId) + const playlistVideoIdSet = playlist.videos.reduce((s, v) => s.add(v.videoId), new Set()) - if (this.toBeAddedToPlaylistVideoIdList.every((vid) => playlistVideoIds.includes(vid))) { + if (this.toBeAddedToPlaylistVideoIdList.every((vid) => playlistVideoIdSet.has(vid))) { ids.push(playlist._id) } }) From 41c563d06a25b4b981e5aa0a2367b8a8bdf47fab Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Sat, 25 May 2024 10:46:55 +0800 Subject: [PATCH 6/7] * Add aria-disabled to disabled playlist selector --- .../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 28688ad4c5322..c6037226a6b7a 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 @@ -62,6 +62,7 @@ :class="{ disabled: playlistDisabled(playlist._id), }" + :aria-disabled="playlistDisabled(playlist._id)" > Date: Thu, 30 May 2024 09:36:39 +0800 Subject: [PATCH 7/7] * Move toggles to the left --- .../ft-playlist-add-video-prompt.css | 20 ++++++++--- .../ft-playlist-add-video-prompt.vue | 34 +++++++++++-------- 2 files changed, 34 insertions(+), 20 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 15d8b4f6c7500..ddcd76c767ac3 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 @@ -24,11 +24,15 @@ .optionsRow { display: grid; - grid-template-columns: repeat(3, auto); - column-gap: 32px; - grid-template-rows: 1fr; + grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); + align-items: center; +} + +.tightOptions { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(100px, max-content)); + column-gap: 16px; align-items: center; - justify-content: end; } @media only screen and (width <= 800px) { @@ -37,7 +41,13 @@ grid-template-columns: auto; grid-template-rows: repeat(auto-fit, auto); align-items: stretch; - justify-content: initial; + } + + .tightOptions { + /* Switch to rows from columns */ + grid-template-columns: auto; + grid-template-rows: repeat(auto-fit, auto); + align-items: stretch; } } 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 c6037226a6b7a..25116cc1f6708 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,21 +27,25 @@
- - +
+ + +