From 0dad0c080e22beb0eb618a2e452644d82cd8f9f2 Mon Sep 17 00:00:00 2001 From: Anton Reshetov Date: Sat, 13 Apr 2024 17:29:35 +0300 Subject: [PATCH] fix: use main process timer (#21) --- src/main.ts | 64 ++++++++++--------- src/preload.ts | 19 ++++-- src/renderer/components/tasks/Tasks.vue | 4 +- .../components/tasks/composables/index.ts | 35 ++++------ src/timer.ts | 29 +++++++++ src/types/index.ts | 12 +++- 6 files changed, 103 insertions(+), 60 deletions(-) create mode 100644 src/timer.ts diff --git a/src/main.ts b/src/main.ts index 8f8bb7d..418c8a2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,15 +14,12 @@ import { store } from './services/store' import { timeFormat } from './renderer/utils' import { menu } from './menu' import { checkForUpdates } from './services/updates' +import { getTime, isTimerActive, startTimer, stopTimer } from './timer' const isDev = process.env.NODE_ENV === 'development' let mainWindow: BrowserWindow let tray: Tray -let timer: NodeJS.Timeout -let sec = 0 - -let isTimerActive = false let isQuitting = false // Handle creating/removing shortcuts on Windows when installing/uninstalling. @@ -77,11 +74,11 @@ function createWindow() { function createTrayMenu() { return Menu.buildFromTemplate([ { - label: isTimerActive ? 'Stop' : 'Start', + label: isTimerActive() ? 'Stop' : 'Start', click: () => - isTimerActive - ? mainWindow.webContents.send('stop') - : mainWindow.webContents.send('start'), + isTimerActive() + ? mainWindow.webContents.send('tray-stop-timer') + : mainWindow.webContents.send('tray-start-timer'), }, { type: 'separator', @@ -126,36 +123,43 @@ app.on('activate', () => { }) if (process.platform === 'darwin') { - ipcMain.on('tray-start-timer', () => { - isTimerActive = true - - tray.setContextMenu(createTrayMenu()) - - timer = setInterval(() => { - sec++ + app.setAboutPanelOptions({ + applicationName: app.name, + applicationVersion: app.getVersion(), + copyright: `${author.name} ©2024-${new Date().getFullYear()}`, + }) +} - tray.setTitle(timeFormat(sec), { +ipcMain.on('start-timer', () => { + if (process.platform === 'darwin') { + startTimer(() => { + tray.setTitle(timeFormat(getTime()), { fontType: 'monospacedDigit', }) - }, 1000) - }) - ipcMain.on('tray-stop-timer', () => { - clearInterval(timer) + mainWindow.webContents.send('timer-update', getTime()) + }) - sec = 0 - isTimerActive = false + tray.setContextMenu(createTrayMenu()) + } + else { + startTimer() + } + mainWindow.webContents.send('start-timer') +}) + +ipcMain.on('stop-timer', () => { + if (process.platform === 'darwin') { + stopTimer() tray.setTitle('00:00:00') tray.setContextMenu(createTrayMenu()) - }) - - app.setAboutPanelOptions({ - applicationName: app.name, - applicationVersion: app.getVersion(), - copyright: `${author.name} ©2024-${new Date().getFullYear()}`, - }) -} + } + else { + stopTimer() + } + mainWindow.webContents.send('stop-timer') +}) ipcMain.on('check-for-updates', () => { checkForUpdates() diff --git a/src/preload.ts b/src/preload.ts index 2d4282d..bdd3d07 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -5,6 +5,7 @@ import { repository } from '../package.json' import { api } from './services/api' import { store } from './services/store' import type { AppStore } from './services/store/types' +import { getTime, isTimerActive } from './timer' contextBridge.exposeInMainWorld('electron', { api, @@ -17,11 +18,21 @@ contextBridge.exposeInMainWorld('electron', { }, }, tray: { - startTimer: () => ipcRenderer.send('tray-start-timer'), - stopTimer: () => ipcRenderer.send('tray-stop-timer'), setTime: (time: number) => ipcRenderer.send('tray-set-time', time), - onStart: (callback: () => void) => ipcRenderer.on('start', callback), - onStop: (callback: () => void) => ipcRenderer.on('stop', callback), + onStart: (callback: () => void) => + ipcRenderer.on('tray-start-timer', callback), + onStop: (callback: () => void) => + ipcRenderer.on('tray-stop-timer', callback), + }, + timer: { + getTime: () => getTime(), + isTimerActive: () => isTimerActive(), + onStart: (callback: () => void) => ipcRenderer.on('start-timer', callback), + onStop: (callback: () => void) => ipcRenderer.on('stop-timer', callback), + onUpdate: (callback: (time: number) => void) => + ipcRenderer.on('timer-update', (_, time) => callback(time)), + startTimer: () => ipcRenderer.send('start-timer'), + stopTimer: () => ipcRenderer.send('stop-timer'), }, updates: { checkForUpdates: () => ipcRenderer.send('check-for-updates'), diff --git a/src/renderer/components/tasks/Tasks.vue b/src/renderer/components/tasks/Tasks.vue index 51a1852..1e2e0c9 100644 --- a/src/renderer/components/tasks/Tasks.vue +++ b/src/renderer/components/tasks/Tasks.vue @@ -11,7 +11,7 @@ import { APP_DEFAULTS } from '~/services/store/constants' import * as ContextMenu from '@/components/ui/shadcn/context-menu' import * as Dialog from '@/components/ui/shadcn/dialog' -const { store, tray } = window.electron +const { store, timer } = window.electron const { getTasks, @@ -83,7 +83,7 @@ function onAddTask() { function onDelete() { if (editTaskId.value === currentTaskId.value) { stop() - tray.stopTimer() + timer.stopTimer() } isConfirmOpen.value = false diff --git a/src/renderer/components/tasks/composables/index.ts b/src/renderer/components/tasks/composables/index.ts index f52b392..3d77182 100644 --- a/src/renderer/components/tasks/composables/index.ts +++ b/src/renderer/components/tasks/composables/index.ts @@ -3,12 +3,11 @@ import type { TaskWithRecords } from '~/services/api/types' import { timeFormat } from '@/utils' import { useFolders } from '@/components/folders/composables' -const { api, store, tray } = window.electron +const { api, store, timer } = window.electron const { selectedFolderId } = useFolders() -let timer: NodeJS.Timeout -let timerToUpdate: NodeJS.Timeout +const INTERVAL_TO_UPDATE = 300 // 5 минут const tasks = shallowRef([]) @@ -52,30 +51,14 @@ function start(id: string) { if (currentTaskItemId.value) stop() - timer = setInterval(() => { - sec.value++ - }, 1000) - currentTaskId.value = id currentTaskItemId.value = api.addTaskRecord({ taskId: id }) lastTaskId.value = id - timerToUpdate = setInterval( - () => { - api.updateTaskRecordDuration(currentTaskItemId.value, sec.value) - // eslint-disable-next-line no-console - console.log('[Update]', currentTask.value.name, sec.value) - }, - 1000 * 60 * 5, - ) - isStarted.value = true } function stop() { - clearInterval(timer) - clearInterval(timerToUpdate) - api.updateTaskRecordDuration(currentTaskItemId.value, sec.value) // eslint-disable-next-line no-console console.log('[Stop]', currentTask.value.name, sec.value) @@ -94,11 +77,11 @@ function startStop(id: string) { if (!isStarted.value) { start(id) - tray.startTimer() + timer.startTimer() } else { stop() - tray.stopTimer() + timer.stopTimer() } } @@ -125,6 +108,16 @@ watch(lastTaskId, (id) => { store.app.set('lastTaskId', id) }) +timer.onUpdate((i) => { + sec.value = i + + if (i % INTERVAL_TO_UPDATE === 0) { + api.updateTaskRecordDuration(currentTaskItemId.value, sec.value) + // eslint-disable-next-line no-console + console.log('[Update]', currentTask.value.name, sec.value) + } +}) + export function useTasks() { return { addTask, diff --git a/src/timer.ts b/src/timer.ts new file mode 100644 index 0000000..89a70e5 --- /dev/null +++ b/src/timer.ts @@ -0,0 +1,29 @@ +let timer: NodeJS.Timeout + +let sec = 0 +let active = false + +function startTimer(callback?: () => void) { + active = true + + timer = setInterval(() => { + sec++ + callback?.() + }, 1000) +} + +function stopTimer() { + clearInterval(timer) + sec = 0 + active = false +} + +function getTime() { + return sec +} + +function isTimerActive() { + return active +} + +export { getTime, isTimerActive, startTimer, stopTimer } diff --git a/src/types/index.ts b/src/types/index.ts index c100f98..28c87f0 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -7,12 +7,18 @@ declare global { api: Api store: Store tray: { - startTimer: () => void - stopTimer: () => void - setTime: (time: number) => void onStart: (callback: () => void) => void onStop: (callback: () => void) => void } + timer: { + getTime: () => number + isTimerActive: () => boolean + onStart: (callback: () => void) => void + onStop: (callback: () => void) => void + onUpdate: (callback: (time: number) => void) => void + startTimer: () => void + stopTimer: () => void + } updates: { checkForUpdates: () => void downloadUpdate: () => void