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
+}