Skip to content
Open
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const DBActions = {
HISTORY: {
UPDATE_WATCH_PROGRESS: 20,
UPDATE_PLAYLIST: 21,
UNSET_PLAYLIST: 22,
},

PROFILES: {
Expand Down
11 changes: 11 additions & 0 deletions src/datastores/handlers/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@ class History {
return db.history.updateAsync({ videoId }, { $set: { lastViewedPlaylistId, lastViewedPlaylistType, lastViewedPlaylistItemId } }, { upsert: true })
}

static unsetLastViewedPlaylist(videoIds, playlistId) {
return db.history.updateAsync(
{
videoId: { $in: videoIds },
lastViewedPlaylistId: playlistId
},
{ $unset: { lastViewedPlaylistId: '', lastViewedPlaylistType: '', lastViewedPlaylistItemId: '' } },
{ multi: true }
)
}

static delete(videoId) {
return db.history.removeAsync({ videoId })
}
Expand Down
4 changes: 4 additions & 0 deletions src/datastores/handlers/electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ class History {
)
}

static unsetLastViewedPlaylist(videoIds, playlistId) {
return window.ftElectron.dbHistory(DBActions.HISTORY.UNSET_PLAYLIST, { videoIds, playlistId })
}

static delete(videoId) {
return window.ftElectron.dbHistory(DBActions.GENERAL.DELETE, videoId)
}
Expand Down
9 changes: 9 additions & 0 deletions src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1725,6 +1725,15 @@ function runApp() {
)
return null

case DBActions.HISTORY.UNSET_PLAYLIST:
await baseHandlers.history.unsetLastViewedPlaylist(data.videoIds, data.playlistId)
syncOtherWindows(
IpcChannels.SYNC_HISTORY,
event,
{ event: SyncEvents.HISTORY.UNSET_PLAYLIST, data }
)
return null

case DBActions.GENERAL.DELETE:
await baseHandlers.history.delete(data)
syncOtherWindows(
Expand Down
25 changes: 25 additions & 0 deletions src/renderer/store/modules/history.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ const actions = {
console.error(errMessage)
}
},

async unsetLastViewedPlaylist({ commit }, { videoIds, playlistId }) {
try {
await DBHistoryHandlers.unsetLastViewedPlaylist(videoIds, playlistId)
commit('unsetRecordsLastViewedPlaylistIdInHistoryCache', { videoIds, playlistId })
} catch (errMessage) {
console.error(errMessage)
}
},
}

const mutations = {
Expand Down Expand Up @@ -153,6 +162,22 @@ const mutations = {
}
},

unsetRecordsLastViewedPlaylistIdInHistoryCache(state, { videoIds, playlistId }) {
for (const videoId of videoIds) {
// historyCacheById and historyCacheSorted reference the same object instances,
// so modifying an existing object in one of them will update both.

const record = state.historyCacheById[videoId]

// Don't unset if the item is not part of the watch history or if the playlist does not match
if (record && record.lastViewedPlaylistId === playlistId) {
delete record.lastViewedPlaylistId
delete record.lastViewedPlaylistType
delete record.lastViewedPlaylistItemId
}
}
},

removeFromHistoryCacheById(state, videoId) {
for (let i = 0; i < state.historyCacheSorted.length; i++) {
if (state.historyCacheSorted[i].videoId === videoId) {
Expand Down
39 changes: 32 additions & 7 deletions src/renderer/store/modules/playlists.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,46 +369,69 @@ const actions = {
}
},

async removeAllPlaylists({ commit }) {
async removeAllPlaylists({ commit, dispatch, getters }) {
try {
const playlists = getters.getAllPlaylists()
for (const playlist of playlists) {
const videoIds = playlist.videos.map(video => video.videoId)
const playlistId = playlist._id
await dispatch('unsetLastViewedPlaylist', { videoIds, playlistId })
}

await DBPlaylistHandlers.deleteAll()
commit('removeAllPlaylists')
} catch (errMessage) {
console.error(errMessage)
}
},

async removeAllVideos({ commit }, _id) {
async removeAllVideos({ commit, dispatch, getters }, _id) {
try {
const playlist = getters.getPlaylist(_id)
const videoIds = playlist.videos.map(video => video.videoId)
await dispatch('unsetLastViewedPlaylist', { videoIds, playlistId: _id })

await DBPlaylistHandlers.deleteAllVideosByPlaylistId(_id)
commit('removeAllVideos', _id)
} catch (errMessage) {
console.error(errMessage)
}
},

async removePlaylist({ commit }, playlistId) {
async removePlaylist({ commit, dispatch, getters }, playlistId) {
try {
const playlist = getters.getPlaylist(playlistId)
const videoIds = playlist.videos.map(video => video.videoId)
await dispatch('unsetLastViewedPlaylist', { videoIds, playlistId })

await DBPlaylistHandlers.delete(playlistId)
commit('removePlaylist', playlistId)
} catch (errMessage) {
console.error(errMessage)
}
},

async removePlaylists({ commit }, playlistIds) {
async removePlaylists({ commit, dispatch, getters }, playlistIds) {
try {
for (const playlistId of playlistIds) {
const playlist = getters.getPlaylist(playlistId)
const videoIds = playlist.videos.map(video => video.videoId)
await dispatch('unsetLastViewedPlaylist', { videoIds, playlistId })
}

await DBPlaylistHandlers.deleteMultiple(playlistIds)
commit('removePlaylists', playlistIds)
} catch (errMessage) {
console.error(errMessage)
}
},

async removeVideo({ commit }, payload) {
async removeVideo({ commit, dispatch }, payload) {
try {
const { _id, videoId, playlistItemId } = payload

await dispatch('unsetLastViewedPlaylist', { videoIds: [videoId], playlistId: _id })

const lastUpdatedAt = Date.now()

await DBPlaylistHandlers.deleteVideoIdByPlaylistId(_id, lastUpdatedAt, videoId, playlistItemId)
Expand All @@ -421,9 +444,11 @@ const actions = {
}
},

async removeVideos({ commit }, payload) {
async removeVideos({ commit, dispatch }, payload) {
try {
const { _id, playlistItemIds } = payload
const { _id, playlistItemIds, videoIds } = payload

await dispatch('unsetLastViewedPlaylist', { videoIds, playlistId: _id })

const lastUpdatedAt = Date.now()

Expand Down
8 changes: 7 additions & 1 deletion src/renderer/views/Playlist/Playlist.vue
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ const videoSearchQuery = ref('')
const promptOpen = ref(false)
/** @type {import('vue').Ref<string[]>} */
const toBeDeletedPlaylistItemIds = ref([])
/** @type {import('vue').Ref<string[]>} */
const videosWithPlaylistToUnset = ref([])
/** @type {AbortController | null} */
let undoToastAbortController = null

Expand Down Expand Up @@ -851,6 +853,7 @@ function removeVideoFromPlaylist(videoId, playlistItemId) {

if (foundVideo) {
toBeDeletedPlaylistItemIds.value.push(playlistItemId)
videosWithPlaylistToUnset.value.push(videoId)

// Only show toast when no existing toast shown
if (undoToastAbortController == null) {
Expand All @@ -867,6 +870,7 @@ function removeVideoFromPlaylist(videoId, playlistItemId) {
() => {
clearTimeout(actualRemoveVideosTimeout)
toBeDeletedPlaylistItemIds.value = []
videosWithPlaylistToUnset.value = []
undoToastAbortController = null
},
undoToastAbortController.signal,
Expand All @@ -885,11 +889,13 @@ async function removeToBeDeletedVideosSometimes() {
if (toBeDeletedPlaylistItemIds.value.length > 0) {
await store.dispatch('removeVideos', {
_id: playlistId.value,
// Create a new non-reactive array to avoid Electron erroring about Proxy objects not being clonable
// Create new non-reactive arrays to avoid Electron erroring about Proxy objects not being clonable
playlistItemIds: [...toBeDeletedPlaylistItemIds.value],
videoIds: [...videosWithPlaylistToUnset.value],
})

toBeDeletedPlaylistItemIds.value = []
videosWithPlaylistToUnset.value = []
undoToastAbortController?.abort()
undoToastAbortController = null
}
Expand Down