Initial commit

This commit is contained in:
AnRil
2026-05-16 13:43:29 +07:00
commit 688a86b611
208 changed files with 44350 additions and 0 deletions

83
src/main/index.ts Normal file
View File

@@ -0,0 +1,83 @@
import { app, BrowserWindow, nativeTheme, systemPreferences } from 'electron'
import { createMainWindow, createReminderWindow, showMainWindow } from './windows'
import { registerIpc } from './ipc'
import { startScheduler, stopScheduler } from './scheduler'
import { createTray } from './tray'
import { flushNow, getState } from './store'
import { wasStartedHidden } from './autostart'
import { broadcastState } from './state-actions'
import { startGamesRegistry, stopGamesRegistry } from './games/registry'
import { IPC } from '@shared/ipc'
const APP_ID = 'com.anril.exercise-reminder'
// Must be set BEFORE app.whenReady() for Windows toasts to show
// the correct app name / icon in Action Center.
app.setAppUserModelId(APP_ID)
app.setName('Exercise Reminder')
const gotLock = app.requestSingleInstanceLock()
if (!gotLock) {
app.quit()
} else {
app.on('second-instance', () => showMainWindow())
app.whenReady().then(() => {
registerIpc()
createTray()
const hidden =
wasStartedHidden() || getState().settings.startMinimized
createMainWindow(!hidden)
// Pre-create the reminder window so first-trigger is instant (no load lag).
createReminderWindow()
startScheduler()
startGamesRegistry().catch((err) =>
console.error('games registry failed:', err)
)
nativeTheme.on('updated', () => {
const theme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light'
for (const win of BrowserWindow.getAllWindows()) {
if (!win.isDestroyed()) win.webContents.send(IPC.evtThemeChanged, theme)
}
})
try {
systemPreferences.on('accent-color-changed' as never, () => {
try {
const color = '#' + systemPreferences.getAccentColor()
for (const win of BrowserWindow.getAllWindows()) {
if (!win.isDestroyed()) win.webContents.send(IPC.evtAccentChanged, color)
}
} catch {
// ignore
}
})
} catch {
// older Electron / non-Windows
}
})
app.on('window-all-closed', () => {
// Keep running in tray instead of quitting when all windows closed.
if (!getState().settings.minimizeToTray) {
app.quit()
}
})
app.on('before-quit', () => {
stopScheduler()
void stopGamesRegistry()
flushNow()
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createMainWindow(true)
else showMainWindow()
})
// Broadcast state once on ready so any prebuilt windows hydrate.
app.whenReady().then(() => broadcastState())
}