Skip to content
Open
2 changes: 2 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ const DBActions = {
HISTORY: {
UPDATE_WATCH_PROGRESS: 20,
UPDATE_PLAYLIST: 21,
UNSET_PLAYLIST_FOR_VIDEOS: 22,
UNSET_PLAYLISTS: 23
},

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

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

static unsetLastViewedPlaylists(lastViewedPlaylistIds) {
return db.history.updateAsync(
{
lastViewedPlaylistId: { $in: lastViewedPlaylistIds }
},
{ $unset: { lastViewedPlaylistId: '', lastViewedPlaylistType: '', lastViewedPlaylistItemId: '' } },
{ multi: true }
)
}

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

static unsetLastViewedPlaylistForVideos(videoIds, lastViewedPlaylistId) {
return window.ftElectron.dbHistory(DBActions.HISTORY.UNSET_PLAYLIST_FOR_VIDEOS, { videoIds, lastViewedPlaylistId })
}

static unsetLastViewedPlaylists(lastViewedPlaylistIds) {
return window.ftElectron.dbHistory(DBActions.HISTORY.UNSET_PLAYLISTS, lastViewedPlaylistIds)
}

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

case DBActions.HISTORY.UNSET_PLAYLIST_FOR_VIDEOS:
await baseHandlers.history.unsetLastViewedPlaylistForVideos(data.videoIds, data.lastViewedPlaylistId)
syncOtherWindows(
IpcChannels.SYNC_HISTORY,
event,
{ event: SyncEvents.HISTORY.UNSET_PLAYLIST_FOR_VIDEOS, data }
)
return null

case DBActions.HISTORY.UNSET_PLAYLISTS:
await baseHandlers.history.unsetLastViewedPlaylists(data)
syncOtherWindows(
IpcChannels.SYNC_HISTORY,
event,
{ event: SyncEvents.HISTORY.UNSET_PLAYLISTS, data }
)
return null

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

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

async unsetLastViewedPlaylists({ commit }, lastViewedPlaylistIds) {
try {
await DBHistoryHandlers.unsetLastViewedPlaylists(lastViewedPlaylistIds)
commit('unsetRecordsLastViewedPlaylistIdsInHistoryCache', lastViewedPlaylistIds)
} catch (errMessage) {
console.error(errMessage)
}
},
}

const mutations = {
Expand Down Expand Up @@ -153,6 +171,35 @@ const mutations = {
}
},

unsetRecordsLastViewedPlaylistIdInHistoryCache(state, { videoIds, lastViewedPlaylistId }) {
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 was removed from the watch history or if the last viewed playlist does not match
if (record && record.lastViewedPlaylistId === lastViewedPlaylistId) {
delete record.lastViewedPlaylistId
delete record.lastViewedPlaylistType
delete record.lastViewedPlaylistItemId
}
}
},

unsetRecordsLastViewedPlaylistIdsInHistoryCache(state, playlistIds) {
const playlistIdSet = new Set(playlistIds)

for (const record of state.historyCacheSorted) {
// Don't unset if the item was removed from the watch history or if the last viewed playlist does not match
if (record && playlistIdSet.has(record.lastViewedPlaylistId)) {
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
27 changes: 20 additions & 7 deletions src/renderer/store/modules/playlists.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,46 +369,57 @@ const actions = {
}
},

async removeAllPlaylists({ commit }) {
async removeAllPlaylists({ commit, dispatch, getters }) {
try {
const playlistIds = getters.getAllPlaylists.map(playlist => playlist._id)
await dispatch('unsetLastViewedPlaylists', playlistIds)

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

async removeAllVideos({ commit }, _id) {
async removeAllVideos({ commit, dispatch }, _id) {
try {
await dispatch('unsetLastViewedPlaylists', [_id])

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

async removePlaylist({ commit }, playlistId) {
async removePlaylist({ commit, dispatch }, playlistId) {
try {
await dispatch('unsetLastViewedPlaylists', [playlistId])

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

async removePlaylists({ commit }, playlistIds) {
async removePlaylists({ commit, dispatch }, playlistIds) {
try {
await dispatch('unsetLastViewedPlaylists', playlistIds)

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('unsetLastViewedPlaylistForVideos', { videoIds: [videoId], lastViewedPlaylistId: _id })

const lastUpdatedAt = Date.now()

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

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

await dispatch('unsetLastViewedPlaylistForVideos', { videoIds, lastViewedPlaylistId: _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 @@ -243,6 +243,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 @@ -852,6 +854,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 @@ -868,6 +871,7 @@ function removeVideoFromPlaylist(videoId, playlistItemId) {
() => {
clearTimeout(actualRemoveVideosTimeout)
toBeDeletedPlaylistItemIds.value = []
videosWithPlaylistToUnset.value = []
undoToastAbortController = null
},
undoToastAbortController.signal,
Expand All @@ -886,11 +890,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