diff --git a/src/main/config.tsx b/src/main/config.tsx index 08ebf7b8..1f48ee15 100644 --- a/src/main/config.tsx +++ b/src/main/config.tsx @@ -85,6 +85,14 @@ if (!fs.existsSync(filtersPath)) { fs.writeFileSync(filtersPath, JSON.stringify(defaultFilterData)); } +const notifiedTodoObjectsPath = path.join(userDataDirectory, 'notifiedTodoObjects.json'); +const notifiedTodoObjectsStorage = new Store<{}>({ cwd: userDataDirectory, name: 'notifiedTodoObjects' }); + +if (!fs.existsSync(notifiedTodoObjectsPath)) { + const defaultNotifiedTodoObjectsData = {}; + fs.writeFileSync(notifiedTodoObjectsPath, JSON.stringify(defaultNotifiedTodoObjectsData)); +} + if (!fs.existsSync(customStylesPath)) { fs.writeFileSync(customStylesPath, ''); } @@ -175,4 +183,4 @@ configStorage.onDidChange('tray', () => { nativeTheme.on('updated', handleTheme); -export { configStorage, filterStorage }; +export { configStorage, filterStorage, notifiedTodoObjectsStorage }; diff --git a/src/main/modules/HandleNotification.tsx b/src/main/modules/HandleNotification.tsx index 27b0cf4a..6c60bbd4 100644 --- a/src/main/modules/HandleNotification.tsx +++ b/src/main/modules/HandleNotification.tsx @@ -1,5 +1,6 @@ +import crypto from 'crypto'; import { Notification } from 'electron'; -import { configStorage } from '../config'; +import { configStorage, notifiedTodoObjectsStorage } from '../config'; import { Badge } from '../util'; import dayjs, { Dayjs } from "dayjs"; import isToday from 'dayjs/plugin/isToday'; @@ -7,8 +8,6 @@ import isTomorrow from 'dayjs/plugin/isTomorrow'; dayjs.extend(isToday); dayjs.extend(isTomorrow); -export const notifiedTodoObjects = new Set(); - export const sendNotification = (title: string, body: string) => { const options = { title, @@ -37,6 +36,7 @@ export function mustNotify(date: Date): boolean { export function handleNotification(id: number, due: string | null, body: string, badge: Badge) { const notificationAllowed = configStorage.get('notificationsAllowed'); + const hash = crypto.createHash('sha256').update(body).digest('hex'); if (notificationAllowed) { const today = dayjs().startOf('day'); @@ -47,9 +47,12 @@ export function handleNotification(id: number, due: string | null, body: string, if (dueDate.isBefore(today.add(notificationThreshold, 'day'))) { badge.count += 1; - if (!notifiedTodoObjects.has(id)) { + const notifiedTodoObjects = new Set(notifiedTodoObjectsStorage.get('notifiedTodoObjects', [])); + + if (!notifiedTodoObjects.has(hash)) { sendNotification(daysUntilDue, body); - notifiedTodoObjects.add(id); + notifiedTodoObjects.add(hash); + notifiedTodoObjectsStorage.set('notifiedTodoObjects', Array.from(notifiedTodoObjects)); } } } diff --git a/src/main/modules/Ipc.tsx b/src/main/modules/Ipc.tsx index ab0c82b8..a53ccf71 100644 --- a/src/main/modules/Ipc.tsx +++ b/src/main/modules/Ipc.tsx @@ -3,7 +3,7 @@ import processDataRequest from './ProcessDataRequest'; import { changeCompleteState } from './TodoObject/ChangeCompleteState'; import { writeTodoObjectToFile, removeLineFromFile } from './File/Write'; import archiveTodos from './File/Archive'; -import { configStorage, filterStorage } from '../config'; +import { configStorage, filterStorage, notifiedTodoObjectsStorage } from '../config'; import { addFile, setFile, removeFile, revealFile } from './File/File'; import { openFile, createFile, changeDoneFilePath } from './File/Dialog'; @@ -56,6 +56,15 @@ function handleStoreSetFilters(event: IpcMainEvent, value: any): void { } } +function handleStoreSetNotifiedTodoObjects(event: IpcMainEvent, value: any): void { + try { + notifiedTodoObjectsStorage.set('notifiedTodoObjects', value); + console.log(`ipcEvents.ts: notifiedTodoObjects saved`); + } catch (error: any) { + console.error('ipcEvents.ts:', error); + } +} + function handleSetFile(event: IpcMainEvent, index: number): void { try { setFile(index); @@ -134,6 +143,7 @@ function removeEventListeners(): void { ipcMain.off('storeGetConfig', handleStoreGetConfig); ipcMain.off('storeSetConfig', handleStoreSetConfig); ipcMain.off('storeSetFilters', handleStoreSetFilters); + ipcMain.off('storeSetNotifiedTodoObjects', handleStoreSetNotifiedTodoObjects); ipcMain.off('setFile', handleSetFile); ipcMain.off('removeFile', handleRemoveFile); ipcMain.off('openFile', openFile); @@ -154,6 +164,7 @@ app.on('before-quit', removeEventListeners); ipcMain.on('storeGetConfig', handleStoreGetConfig); ipcMain.on('storeSetConfig', handleStoreSetConfig); ipcMain.on('storeSetFilters', handleStoreSetFilters); +ipcMain.on('storeSetNotifiedTodoObjects', handleStoreSetNotifiedTodoObjects); ipcMain.on('setFile', handleSetFile); ipcMain.on('removeFile', handleRemoveFile); ipcMain.on('openFile', openFile); diff --git a/src/main/preload.js b/src/main/preload.js index d767fc02..e60e2f2c 100644 --- a/src/main/preload.js +++ b/src/main/preload.js @@ -11,6 +11,9 @@ contextBridge.exposeInMainWorld('api', { setFilters(value) { ipcRenderer.send('storeSetFilters', value); }, + notifiedTodoObjects(value) { + ipcRenderer.send('storeSetNotifiedTodoObjects', value); + }, }, ipcRenderer: { send(channel, ...args) {