Skip to content

Commit f13f788

Browse files
authored
Make adding duplicate disabled by default (#5044)
* * Make adding duplicate disabled by default * * Make additional text work for multi video adding * * Put controls toward the end * * Add new label text to translation file * * Use set instead of array for performance * * Add aria-disabled to disabled playlist selector * * Move toggles to the left
1 parent aaea23b commit f13f788

File tree

7 files changed

+141
-19
lines changed

7 files changed

+141
-19
lines changed

src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.css

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,29 @@
2424

2525
.optionsRow {
2626
display: grid;
27-
grid-template-columns: repeat(2, 1fr);
28-
grid-template-rows: 1fr;
27+
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
28+
align-items: center;
29+
}
30+
31+
.tightOptions {
32+
display: grid;
33+
grid-template-columns: repeat(auto-fit, minmax(100px, max-content));
34+
column-gap: 16px;
2935
align-items: center;
3036
}
3137

3238
@media only screen and (width <= 800px) {
3339
.optionsRow {
34-
/* Switch to 2 rows from 2 columns */
40+
/* Switch to rows from columns */
3541
grid-template-columns: auto;
36-
grid-template-rows: auto auto;
42+
grid-template-rows: repeat(auto-fit, auto);
43+
align-items: stretch;
44+
}
45+
46+
.tightOptions {
47+
/* Switch to rows from columns */
48+
grid-template-columns: auto;
49+
grid-template-rows: repeat(auto-fit, auto);
3750
align-items: stretch;
3851
}
3952
}
@@ -51,7 +64,11 @@
5164
overflow-y: scroll;
5265
}
5366

54-
.playlist-selector-container {
67+
.playlist-selector-container:not(.disabled) {
5568
/* Make them look selectable */
5669
cursor: pointer;
5770
}
71+
72+
.playlist-selector-container.disabled {
73+
opacity: 0.5;
74+
}

src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.js

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export default defineComponent({
4545
updateQueryDebounce: function() {},
4646
lastShownAt: Date.now(),
4747
sortBy: SORT_BY_VALUES.LatestUpdatedFirst,
48+
addingDuplicateVideosEnabled: false,
4849
}
4950
},
5051
computed: {
@@ -111,6 +112,9 @@ export default defineComponent({
111112
toBeAddedToPlaylistVideoList: function () {
112113
return this.$store.getters.getToBeAddedToPlaylistVideoList
113114
},
115+
toBeAddedToPlaylistVideoIdList: function () {
116+
return this.toBeAddedToPlaylistVideoList.map((v) => v.videoId)
117+
},
114118
newPlaylistDefaultProperties: function () {
115119
return this.$store.getters.getNewPlaylistDefaultProperties
116120
},
@@ -161,6 +165,23 @@ export default defineComponent({
161165
sortBySelectValues() {
162166
return Object.values(SORT_BY_VALUES)
163167
},
168+
169+
playlistIdsContainingVideosToBeAdded() {
170+
const ids = []
171+
172+
this.allPlaylists.forEach((playlist) => {
173+
const playlistVideoIdSet = playlist.videos.reduce((s, v) => s.add(v.videoId), new Set())
174+
175+
if (this.toBeAddedToPlaylistVideoIdList.every((vid) => playlistVideoIdSet.has(vid))) {
176+
ids.push(playlist._id)
177+
}
178+
})
179+
180+
return ids
181+
},
182+
anyPlaylistContainsVideosToBeAdded() {
183+
return this.playlistIdsContainingVideosToBeAdded.length > 0
184+
},
164185
},
165186
watch: {
166187
allPlaylistsLength(val, oldVal) {
@@ -202,6 +223,16 @@ export default defineComponent({
202223
// due to enter key press in CreatePlaylistPrompt
203224
nextTick(() => this.$refs.searchBar.focus())
204225
},
226+
227+
addingDuplicateVideosEnabled(val) {
228+
if (val) { return }
229+
230+
// Only care when addingDuplicateVideosEnabled disabled
231+
// Remove disabled playlists
232+
this.selectedPlaylistIdList = this.selectedPlaylistIdList.filter(playlistId => {
233+
return !this.playlistIdsContainingVideosToBeAdded.includes(playlistId)
234+
})
235+
},
205236
},
206237
mounted: function () {
207238
this.updateQueryDebounce = debounce(this.updateQuery, 500)
@@ -238,10 +269,16 @@ export default defineComponent({
238269
const playlist = this.allPlaylists.find((list) => list._id === selectedPlaylistId)
239270
if (playlist == null) { return }
240271

272+
// Use [].concat to avoid `do not mutate vuex store state outside mutation handlers`
273+
let videosToBeAdded = [].concat(this.toBeAddedToPlaylistVideoList)
274+
if (!this.addingDuplicateVideosEnabled) {
275+
const playlistVideoIds = playlist.videos.map((v) => v.videoId)
276+
videosToBeAdded = videosToBeAdded.filter((v) => !playlistVideoIds.includes(v.videoId))
277+
}
278+
241279
this.addVideos({
242280
_id: playlist._id,
243-
// Use [].concat to avoid `do not mutate vuex store state outside mutation handlers`
244-
videos: [].concat(this.toBeAddedToPlaylistVideoList),
281+
videos: videosToBeAdded,
245282
})
246283
addedPlaylistIds.add(playlist._id)
247284
// Update playlist's `lastUpdatedAt`
@@ -281,6 +318,12 @@ export default defineComponent({
281318

282319
getIconForSortPreference: (s) => getIconForSortPreference(s),
283320

321+
playlistDisabled(playlistId) {
322+
if (this.addingDuplicateVideosEnabled) { return false }
323+
324+
return this.playlistIdsContainingVideosToBeAdded.includes(playlistId)
325+
},
326+
284327
...mapActions([
285328
'addVideos',
286329
'updatePlaylist',

src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,25 @@
2828
<div
2929
class="optionsRow"
3030
>
31-
<ft-toggle-switch
32-
:label="$t('User Playlists.Playlists with Matching Videos')"
33-
:compact="true"
34-
:default-value="doSearchPlaylistsWithMatchingVideos"
35-
@change="doSearchPlaylistsWithMatchingVideos = !doSearchPlaylistsWithMatchingVideos"
36-
/>
31+
<div
32+
class="tightOptions"
33+
>
34+
<ft-toggle-switch
35+
class="matchingVideoToggle"
36+
:label="$t('User Playlists.Playlists with Matching Videos')"
37+
:compact="true"
38+
:default-value="doSearchPlaylistsWithMatchingVideos"
39+
@change="doSearchPlaylistsWithMatchingVideos = !doSearchPlaylistsWithMatchingVideos"
40+
/>
41+
<ft-toggle-switch
42+
v-if="anyPlaylistContainsVideosToBeAdded"
43+
class="allowDuplicateToggle"
44+
:label="$t('User Playlists.AddVideoPrompt.Allow Adding Duplicate Video(s)')"
45+
:compact="true"
46+
:default-value="addingDuplicateVideosEnabled"
47+
@change="addingDuplicateVideosEnabled = !addingDuplicateVideosEnabled"
48+
/>
49+
</div>
3750
<ft-select
3851
v-if="allPlaylists.length > 1"
3952
class="sortSelect"
@@ -49,14 +62,20 @@
4962
<ft-flex-box>
5063
<div
5164
v-for="(playlist, index) in activePlaylists"
52-
:key="playlist._id"
65+
:key="`${playlist._id}-${playlistDisabled(playlist._id)}`"
5366
class="playlist-selector-container"
67+
:class="{
68+
disabled: playlistDisabled(playlist._id),
69+
}"
70+
:aria-disabled="playlistDisabled(playlist._id)"
5471
>
5572
<ft-playlist-selector
56-
tabindex="0"
73+
:tabindex="playlistDisabled(playlist._id) ? -1 : 0"
5774
:playlist="playlist"
5875
:index="index"
5976
:selected="selectedPlaylistIdList.includes(playlist._id)"
77+
:disabled="playlistDisabled(playlist._id)"
78+
:adding-duplicate-videos-enabled="addingDuplicateVideosEnabled"
6079
@selected="countSelected(playlist._id)"
6180
/>
6281
</div>

src/renderer/components/ft-playlist-selector/ft-playlist-selector.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ export default defineComponent({
2424
type: Boolean,
2525
required: true,
2626
},
27+
disabled: {
28+
type: Boolean,
29+
required: true,
30+
},
31+
addingDuplicateVideosEnabled: {
32+
type: Boolean,
33+
required: true,
34+
},
2735
},
2836
emits: ['selected'],
2937
data: function () {
@@ -76,10 +84,40 @@ export default defineComponent({
7684
count: this.loneVideoPresenceCountInPlaylist,
7785
})
7886
},
87+
multiVideoPresenceCountInPlaylist() {
88+
if (this.toBeAddedToPlaylistVideoList.length < 2) { return null }
89+
90+
// Count of to be added videos already present in this playlist
91+
const v = this.toBeAddedToPlaylistVideoList.reduce((accumulator, toBeAddedToVideo) => {
92+
return this.playlist.videos.some((pv) => pv.videoId === toBeAddedToVideo.videoId)
93+
? accumulator + 1
94+
: accumulator
95+
}, 0)
96+
// Don't display zero value
97+
return v === 0 ? null : v
98+
},
99+
multiVideoPresenceCountInPlaylistText() {
100+
if (this.multiVideoPresenceCountInPlaylist == null) { return null }
101+
102+
if (this.addingDuplicateVideosEnabled || this.toBeAddedToPlaylistVideoList.length === this.multiVideoPresenceCountInPlaylist) {
103+
return this.$t('User Playlists.AddVideoPrompt.{videoCount}/{totalVideoCount} Videos Already Added', {
104+
videoCount: this.multiVideoPresenceCountInPlaylist,
105+
totalVideoCount: this.toBeAddedToPlaylistVideoList.length,
106+
})
107+
}
108+
109+
return this.$t('User Playlists.AddVideoPrompt.{videoCount}/{totalVideoCount} Videos Will Be Added', {
110+
videoCount: this.toBeAddedToPlaylistVideoList.length - this.multiVideoPresenceCountInPlaylist,
111+
totalVideoCount: this.toBeAddedToPlaylistVideoList.length,
112+
})
113+
},
114+
videoPresenceCountInPlaylistText() {
115+
return this.loneVideoPresenceCountInPlaylistText ?? this.multiVideoPresenceCountInPlaylistText
116+
},
79117
videoPresenceCountInPlaylistTextVisible() {
80118
if (!this.videoPresenceCountInPlaylistTextShouldBeVisible) { return false }
81119

82-
return this.loneVideoPresenceCountInPlaylistText != null
120+
return this.videoPresenceCountInPlaylistText != null
83121
},
84122
},
85123
created: function () {
@@ -100,6 +138,8 @@ export default defineComponent({
100138
},
101139

102140
toggleSelection: function () {
141+
if (this.disabled) { return }
142+
103143
this.$emit('selected', this.index)
104144
},
105145

src/renderer/components/ft-playlist-selector/ft-playlist-selector.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
v-if="videoPresenceCountInPlaylistTextVisible"
4646
class="videoPresenceCount"
4747
>
48-
{{ loneVideoPresenceCountInPlaylistText }}
48+
{{ videoPresenceCountInPlaylistText }}
4949
</div>
5050
</div>
5151
</div>

static/locales/en-US.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,12 @@ User Playlists:
236236
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'
237237
N playlists selected: '{playlistCount} Selected'
238238
Search in Playlists: Search in Playlists
239+
Allow Adding Duplicate Video(s): Allow Adding Duplicate Video(s)
239240
Save: Save
240241

241-
Added {count} Times: 'Added {count} Time | Added {count} Times'
242+
Added {count} Times: 'Already Added | Added {count} Times'
243+
"{videoCount}/{totalVideoCount} Videos Will Be Added": '{videoCount}/{totalVideoCount} Videos Will Be Added'
244+
"{videoCount}/{totalVideoCount} Videos Already Added": '{videoCount}/{totalVideoCount} Videos Already Added'
242245

243246
Toast:
244247
You haven't selected any playlist yet.: You haven't selected any playlist yet.

static/locales/en_GB.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ User Playlists:
190190
playlists
191191
Select a playlist to add your N videos to: Select a playlist to add your video
192192
to | Select a playlist to add your {videoCount} videos to
193-
Added {count} Times: Added {count} time | Added {count} times
193+
Added {count} Times: Already Added | Added {count} times
194194
CreatePlaylistPrompt:
195195
New Playlist Name: New Playlist name
196196
Create: Create

0 commit comments

Comments
 (0)