update tracjer
This commit is contained in:
4
desktop/.gitignore
vendored
4
desktop/.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user