Initial commit
This commit is contained in:
88
src/main/scheduler.ts
Normal file
88
src/main/scheduler.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { powerMonitor, BrowserWindow } from 'electron'
|
||||
import { IPC } from '@shared/ipc'
|
||||
import type { Tick } from '@shared/types'
|
||||
import { getExercises, getSettings, updateExercise } from './store'
|
||||
import { fireReminder } from './notifications'
|
||||
|
||||
const TICK_MS = 1000
|
||||
const CHECK_MS = 5000
|
||||
let tickHandle: NodeJS.Timeout | null = null
|
||||
let lastCheckAt = 0
|
||||
let paused = false
|
||||
|
||||
function checkDueExercises(): void {
|
||||
if (paused) return
|
||||
const settings = getSettings()
|
||||
if (!settings.globalEnabled) return
|
||||
|
||||
const now = Date.now()
|
||||
const exercises = getExercises()
|
||||
for (const ex of exercises) {
|
||||
if (!ex.enabled) continue
|
||||
if (ex.nextFireAt <= now) {
|
||||
// Fire once, reschedule from now (drop missed intervals).
|
||||
const updated = updateExercise(ex.id, {
|
||||
nextFireAt: now + ex.intervalMinutes * 60_000
|
||||
})
|
||||
if (updated) fireReminder(updated, settings.notificationMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function broadcastTicks(): void {
|
||||
const now = Date.now()
|
||||
const ticks: Tick[] = getExercises().map((e) => ({
|
||||
exerciseId: e.id,
|
||||
msUntilFire: Math.max(0, e.nextFireAt - now),
|
||||
enabled: e.enabled
|
||||
}))
|
||||
for (const win of BrowserWindow.getAllWindows()) {
|
||||
if (!win.isDestroyed()) win.webContents.send(IPC.evtTick, ticks)
|
||||
}
|
||||
}
|
||||
|
||||
function tick(): void {
|
||||
broadcastTicks()
|
||||
const now = Date.now()
|
||||
if (now - lastCheckAt >= CHECK_MS) {
|
||||
lastCheckAt = now
|
||||
checkDueExercises()
|
||||
}
|
||||
}
|
||||
|
||||
export function startScheduler(): void {
|
||||
if (tickHandle) return
|
||||
lastCheckAt = 0
|
||||
tickHandle = setInterval(tick, TICK_MS)
|
||||
// Run an immediate tick so renderer hydrates quickly.
|
||||
tick()
|
||||
|
||||
powerMonitor.on('resume', () => {
|
||||
lastCheckAt = 0
|
||||
tick()
|
||||
})
|
||||
powerMonitor.on('unlock-screen', () => {
|
||||
lastCheckAt = 0
|
||||
tick()
|
||||
})
|
||||
}
|
||||
|
||||
export function stopScheduler(): void {
|
||||
if (tickHandle) {
|
||||
clearInterval(tickHandle)
|
||||
tickHandle = null
|
||||
}
|
||||
}
|
||||
|
||||
export function setPaused(value: boolean): void {
|
||||
paused = value
|
||||
}
|
||||
|
||||
export function isPaused(): boolean {
|
||||
return paused
|
||||
}
|
||||
|
||||
export function forceCheck(): void {
|
||||
lastCheckAt = 0
|
||||
tick()
|
||||
}
|
||||
Reference in New Issue
Block a user