Skip to content

Commit

Permalink
Undo Feature For Remove From Playlist. (FreeTubeApp#5885)
Browse files Browse the repository at this point in the history
* changed logic to work with Custom as well.

* updated removeVideos

* linted

* resolving conflict

* updated changes
  • Loading branch information
Soham456 authored and Alban Dumas committed Jan 24, 2025
1 parent 2cef76c commit d7a0810
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 27 deletions.
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ const SyncEvents = {
UPSERT_VIDEO: 'sync-playlists-upsert-video',
UPSERT_VIDEOS: 'sync-playlists-upsert-videos',
DELETE_VIDEO: 'sync-playlists-delete-video',
DELETE_VIDEOS: 'sync-playlists-delete-videos',
},

SUBSCRIPTION_CACHE: {
Expand Down
4 changes: 2 additions & 2 deletions src/datastores/handlers/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,10 @@ class Playlists {
}
}

static deleteVideoIdsByPlaylistId(_id, videoIds) {
static deleteVideoIdsByPlaylistId(_id, playlistItemIds) {
return db.playlists.updateAsync(
{ _id },
{ $pull: { videos: { videoId: { $in: videoIds } } } },
{ $pull: { videos: { playlistItemId: { $in: playlistItemIds } } } },
{ upsert: true }
)
}
Expand Down
4 changes: 2 additions & 2 deletions src/datastores/handlers/electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,12 @@ class Playlists {
)
}

static deleteVideoIdsByPlaylistId(_id, videoIds) {
static deleteVideoIdsByPlaylistId(_id, playlistItemIds) {
return ipcRenderer.invoke(
IpcChannels.DB_PLAYLISTS,
{
action: DBActions.PLAYLISTS.DELETE_VIDEO_IDS,
data: { _id, videoIds }
data: { _id, playlistItemIds }
}
)
}
Expand Down
9 changes: 6 additions & 3 deletions src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1354,9 +1354,12 @@ function runApp() {
return null

case DBActions.PLAYLISTS.DELETE_VIDEO_IDS:
await baseHandlers.playlists.deleteVideoIdsByPlaylistId(data._id, data.videoIds)
// TODO: Syncing (implement only when it starts being used)
// syncOtherWindows(IpcChannels.SYNC_PLAYLISTS, event, { event: '_', data })
await baseHandlers.playlists.deleteVideoIdsByPlaylistId(data._id, data.playlistItemIds)
syncOtherWindows(
IpcChannels.SYNC_PLAYLISTS,
event,
{ event: SyncEvents.PLAYLISTS.DELETE_VIDEOS, data }
)
return null

case DBActions.PLAYLISTS.DELETE_ALL_VIDEOS:
Expand Down
11 changes: 7 additions & 4 deletions src/renderer/store/modules/playlists.js
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,8 @@ const actions = {

async removeVideos({ commit }, payload) {
try {
const { _id, videoIds } = payload
await DBPlaylistHandlers.deleteVideoIdsByPlaylistId(_id, videoIds)
const { _id, playlistItemIds } = payload
await DBPlaylistHandlers.deleteVideoIdsByPlaylistId(_id, playlistItemIds)
commit('removeVideos', payload)
} catch (errMessage) {
console.error(errMessage)
Expand Down Expand Up @@ -484,10 +484,13 @@ const mutations = {
}
},

removeVideos(state, { _id, videoId }) {
removeVideos(state, { _id, playlistItemIds }) {
const playlist = state.playlists.find(playlist => playlist._id === _id)
if (playlist) {
playlist.videos = playlist.videos.filter(video => videoId.indexOf(video) === -1)
playlist.videos = playlist.videos.filter(video => {
const playlistItemIdMatches = playlistItemIds.includes(video.playlistItemId)
return !playlistItemIdMatches
})
}
},

Expand Down
4 changes: 4 additions & 0 deletions src/renderer/store/modules/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,10 @@ const customActions = {
commit('removeVideo', data)
break

case SyncEvents.PLAYLISTS.DELETE_VIDEOS:
commit('removeVideos', data)
break

default:
console.error('playlists: invalid sync event received')
}
Expand Down
69 changes: 53 additions & 16 deletions src/renderer/views/Playlist/Playlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,17 @@ export default defineComponent({
userPlaylistVisibleLimit: 100,
continuationData: null,
isLoadingMore: false,
getPlaylistInfoDebounce: function() {},
getPlaylistInfoDebounce: function () { },
playlistInEditMode: false,
forceListView: false,
alreadyShownNotice: false,

videoSearchQuery: '',

promptOpen: false,
deletedVideoIds: [],
deletedPlaylistItemIds: [],
isUndoToast: false
}
},
computed: {
Expand All @@ -101,7 +104,7 @@ export default defineComponent({
currentLocale: function () {
return this.$i18n.locale
},
playlistId: function() {
playlistId: function () {
return this.$route.params.id
},
listType: function () {
Expand All @@ -126,7 +129,7 @@ export default defineComponent({
return []
}
},
selectedUserPlaylistVideoCount: function() {
selectedUserPlaylistVideoCount: function () {
return this.selectedUserPlaylistVideos.length
},

Expand Down Expand Up @@ -242,25 +245,25 @@ export default defineComponent({
},
},
watch: {
$route () {
$route() {
// react to route changes...
this.getPlaylistInfoDebounce()
},
userPlaylistsReady () {
userPlaylistsReady() {
// Fetch from local store when playlist data ready
if (!this.isUserPlaylistRequested) { return }

this.getPlaylistInfoDebounce()
},
selectedUserPlaylist () {
selectedUserPlaylist() {
// Fetch from local store when current user playlist changed
this.getPlaylistInfoDebounce()
},
selectedUserPlaylistLastUpdatedAt () {
selectedUserPlaylistLastUpdatedAt() {
// Re-fetch from local store when current user playlist updated
this.getPlaylistInfoDebounce()
},
selectedUserPlaylistVideoCount () {
selectedUserPlaylistVideoCount() {
// Monitoring `selectedUserPlaylistVideos` makes this function called
// Even when the same array object is returned
// So length is monitored instead
Expand Down Expand Up @@ -586,14 +589,48 @@ export default defineComponent({

removeVideoFromPlaylist: function (videoId, playlistItemId) {
try {
this.removeVideo({
_id: this.playlistId,
videoId: videoId,
playlistItemId: playlistItemId,
const playlistItems = [].concat(this.playlistItems)
const tempPlaylistItems = [].concat(this.playlistItems)
let isUndoClicked = false

const videoIndex = this.playlistItems.findIndex((video) => {
return video.videoId === videoId && video.playlistItemId === playlistItemId
})
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: this.playlistId })
showToast(this.$t('User Playlists.SinglePlaylistView.Toast.Video has been removed'))

if (videoIndex !== -1) {
this.deletedVideoIds.push(this.playlistItems[videoIndex].videoId)
this.deletedPlaylistItemIds.push(this.playlistItems[videoIndex].playlistItemId)
playlistItems.splice(videoIndex, 1)
this.playlistItems = playlistItems

// Only show toast when no existing toast shown
if (!this.isUndoToast) {
this.isUndoToast = true
showToast(
this.$t('User Playlists.SinglePlaylistView.Toast["Video has been removed. Click here to undo."]'),
5000,
() => {
this.playlistItems = tempPlaylistItems
isUndoClicked = true
this.isUndoToast = false
this.deletedVideoIds = []
this.deletedPlaylistItemIds = []
}
)
setTimeout(() => {
if (!isUndoClicked) {
this.removeVideos({
_id: this.playlistId,
videoIds: this.deletedVideoIds,
playlistItemIds: this.deletedPlaylistItemIds,
})
this.deletedVideoIds = []
this.deletedPlaylistItemIds = []
this.isUndoToast = false
}
}, 5000)
}
}
} catch (e) {
showToast(this.$t('User Playlists.SinglePlaylistView.Toast.There was a problem with removing this video'))
console.error(e)
Expand Down Expand Up @@ -648,7 +685,7 @@ export default defineComponent({
'updateSubscriptionDetails',
'updatePlaylist',
'updateUserPlaylistSortOrder',
'removeVideo',
'removeVideos',
]),

...mapMutations([
Expand Down
1 change: 1 addition & 0 deletions static/locales/en-US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ User Playlists:
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
Video has been removed. Click here to undo.: Video has been removed. Click here to undo.
There was a problem with removing this video: There was a problem with removing this video

This playlist is already being used for quick bookmark.: This playlist is already being used for quick bookmark.
Expand Down

0 comments on commit d7a0810

Please sign in to comment.