Merge pull request #2505 from h3poteto/iss-574
refs #574 Save marker in local db
This commit is contained in:
commit
76643b7eb9
|
@ -25,7 +25,7 @@ import path from 'path'
|
|||
import ContextMenu from 'electron-context-menu'
|
||||
import { initSplashScreen, Config } from '@trodi/electron-splashscreen'
|
||||
import openAboutWindow from 'about-window'
|
||||
import { Entity, detector, NotificationType } from 'megalodon'
|
||||
import generator, { Entity, detector, NotificationType } from 'megalodon'
|
||||
import sanitizeHtml from 'sanitize-html'
|
||||
import AutoLaunch from 'auto-launch'
|
||||
import minimist from 'minimist'
|
||||
|
@ -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
|
||||
|
@ -125,8 +127,8 @@ const accountDB = new Datastore({
|
|||
filename: accountDBPath,
|
||||
autoload: true
|
||||
})
|
||||
const accountManager = new Account(accountDB)
|
||||
accountManager.initialize().catch((err: Error) => log.error(err))
|
||||
const accountRepo = new Account(accountDB)
|
||||
accountRepo.initialize().catch((err: Error) => log.error(err))
|
||||
|
||||
const hashtagsDBPath = process.env.NODE_ENV === 'production' ? userData + '/db/hashtags.db' : 'hashtags.db'
|
||||
const hashtagsDB = new Datastore({
|
||||
|
@ -140,6 +142,13 @@ 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)
|
||||
|
||||
/**
|
||||
* Cache path
|
||||
*/
|
||||
|
@ -172,7 +181,7 @@ if (process.platform !== 'darwin') {
|
|||
|
||||
async function listAccounts(): Promise<Array<LocalAccount>> {
|
||||
try {
|
||||
const accounts = await accountManager.listAccounts()
|
||||
const accounts = await accountRepo.listAccounts()
|
||||
return accounts
|
||||
} catch (err) {
|
||||
return []
|
||||
|
@ -441,7 +450,7 @@ app.on('activate', () => {
|
|||
}
|
||||
})
|
||||
|
||||
const auth = new Authentication(accountManager)
|
||||
const auth = new Authentication(accountRepo)
|
||||
|
||||
type AuthRequest = {
|
||||
instance: string
|
||||
|
@ -497,23 +506,23 @@ ipcMain.handle('get-and-update-access-token', async (_: IpcMainInvokeEvent, requ
|
|||
|
||||
// nedb
|
||||
ipcMain.handle('list-accounts', async (_: IpcMainInvokeEvent) => {
|
||||
const accounts = await accountManager.listAccounts()
|
||||
const accounts = await accountRepo.listAccounts()
|
||||
return accounts
|
||||
})
|
||||
|
||||
ipcMain.handle('get-local-account', async (_: IpcMainInvokeEvent, id: string) => {
|
||||
const account = await accountManager.getAccount(id)
|
||||
const account = await accountRepo.getAccount(id)
|
||||
return account
|
||||
})
|
||||
|
||||
ipcMain.handle('update-account', async (_: IpcMainInvokeEvent, acct: LocalAccount) => {
|
||||
const proxy = await proxyConfiguration.forMastodon()
|
||||
const ac: LocalAccount = await accountManager.refresh(acct, proxy)
|
||||
const ac: LocalAccount = await accountRepo.refresh(acct, proxy)
|
||||
return ac
|
||||
})
|
||||
|
||||
ipcMain.handle('remove-account', async (_: IpcMainInvokeEvent, id: string) => {
|
||||
const accountId = await accountManager.removeAccount(id)
|
||||
const accountId = await accountRepo.removeAccount(id)
|
||||
|
||||
const accounts = await listAccounts()
|
||||
const accountsChange: Array<MenuItemConstructorOptions> = accounts.map((a, index) => {
|
||||
|
@ -534,22 +543,22 @@ ipcMain.handle('remove-account', async (_: IpcMainInvokeEvent, id: string) => {
|
|||
})
|
||||
|
||||
ipcMain.handle('forward-account', async (_: IpcMainInvokeEvent, acct: LocalAccount) => {
|
||||
await accountManager.forwardAccount(acct)
|
||||
await accountRepo.forwardAccount(acct)
|
||||
})
|
||||
|
||||
ipcMain.handle('backward-account', async (_: IpcMainInvokeEvent, acct: LocalAccount) => {
|
||||
await accountManager.backwardAccount(acct)
|
||||
await accountRepo.backwardAccount(acct)
|
||||
})
|
||||
|
||||
ipcMain.handle('refresh-accounts', async (_: IpcMainInvokeEvent) => {
|
||||
const proxy = await proxyConfiguration.forMastodon()
|
||||
const accounts = await accountManager.refreshAccounts(proxy)
|
||||
const accounts = await accountRepo.refreshAccounts(proxy)
|
||||
|
||||
return accounts
|
||||
})
|
||||
|
||||
ipcMain.handle('remove-all-accounts', async (_: IpcMainInvokeEvent) => {
|
||||
await accountManager.removeAll()
|
||||
await accountRepo.removeAll()
|
||||
|
||||
const accounts = await listAccounts()
|
||||
const accountsChange: Array<MenuItemConstructorOptions> = accounts.map((a, index) => {
|
||||
|
@ -605,7 +614,7 @@ ipcMain.on('start-all-user-streamings', (event: IpcMainEvent, accounts: Array<Lo
|
|||
accounts.map(async account => {
|
||||
const id: string = account._id!
|
||||
try {
|
||||
const acct = await accountManager.getAccount(id)
|
||||
const acct = await accountRepo.getAccount(id)
|
||||
// Stop old user streaming
|
||||
if (userStreamings[id]) {
|
||||
userStreamings[id]!.stop()
|
||||
|
@ -716,7 +725,7 @@ let directMessagesStreaming: DirectStreaming | null = null
|
|||
ipcMain.on('start-directmessages-streaming', async (event: IpcMainEvent, obj: StreamingSetting) => {
|
||||
const { account } = obj
|
||||
try {
|
||||
const acct = await accountManager.getAccount(account._id!)
|
||||
const acct = await accountRepo.getAccount(account._id!)
|
||||
|
||||
// Stop old directmessages streaming
|
||||
if (directMessagesStreaming !== null) {
|
||||
|
@ -765,7 +774,7 @@ let localStreaming: LocalStreaming | null = null
|
|||
ipcMain.on('start-local-streaming', async (event: IpcMainEvent, obj: StreamingSetting) => {
|
||||
const { account } = obj
|
||||
try {
|
||||
const acct = await accountManager.getAccount(account._id!)
|
||||
const acct = await accountRepo.getAccount(account._id!)
|
||||
|
||||
// Stop old local streaming
|
||||
if (localStreaming !== null) {
|
||||
|
@ -814,7 +823,7 @@ let publicStreaming: PublicStreaming | null = null
|
|||
ipcMain.on('start-public-streaming', async (event: IpcMainEvent, obj: StreamingSetting) => {
|
||||
const { account } = obj
|
||||
try {
|
||||
const acct = await accountManager.getAccount(account._id!)
|
||||
const acct = await accountRepo.getAccount(account._id!)
|
||||
|
||||
// Stop old public streaming
|
||||
if (publicStreaming !== null) {
|
||||
|
@ -867,7 +876,7 @@ type ListID = {
|
|||
ipcMain.on('start-list-streaming', async (event: IpcMainEvent, obj: ListID & StreamingSetting) => {
|
||||
const { listID, account } = obj
|
||||
try {
|
||||
const acct = await accountManager.getAccount(account._id!)
|
||||
const acct = await accountRepo.getAccount(account._id!)
|
||||
|
||||
// Stop old list streaming
|
||||
if (listStreaming !== null) {
|
||||
|
@ -921,7 +930,7 @@ type Tag = {
|
|||
ipcMain.on('start-tag-streaming', async (event: IpcMainEvent, obj: Tag & StreamingSetting) => {
|
||||
const { tag, account } = obj
|
||||
try {
|
||||
const acct = await accountManager.getAccount(account._id!)
|
||||
const acct = await accountRepo.getAccount(account._id!)
|
||||
|
||||
// Stop old tag streaming
|
||||
if (tagStreaming !== null) {
|
||||
|
@ -1137,6 +1146,51 @@ ipcMain.handle('update-spellchecker-languages', async (_: IpcMainInvokeEvent, la
|
|||
return conf.language.spellchecker.languages
|
||||
})
|
||||
|
||||
// marker
|
||||
ipcMain.handle('save-marker', async (_: IpcMainInvokeEvent, marker: LocalMarker) => {
|
||||
if (marker.owner_id === null || marker.owner_id === undefined || marker.owner_id === '') {
|
||||
return
|
||||
}
|
||||
await markerRepo.save(marker)
|
||||
})
|
||||
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
const accounts = await accountRepo.listAccounts()
|
||||
accounts.map(async acct => {
|
||||
const proxy = await proxyConfiguration.forMastodon()
|
||||
const sns = await detector(acct.baseURL, proxy)
|
||||
if (sns === 'misskey') {
|
||||
return
|
||||
}
|
||||
const client = generator(sns, acct.baseURL, acct.accessToken, 'Whalebird', proxy)
|
||||
const home = await markerRepo.get(acct._id!, 'home')
|
||||
const notifications = await markerRepo.get(acct._id!, 'notifications')
|
||||
let params = {}
|
||||
if (home !== null && home !== undefined) {
|
||||
params = Object.assign({}, params, {
|
||||
home: {
|
||||
last_read_id: home.last_read_id
|
||||
}
|
||||
})
|
||||
}
|
||||
if (notifications !== null && notifications !== undefined) {
|
||||
params = Object.assign({}, params, {
|
||||
notifications: {
|
||||
last_read_id: notifications.last_read_id
|
||||
}
|
||||
})
|
||||
}
|
||||
if (isEmpty(params)) {
|
||||
return
|
||||
}
|
||||
await client.saveMarkers(params)
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}, 120000)
|
||||
|
||||
// hashtag
|
||||
ipcMain.handle('save-hashtag', async (_: IpcMainInvokeEvent, tag: string) => {
|
||||
const hashtags = new Hashtags(hashtagsDB)
|
||||
|
|
|
@ -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<LocalMarker> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.db.insert(marker, (err, doc) => {
|
||||
if (err) return reject(err)
|
||||
resolve(doc)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private update(marker: LocalMarker): Promise<LocalMarker> {
|
||||
// @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)
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public async save(marker: LocalMarker): Promise<LocalMarker> {
|
||||
return this.get(marker.owner_id, marker.timeline).then(l => {
|
||||
if (isEmpty(l)) return this.insert(marker)
|
||||
return this.update(marker)
|
||||
})
|
||||
}
|
||||
|
||||
public async get(owner_id: string, timeline: 'home' | 'notifications'): Promise<LocalMarker | null> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.db.findOne<LocalMarker>({ owner_id: owner_id, timeline: timeline }, (err, doc) => {
|
||||
if (err) return reject(err)
|
||||
resolve(doc)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public async list(owner_id: string): Promise<Array<LocalMarker>> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.db
|
||||
.find<LocalMarker>({ owner_id: owner_id })
|
||||
.exec((err, docs) => {
|
||||
if (err) return reject(err)
|
||||
resolve(docs)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
|
@ -94,6 +94,10 @@ export default {
|
|||
this.focusedId = previousFocusedId
|
||||
})
|
||||
})
|
||||
|
||||
if (this.heading && this.timeline.length > 0) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Home/saveMarker', this.timeline[0].id)
|
||||
}
|
||||
},
|
||||
beforeUpdate() {
|
||||
if (this.$store.state.TimelineSpace.SideMenu.unreadHomeTimeline && this.heading) {
|
||||
|
@ -127,6 +131,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: {
|
||||
|
|
|
@ -47,10 +47,12 @@ export default {
|
|||
...mapState({
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar,
|
||||
startReload: state => state.TimelineSpace.HeaderMenu.reload,
|
||||
backgroundColor: state => state.App.theme.background_color,
|
||||
lazyLoading: state => state.TimelineSpace.Contents.Notifications.lazyLoading,
|
||||
heading: state => state.TimelineSpace.Contents.Notifications.heading,
|
||||
unread: state => state.TimelineSpace.Contents.Notifications.unreadNotifications
|
||||
backgroundColor: state => state.App.theme.background_color
|
||||
}),
|
||||
...mapState('TimelineSpace/Contents/Notifications', {
|
||||
lazyLoading: state => state.lazyLoading,
|
||||
heading: state => state.heading,
|
||||
unread: state => state.unreadNotifications
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Contents/Notifications', ['handledNotifications', 'filters']),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened']),
|
||||
|
@ -79,6 +81,10 @@ export default {
|
|||
this.focusedId = previousFocusedId
|
||||
})
|
||||
})
|
||||
|
||||
if (this.heading && this.handledNotifications.length > 0) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Notifications/saveMarker', this.handledNotifications[0].id)
|
||||
}
|
||||
},
|
||||
beforeUpdate() {
|
||||
if (this.$store.state.TimelineSpace.SideMenu.unreadNotifications) {
|
||||
|
@ -113,6 +119,11 @@ export default {
|
|||
this.$store.commit('TimelineSpace/Contents/Notifications/mergeNotifications')
|
||||
this.$store.dispatch('TimelineSpace/Contents/Notifications/resetBadge')
|
||||
}
|
||||
},
|
||||
handledNotifications: function (newState, _oldState) {
|
||||
if (this.heading && newState.length > 0) {
|
||||
this.$store.dispatch('TimelineSpace/Contents/Notifications/saveMarker', newState[0].id)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -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,13 @@ const actions: ActionTree<HomeState, RootState> = {
|
|||
.finally(() => {
|
||||
commit(MUTATION_TYPES.CHANGE_LAZY_LOADING, false)
|
||||
})
|
||||
},
|
||||
saveMarker: async ({ rootState }, id: string) => {
|
||||
await win.ipcRenderer.invoke('save-marker', {
|
||||
owner_id: rootState.TimelineSpace.account._id,
|
||||
timeline: 'home',
|
||||
last_read_id: id
|
||||
} as LocalMarker)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import generator, { Entity, FilterContext, NotificationType } 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
|
||||
|
@ -135,6 +136,13 @@ const actions: ActionTree<NotificationsState, RootState> = {
|
|||
},
|
||||
resetBadge: () => {
|
||||
win.ipcRenderer.send('reset-badge')
|
||||
},
|
||||
saveMarker: async ({ rootState }, id: string) => {
|
||||
await win.ipcRenderer.invoke('save-marker', {
|
||||
owner_id: rootState.TimelineSpace.account._id,
|
||||
timeline: 'notifications',
|
||||
last_read_id: id
|
||||
} as LocalMarker)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export type LocalMarker = {
|
||||
owner_id: string
|
||||
timeline: 'home' | 'notifications'
|
||||
last_read_id: string
|
||||
}
|
Loading…
Reference in New Issue