update tracjer

This commit is contained in:
2026-01-21 23:29:52 +07:00
parent 9f79daf796
commit 765da3c37f
7 changed files with 64 additions and 37 deletions

4
desktop/.gitignore vendored
View File

@@ -14,6 +14,7 @@ npm-debug.log*
.vscode/
*.swp
*.swo
.claude/
# OS
.DS_Store
@@ -26,3 +27,6 @@ Thumbs.db
# Electron
*.asar
# Lock files (optional - remove if you want to commit)
package-lock.json

View File

@@ -1,6 +1,6 @@
{
"name": "game-marathon-tracker",
"version": "1.0.0",
"version": "1.0.1",
"description": "Desktop app for tracking game time in Game Marathon",
"main": "dist/main/main/index.js",
"author": "Game Marathon",
@@ -54,13 +54,20 @@
"output": "release"
},
"files": [
"dist/**/*",
"resources/**/*"
"dist/**/*"
],
"extraResources": [
{
"from": "resources",
"to": "resources"
}
],
"win": {
"target": [
"nsis",
"portable"
{
"target": "nsis",
"arch": ["x64"]
}
],
"icon": "resources/icon.ico",
"signAndEditExecutable": false
@@ -69,7 +76,9 @@
"oneClick": false,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true
"createStartMenuShortcut": true,
"runAfterFinish": false,
"artifactName": "Game-Marathon-Tracker-Setup-${version}.${ext}"
},
"publish": {
"provider": "github",

View File

@@ -34,12 +34,23 @@ const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged
// Prevent multiple instances
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
app.exit(0)
}
// Someone tried to run a second instance, focus our window
app.on('second-instance', () => {
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.show()
mainWindow.focus()
}
})
function createWindow() {
// __dirname is dist/main/main/ in both dev and prod
const iconPath = path.join(__dirname, '../../../resources/icon.ico')
// In dev: use project resources folder, in prod: use app resources
const iconPath = isDev
? path.join(__dirname, '../../../resources/icon.ico')
: path.join(process.resourcesPath, 'resources/icon.ico')
mainWindow = new BrowserWindow({
width: 450,
@@ -149,6 +160,11 @@ ipcMain.on('minimize-to-tray', () => {
mainWindow?.hide()
})
ipcMain.on('close-window', () => {
// This triggers the 'close' event handler which checks minimizeToTray setting
mainWindow?.close()
})
ipcMain.on('quit-app', () => {
app.isQuitting = true
app.quit()

View File

@@ -10,10 +10,10 @@ export function setupTray(
) {
const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged
// In dev: __dirname is dist/main/main/, in prod: same
// In dev: use project resources folder, in prod: use app resources
const iconPath = isDev
? path.join(__dirname, '../../../resources/icon.ico')
: path.join(__dirname, '../../../resources/icon.ico')
: path.join(process.resourcesPath, 'resources/icon.ico')
// Create tray icon
let trayIcon: NativeImage

View File

@@ -53,15 +53,20 @@ function sendProgressToSplash(percent: number) {
export function setupAutoUpdater(onComplete: () => void) {
const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged
let hasCompleted = false
const safeComplete = () => {
if (hasCompleted) return
hasCompleted = true
closeSplashWindow()
onComplete()
}
// In development, skip update check
if (isDev) {
console.log('[Updater] Skipping update check in development mode')
sendStatusToSplash('Режим разработки')
setTimeout(() => {
closeSplashWindow()
onComplete()
}, 1500)
setTimeout(safeComplete, 1500)
return
}
@@ -69,24 +74,21 @@ export function setupAutoUpdater(onComplete: () => void) {
autoUpdater.autoDownload = true
autoUpdater.autoInstallOnAppQuit = true
// Check for updates
autoUpdater.on('checking-for-update', () => {
// Check for updates (use 'once' to prevent handlers from triggering on manual update checks)
autoUpdater.once('checking-for-update', () => {
console.log('[Updater] Checking for updates...')
sendStatusToSplash('Проверка обновлений...')
})
autoUpdater.on('update-available', (info) => {
autoUpdater.once('update-available', (info) => {
console.log('[Updater] Update available:', info.version)
sendStatusToSplash(`Найдено обновление v${info.version}`)
})
autoUpdater.on('update-not-available', () => {
autoUpdater.once('update-not-available', () => {
console.log('[Updater] No updates available')
sendStatusToSplash('Актуальная версия')
setTimeout(() => {
closeSplashWindow()
onComplete()
}, 1000)
setTimeout(safeComplete, 1000)
})
autoUpdater.on('download-progress', (progress) => {
@@ -96,7 +98,7 @@ export function setupAutoUpdater(onComplete: () => void) {
sendProgressToSplash(percent)
})
autoUpdater.on('update-downloaded', (info) => {
autoUpdater.once('update-downloaded', (info) => {
console.log('[Updater] Update downloaded:', info.version)
sendStatusToSplash('Установка обновления...')
// Install and restart
@@ -105,23 +107,18 @@ export function setupAutoUpdater(onComplete: () => void) {
}, 1500)
})
autoUpdater.on('error', (error) => {
console.error('[Updater] Error:', error)
sendStatusToSplash('Ошибка проверки обновлений')
setTimeout(() => {
closeSplashWindow()
onComplete()
}, 2000)
autoUpdater.once('error', (error) => {
console.error('[Updater] Error:', error.message)
console.error('[Updater] Error stack:', error.stack)
sendStatusToSplash('Запуск...')
setTimeout(safeComplete, 1500)
})
// Start checking
autoUpdater.checkForUpdates().catch((error) => {
console.error('[Updater] Failed to check for updates:', error)
sendStatusToSplash('Не удалось проверить обновления')
setTimeout(() => {
closeSplashWindow()
onComplete()
}, 2000)
sendStatusToSplash('Запуск...')
setTimeout(safeComplete, 1500)
})
}

View File

@@ -52,6 +52,7 @@ const electronAPI = {
// Window controls
minimizeToTray: (): void => ipcRenderer.send('minimize-to-tray'),
closeWindow: (): void => ipcRenderer.send('close-window'),
quitApp: (): void => ipcRenderer.send('quit-app'),
// Monitoring control

View File

@@ -32,7 +32,7 @@ export function Layout({ children }: LayoutProps) {
<Minus className="w-4 h-4 text-gray-400" />
</button>
<button
onClick={() => window.electronAPI.quitApp()}
onClick={() => window.electronAPI.closeWindow()}
className="w-8 h-8 flex items-center justify-center hover:bg-red-600 transition-colors"
>
<X className="w-4 h-4 text-gray-400" />