diff --git a/package.json b/package.json index b22c5a37..93bb7ffd 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "emoji-mart-vue": "^2.6.6", "i18next": "^21.3.3", "lodash": "^4.17.21", + "lokijs": "^1.5.12", "megalodon": "3.6.7", "minimist": "^1.2.5", "moment": "^2.29.1", @@ -125,6 +126,7 @@ "@types/i18next": "^13.0.0", "@types/jest": "27.0.2", "@types/lodash": "^4.14.176", + "@types/lokijs": "^1.5.7", "@types/nedb": "^1.8.12", "@types/node": "^16.11.6", "@types/parse-link-header": "^1.0.0", diff --git a/src/main/database.ts b/src/main/database.ts new file mode 100644 index 00000000..51558345 --- /dev/null +++ b/src/main/database.ts @@ -0,0 +1,22 @@ +import Loki from 'lokijs' + +const newDB = (file: string): Promise => { + return new Promise(resolve => { + const databaseInitializer = () => { + let markers = db.getCollection('markers') + if (markers === null) { + markers = db.addCollection('markers') + } + resolve(db) + } + + const db = new Loki(file, { + autoload: true, + autosave: true, + autosaveInterval: 4000, + autoloadCallback: databaseInitializer + }) + }) +} + +export default newDB diff --git a/src/main/index.ts b/src/main/index.ts index 5134de43..5a30aa18 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -55,6 +55,7 @@ import { EnabledTimelines } from '~/src/types/enabledTimelines' import { Menu as MenuPreferences } from '~/src/types/preference' import { LocalMarker } from '~/src/types/localMarker' import Marker from './marker' +import newDB from './database' /** * Context menu @@ -141,12 +142,9 @@ unreadNotification.initialize().catch((err: Error) => log.error(err)) const preferencesDBPath = process.env.NODE_ENV === 'production' ? userData + './db/preferences.json' : 'preferences.json' -const markerDBPath = process.env.NODE_ENV === 'production' ? userData + '/db/marker.db' : 'marker.db' -const markerDB = new Datastore({ - filename: markerDBPath, - autoload: true -}) -const markerRepo = new Marker(markerDB) +const lokiDatabasePath = process.env.NODE_ENV === 'production' ? userData + '/db/lokiDatabase.db' : 'lokiDatabase.db' + +let markerRepo: Marker | null = null /** * Cache path @@ -257,6 +255,11 @@ const updateDockMenu = async (accountsChange: Array) } async function createWindow() { + /** + DB + */ + const lokiDB = await newDB(lokiDatabasePath) + markerRepo = new Marker(lokiDB) /** * List accounts */ @@ -1160,11 +1163,17 @@ ipcMain.handle('update-spellchecker-languages', async (_: IpcMainInvokeEvent, la // marker ipcMain.handle('get-home-marker', async (_: IpcMainInvokeEvent, ownerID: string) => { + if (markerRepo === null) { + return null + } const marker = await markerRepo.get(ownerID, 'home') return marker }) ipcMain.handle('get-notifications-marker', async (_: IpcMainInvokeEvent, ownerID: string) => { + if (markerRepo === null) { + return null + } const marker = await markerRepo.get(ownerID, 'notifications') return marker }) @@ -1175,6 +1184,9 @@ ipcMain.on( if (marker.owner_id === null || marker.owner_id === undefined || marker.owner_id === '') { return null } + if (markerRepo === null) { + return null + } const res = await markerRepo.save(marker) return res } diff --git a/src/main/marker.ts b/src/main/marker.ts index ef3d0c4c..a4cdf89e 100644 --- a/src/main/marker.ts +++ b/src/main/marker.ts @@ -1,21 +1,22 @@ import { isEmpty } from 'lodash' -import Datastore from 'nedb' +import Loki, { Collection } from 'lokijs' import { LocalMarker } from '~/src/types/localMarker' export default class Marker { - private db: Datastore + private markers: Collection - constructor(db: Datastore) { - this.db = db - this.db.persistence.setAutocompactionInterval(60000) // milliseconds + constructor(db: Loki) { + this.markers = db.getCollection('markers') } private insert(marker: LocalMarker): Promise { return new Promise((resolve, reject) => { - this.db.insert(marker, (err, doc) => { - if (err) return reject(err) + try { + const doc: LocalMarker = this.markers.insert(marker) resolve(doc) - }) + } catch (err) { + reject(err) + } }) } @@ -23,18 +24,20 @@ export default class Marker { // @ts-ignore return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars - this.db.update( - { - owner_id: marker.owner_id, - timeline: marker.timeline - }, - { $set: marker }, - { multi: false }, - err => { - if (err) return reject(err) - return this.get(marker.owner_id, marker.timeline) - } - ) + try { + this.markers.findAndUpdate( + { + owner_id: { $eq: marker.owner_id }, + timeline: { $eq: marker.timeline } + }, + (item: LocalMarker) => { + item.last_read_id = marker.last_read_id + } + ) + return this.get(marker.owner_id, marker.timeline) + } catch (err) { + reject(err) + } }) } @@ -47,21 +50,28 @@ export default class Marker { public async get(owner_id: string, timeline: 'home' | 'notifications'): Promise { return new Promise((resolve, reject) => { - this.db.findOne({ owner_id: owner_id, timeline: timeline }, (err, doc) => { - if (err) return reject(err) + try { + const doc: LocalMarker | null = this.markers.findOne({ + owner_id: { $eq: owner_id }, + timeline: { $eq: timeline } + }) resolve(doc) - }) + } catch (err) { + reject(err) + } }) } public async list(owner_id: string): Promise> { return new Promise((resolve, reject) => { - this.db - .find({ owner_id: owner_id }) - .exec((err, docs) => { - if (err) return reject(err) - resolve(docs) + try { + const docs: Array = this.markers.find({ + owner_id: { $eq: owner_id } }) + resolve(docs) + } catch (err) { + reject(err) + } }) } } diff --git a/yarn.lock b/yarn.lock index 1e3ba4e9..bcdb3710 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1592,6 +1592,11 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.176.tgz#641150fc1cda36fbfa329de603bbb175d7ee20c0" integrity sha512-xZmuPTa3rlZoIbtDUyJKZQimJV3bxCmzMIO2c9Pz9afyDro6kr7R79GwcB6mRhuoPmV2p1Vb66WOJH7F886WKQ== +"@types/lokijs@^1.5.7": + version "1.5.7" + resolved "https://registry.yarnpkg.com/@types/lokijs/-/lokijs-1.5.7.tgz#5eb4b189149681a89acad6dc8adb088f6025feb3" + integrity sha512-WEFQLgO3u2Wa7yFybqkTZYumqF1GcHvUwx8Tv2SUHy2qpnIainMMoLmEUGdjhPNp/v5pyC9e91fSMC3mkxBIDw== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -7920,6 +7925,11 @@ loglevel@^1.6.8: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== +lokijs@^1.5.12: + version "1.5.12" + resolved "https://registry.yarnpkg.com/lokijs/-/lokijs-1.5.12.tgz#cb55b37009bdf09ee7952a6adddd555b893653a0" + integrity sha512-Q5ALD6JiS6xAUWCwX3taQmgwxyveCtIIuL08+ml0nHwT3k0S/GIFJN+Hd38b1qYIMaE5X++iqsqWVksz7SYW+Q== + longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"