diff --git a/src/constants.js b/src/constants.js index 0ae194d19a6cd..bac4c5b45de24 100644 --- a/src/constants.js +++ b/src/constants.js @@ -29,10 +29,12 @@ const IpcChannels = { DB_HISTORY: 'db-history', DB_PROFILES: 'db-profiles', DB_PLAYLISTS: 'db-playlists', + DB_SEARCH_HISTORY: 'db-search-history', DB_SUBSCRIPTION_CACHE: 'db-subscription-cache', SYNC_SETTINGS: 'sync-settings', SYNC_HISTORY: 'sync-history', + SYNC_SEARCH_HISTORY: 'sync-search-history', SYNC_PROFILES: 'sync-profiles', SYNC_PLAYLISTS: 'sync-playlists', SYNC_SUBSCRIPTION_CACHE: 'sync-subscription-cache', diff --git a/src/datastores/handlers/base.js b/src/datastores/handlers/base.js index 18411722951a1..1d98fd2c4c3cd 100644 --- a/src/datastores/handlers/base.js +++ b/src/datastores/handlers/base.js @@ -226,6 +226,32 @@ class Playlists { } } +class SearchHistory { + static create(pageBookmark) { + return db.searchHistory.insertAsync(pageBookmark) + } + + static find() { + return db.searchHistory.findAsync({}) + } + + static upsert(pageBookmark) { + return db.searchHistory.updateAsync({ _id: pageBookmark._id }, pageBookmark, { upsert: true }) + } + + static delete(_id) { + return db.searchHistory.removeAsync({ _id: _id }) + } + + static deleteMultiple(ids) { + return db.searchHistory.removeAsync({ _id: { $in: ids } }) + } + + static deleteAll() { + return db.searchHistory.removeAsync({}, { multi: true }) + } +} + class SubscriptionCache { static find() { return db.subscriptionCache.findAsync({}) @@ -311,6 +337,7 @@ function compactAllDatastores() { db.history.compactDatafileAsync(), db.profiles.compactDatafileAsync(), db.playlists.compactDatafileAsync(), + db.searchHistory.compactDatafileAsync(), db.subscriptionCache.compactDatafileAsync(), ]) } @@ -320,6 +347,7 @@ export { History as history, Profiles as profiles, Playlists as playlists, + SearchHistory as searchHistory, SubscriptionCache as subscriptionCache, compactAllDatastores, diff --git a/src/datastores/handlers/electron.js b/src/datastores/handlers/electron.js index 889c91d4f060c..68b95f1fd0b60 100644 --- a/src/datastores/handlers/electron.js +++ b/src/datastores/handlers/electron.js @@ -218,6 +218,50 @@ class Playlists { } } +class SearchHistory { + static create(pageBookmark) { + return ipcRenderer.invoke( + IpcChannels.DB_SEARCH_HISTORY, + { action: DBActions.GENERAL.CREATE, data: pageBookmark } + ) + } + + static find() { + return ipcRenderer.invoke( + IpcChannels.DB_SEARCH_HISTORY, + { action: DBActions.GENERAL.FIND } + ) + } + + static upsert(pageBookmark) { + return ipcRenderer.invoke( + IpcChannels.DB_SEARCH_HISTORY, + { action: DBActions.GENERAL.UPSERT, data: pageBookmark } + ) + } + + static delete(_id) { + return ipcRenderer.invoke( + IpcChannels.DB_SEARCH_HISTORY, + { action: DBActions.GENERAL.DELETE, data: _id } + ) + } + + static deleteMultiple(ids) { + return ipcRenderer.invoke( + IpcChannels.DB_SEARCH_HISTORY, + { action: DBActions.GENERAL.DELETE_MULTIPLE, data: ids } + ) + } + + static deleteAll() { + return ipcRenderer.invoke( + IpcChannels.DB_SEARCH_HISTORY, + { action: DBActions.GENERAL.DELETE_ALL } + ) + } +} + class SubscriptionCache { static find() { return ipcRenderer.invoke( @@ -296,5 +340,6 @@ export { History as history, Profiles as profiles, Playlists as playlists, + SearchHistory as searchHistory, SubscriptionCache as subscriptionCache, } diff --git a/src/datastores/handlers/index.js b/src/datastores/handlers/index.js index 6d9b8ab729d43..1409b1cd3a450 100644 --- a/src/datastores/handlers/index.js +++ b/src/datastores/handlers/index.js @@ -3,5 +3,6 @@ export { history as DBHistoryHandlers, profiles as DBProfileHandlers, playlists as DBPlaylistHandlers, + searchHistory as DBSearchHistoryHandlers, subscriptionCache as DBSubscriptionCacheHandlers, } from 'DB_HANDLERS_ELECTRON_RENDERER_OR_WEB' diff --git a/src/datastores/handlers/web.js b/src/datastores/handlers/web.js index d68e24f042615..b06b8c62ac75e 100644 --- a/src/datastores/handlers/web.js +++ b/src/datastores/handlers/web.js @@ -122,6 +122,32 @@ class Playlists { } } +class SearchHistory { + static create(pageBookmark) { + return baseHandlers.searchHistory.create(pageBookmark) + } + + static find() { + return baseHandlers.searchHistory.find() + } + + static upsert(pageBookmark) { + return baseHandlers.searchHistory.upsert(pageBookmark) + } + + static delete(_id) { + return baseHandlers.searchHistory.delete(_id) + } + + static deleteMultiple(ids) { + return baseHandlers.searchHistory.deleteMultiple(ids) + } + + static deleteAll() { + return baseHandlers.searchHistory.deleteAll() + } +} + class SubscriptionCache { static find() { return baseHandlers.subscriptionCache.find() @@ -180,5 +206,6 @@ export { History as history, Profiles as profiles, Playlists as playlists, + SearchHistory as searchHistory, SubscriptionCache as subscriptionCache, } diff --git a/src/datastores/index.js b/src/datastores/index.js index 7a3da53356f00..37a27b12cff89 100644 --- a/src/datastores/index.js +++ b/src/datastores/index.js @@ -26,4 +26,5 @@ export const settings = new Datastore({ filename: dbPath('settings'), autoload: export const profiles = new Datastore({ filename: dbPath('profiles'), autoload: true }) export const playlists = new Datastore({ filename: dbPath('playlists'), autoload: true }) export const history = new Datastore({ filename: dbPath('history'), autoload: true }) +export const searchHistory = new Datastore({ filename: dbPath('search-history'), autoload: true }) export const subscriptionCache = new Datastore({ filename: dbPath('subscription-cache'), autoload: true }) diff --git a/src/main/index.js b/src/main/index.js index eb3376c0776d2..2376bcaac96f8 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1340,6 +1340,64 @@ function runApp() { } }) + // ************** // + // Search History + ipcMain.handle(IpcChannels.DB_SEARCH_HISTORY, async (event, { action, data }) => { + try { + switch (action) { + case DBActions.GENERAL.CREATE: { + const pageBookmark = await baseHandlers.searchHistory.create(data) + syncOtherWindows( + IpcChannels.SYNC_SEARCH_HISTORY, + event, + { event: SyncEvents.GENERAL.CREATE, data } + ) + return pageBookmark + } + case DBActions.GENERAL.FIND: + return await baseHandlers.searchHistory.find() + + case DBActions.GENERAL.UPSERT: + await baseHandlers.searchHistory.upsert(data) + syncOtherWindows( + IpcChannels.SYNC_SEARCH_HISTORY, + event, + { event: SyncEvents.GENERAL.UPSERT, data } + ) + return null + + case DBActions.GENERAL.DELETE: + await baseHandlers.searchHistory.delete(data) + syncOtherWindows( + IpcChannels.SYNC_SEARCH_HISTORY, + event, + { event: SyncEvents.GENERAL.DELETE, data } + ) + return null + + case DBActions.GENERAL.DELETE_MULTIPLE: + await baseHandlers.searchHistory.deleteMultiple(data) + syncOtherWindows( + IpcChannels.SYNC_SEARCH_HISTORY, + event, + { event: SyncEvents.GENERAL.DELETE_MULTIPLE, data } + ) + return null + + case DBActions.GENERAL.DELETE_ALL: + await baseHandlers.searchHistory.deleteAll() + return null + + default: + // eslint-disable-next-line no-throw-literal + throw 'invalid search history db action' + } + } catch (err) { + if (typeof err === 'string') throw err + else throw err.toString() + } + }) + // *********** // // *********** // diff --git a/src/renderer/App.js b/src/renderer/App.js index 372be1665bbeb..ed2164bfcc1f2 100644 --- a/src/renderer/App.js +++ b/src/renderer/App.js @@ -10,6 +10,7 @@ import FtToast from './components/ft-toast/ft-toast.vue' import FtProgressBar from './components/FtProgressBar/FtProgressBar.vue' import FtPlaylistAddVideoPrompt from './components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue' import FtCreatePlaylistPrompt from './components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue' +import PageBookmarkPrompt from './components/PageBookmarkPrompt/PageBookmarkPrompt.vue' import FtSearchFilters from './components/FtSearchFilters/FtSearchFilters.vue' import { marked } from 'marked' import { IpcChannels } from '../constants' @@ -32,6 +33,7 @@ export default defineComponent({ FtProgressBar, FtPlaylistAddVideoPrompt, FtCreatePlaylistPrompt, + PageBookmarkPrompt, FtSearchFilters }, data: function () { @@ -40,6 +42,7 @@ export default defineComponent({ showUpdatesBanner: false, showBlogBanner: false, showReleaseNotes: false, + pageBookmarksAvailable: false, updateBannerMessage: '', blogBannerMessage: '', latestBlogUrl: '', @@ -77,6 +80,9 @@ export default defineComponent({ showCreatePlaylistPrompt: function () { return this.$store.getters.getShowCreatePlaylistPrompt }, + showPageBookmarkPrompt: function () { + return this.$store.getters.getShowPageBookmarkPrompt + }, showSearchFilters: function () { return this.$store.getters.getShowSearchFilters }, @@ -188,6 +194,9 @@ export default defineComponent({ this.grabAllProfiles(this.$t('Profile.All Channels')).then(async () => { this.grabHistory() this.grabAllPlaylists() + this.grabPageBookmarks().then(() => { + this.pageBookmarksAvailable = true + }) this.grabAllSubscriptions() if (process.env.IS_ELECTRON) { @@ -568,6 +577,7 @@ export default defineComponent({ 'grabUserSettings', 'grabAllProfiles', 'grabHistory', + 'grabPageBookmarks', 'grabAllPlaylists', 'grabAllSubscriptions', 'getYoutubeUrlInfo', diff --git a/src/renderer/App.vue b/src/renderer/App.vue index a0235a5854898..21acc7e1abeef 100644 --- a/src/renderer/App.vue +++ b/src/renderer/App.vue @@ -56,6 +56,9 @@ + + +

+ {{ title }} +

+
+ + +

{{ $tc('Page Bookmark["There is {count} other bookmark with the same name."]', duplicateNameCount, { count: duplicateNameCount }) }}

+
+
+
+ + + + + +
+
+ + + + +