From ba1574116fc6df795c902ad35629ab2de61e3ca1 Mon Sep 17 00:00:00 2001 From: AkiraFukushima Date: Thu, 10 Jun 2021 12:03:51 +0900 Subject: [PATCH] refs #574 Save marker in local db every time receive a new status in home --- src/main/index.ts | 14 ++++ src/main/marker.ts | 67 +++++++++++++++++++ .../TimelineSpace/Contents/Home.vue | 5 ++ .../store/TimelineSpace/Contents/Home.ts | 12 ++++ src/types/localMarker.ts | 5 ++ 5 files changed, 103 insertions(+) create mode 100644 src/main/marker.ts create mode 100644 src/types/localMarker.ts diff --git a/src/main/index.ts b/src/main/index.ts index 8aa58d3c..a7f8e86d 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -54,6 +54,8 @@ import ProxyConfiguration from './proxy' import confirm from './timelines' import { EnabledTimelines } from '~/src/types/enabledTimelines' import { Menu as MenuPreferences } from '~/src/types/preference' +import { LocalMarker } from '~/src/types/localMarker' +import Marker from './marker' /** * Context menu @@ -140,6 +142,12 @@ 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 +}) + /** * Cache path */ @@ -1137,6 +1145,12 @@ ipcMain.handle('update-spellchecker-languages', async (_: IpcMainInvokeEvent, la return conf.language.spellchecker.languages }) +// marker +ipcMain.handle('save-marker', async (_: IpcMainInvokeEvent, marker: LocalMarker) => { + const repo = new Marker(markerDB) + await repo.save(marker) +}) + // hashtag ipcMain.handle('save-hashtag', async (_: IpcMainInvokeEvent, tag: string) => { const hashtags = new Hashtags(hashtagsDB) diff --git a/src/main/marker.ts b/src/main/marker.ts new file mode 100644 index 00000000..a000a484 --- /dev/null +++ b/src/main/marker.ts @@ -0,0 +1,67 @@ +import { isEmpty } from 'lodash' +import Datastore from 'nedb' +import { LocalMarker } from '~/src/types/localMarker' + +export default class Marker { + private db: Datastore + + constructor(db: Datastore) { + this.db = db + this.db.persistence.setAutocompactionInterval(60000) // milliseconds + } + + private insert(marker: LocalMarker): Promise { + return new Promise((resolve, reject) => { + this.db.insert(marker, (err, doc) => { + if (err) return reject(err) + resolve(doc) + }) + }) + } + + private update(marker: LocalMarker): Promise { + // @ts-ignore + return new Promise((resolve, reject) => { + // eslint-disable-line no-unused-vars + this.db.update( + { + acct: marker.acct, + timeline: marker.timeline + }, + { $set: marker }, + { multi: false }, + err => { + if (err) return reject(err) + return this.get(marker.acct, marker.timeline) + } + ) + }) + } + + public async save(marker: LocalMarker): Promise { + return this.get(marker.acct, marker.timeline).then(l => { + if (isEmpty(l)) return this.insert(marker) + return this.update(marker) + }) + } + + public async get(acct: string, timeline: 'home' | 'notifications'): Promise { + return new Promise((resolve, reject) => { + this.db.findOne({ acct: acct, timeline: timeline }, (err, doc) => { + if (err) return reject(err) + resolve(doc) + }) + }) + } + + public async list(acct: string): Promise> { + return new Promise((resolve, reject) => { + this.db + .find({ acct: acct }) + .exec((err, docs) => { + if (err) return reject(err) + resolve(docs) + }) + }) + } +} diff --git a/src/renderer/components/TimelineSpace/Contents/Home.vue b/src/renderer/components/TimelineSpace/Contents/Home.vue index 413ac1e7..b463bad1 100644 --- a/src/renderer/components/TimelineSpace/Contents/Home.vue +++ b/src/renderer/components/TimelineSpace/Contents/Home.vue @@ -127,6 +127,11 @@ export default { this.$store.commit('TimelineSpace/Contents/Home/changeHeading', true) this.$store.commit('TimelineSpace/Contents/Home/mergeTimeline') } + }, + timeline: function (newState, _oldState) { + if (this.heading && newState.length > 0) { + this.$store.dispatch('TimelineSpace/Contents/Home/saveMarker', newState[0].id) + } } }, methods: { diff --git a/src/renderer/store/TimelineSpace/Contents/Home.ts b/src/renderer/store/TimelineSpace/Contents/Home.ts index feadab7f..56659587 100644 --- a/src/renderer/store/TimelineSpace/Contents/Home.ts +++ b/src/renderer/store/TimelineSpace/Contents/Home.ts @@ -1,6 +1,10 @@ import generator, { Entity, FilterContext } from 'megalodon' import { Module, MutationTree, ActionTree, GetterTree } from 'vuex' import { RootState } from '@/store' +import { LocalMarker } from '~/src/types/localMarker' +import { MyWindow } from '~/src/types/global' + +const win = (window as any) as MyWindow export type HomeState = { lazyLoading: boolean @@ -135,6 +139,14 @@ const actions: ActionTree = { .finally(() => { commit(MUTATION_TYPES.CHANGE_LAZY_LOADING, false) }) + }, + saveMarker: async ({ rootState }, id: string) => { + const acct = `@${rootState.TimelineSpace.account.username}@${rootState.TimelineSpace.account.domain}` + await win.ipcRenderer.invoke('save-marker', { + acct: acct, + timeline: 'home', + lastReadID: id + } as LocalMarker) } } diff --git a/src/types/localMarker.ts b/src/types/localMarker.ts new file mode 100644 index 00000000..95712762 --- /dev/null +++ b/src/types/localMarker.ts @@ -0,0 +1,5 @@ +export type LocalMarker = { + acct: string + timeline: 'home' | 'notifications' + lastReadID: string +}