|
1 | | -const { app, BrowserWindow, ipcMain, dialog } = require('electron'); |
| 1 | +const { app, BrowserWindow, ipcMain, dialog, shell, globalShortcut } = require('electron'); |
2 | 2 | const path = require('path'); |
3 | 3 | const fs = require('fs'); |
| 4 | +const https = require('https'); |
| 5 | +const { autoUpdater } = require('electron-updater'); |
| 6 | + |
| 7 | +// App version, normalized to strip the `--<electron-version>` suffix (e.g. 3.2.10--1.0.8 -> 3.2.10) |
| 8 | +const APP_VERSION = require('../package.json').version.replace(/--.*$/, ''); |
4 | 9 |
|
5 | 10 | let mainWindow; |
6 | 11 | let serverInstance; |
@@ -36,11 +41,97 @@ function createWindow() { |
36 | 41 | mainWindow.on('closed', () => { |
37 | 42 | mainWindow = null; |
38 | 43 | }); |
| 44 | + |
| 45 | + globalShortcut.register('F12', () => { |
| 46 | + if (mainWindow) mainWindow.webContents.toggleDevTools(); |
| 47 | + }); |
39 | 48 | } |
40 | 49 |
|
41 | 50 | app.whenReady().then(() => { |
42 | 51 | createWindow(); |
43 | 52 |
|
| 53 | + // Register IPC handler for opening external URLs |
| 54 | + ipcMain.handle('shell:openExternal', async (event, url) => { |
| 55 | + await shell.openExternal(url); |
| 56 | + }); |
| 57 | + |
| 58 | + // Auto-updater setup (AppImage, NSIS, DMG only — others fall back to releases page) |
| 59 | + autoUpdater.autoDownload = false; |
| 60 | + autoUpdater.autoInstallOnAppQuit = false; |
| 61 | + autoUpdater.channel = 'latest'; |
| 62 | + autoUpdater.allowPrerelease = false; |
| 63 | + |
| 64 | + const updatableFormats = ['appimage', 'nsis', 'dmg']; |
| 65 | + |
| 66 | + function getInstallerType() { |
| 67 | + if (process.platform === 'linux') return process.env.APPIMAGE ? 'appimage' : 'other'; |
| 68 | + if (process.platform === 'win32') return fs.existsSync(path.join(process.resourcesPath, '..', 'Uninstall LiaScript-Exporter.exe')) ? 'nsis' : 'other'; |
| 69 | + if (process.platform === 'darwin') return 'dmg'; |
| 70 | + return 'other'; |
| 71 | + } |
| 72 | + |
| 73 | + autoUpdater.on('update-available', (info) => { |
| 74 | + if (mainWindow) mainWindow.webContents.send('update:available', { version: info.version }); |
| 75 | + }); |
| 76 | + |
| 77 | + autoUpdater.on('download-progress', (progress) => { |
| 78 | + if (mainWindow) mainWindow.webContents.send('update:progress', { percent: Math.round(progress.percent) }); |
| 79 | + }); |
| 80 | + |
| 81 | + autoUpdater.on('update-downloaded', () => { |
| 82 | + if (mainWindow) mainWindow.webContents.send('update:downloaded'); |
| 83 | + }); |
| 84 | + |
| 85 | + autoUpdater.on('error', () => { |
| 86 | + if (mainWindow) mainWindow.webContents.send('update:error'); |
| 87 | + }); |
| 88 | + |
| 89 | + ipcMain.handle('app:checkForUpdates', async () => { |
| 90 | + if (!updatableFormats.includes(getInstallerType())) { |
| 91 | + // Fallback: check GitHub API and return release URL for unsupported formats |
| 92 | + return new Promise((resolve) => { |
| 93 | + https.get({ |
| 94 | + hostname: 'api.github.com', |
| 95 | + path: '/repos/LiaScript/LiaScript-Exporter/releases/latest', |
| 96 | + headers: { 'User-Agent': 'LiaScript-Exporter' } |
| 97 | + }, (res) => { |
| 98 | + let data = ''; |
| 99 | + res.on('data', (chunk) => { data += chunk; }); |
| 100 | + res.on('end', () => { |
| 101 | + try { |
| 102 | + const release = JSON.parse(data); |
| 103 | + const latestVersion = release.tag_name.replace(/^v/, ''); |
| 104 | + resolve({ |
| 105 | + supported: false, |
| 106 | + hasUpdate: latestVersion !== APP_VERSION, |
| 107 | + releaseUrl: release.html_url |
| 108 | + }); |
| 109 | + } catch { |
| 110 | + resolve({ supported: false, hasUpdate: false }); |
| 111 | + } |
| 112 | + }); |
| 113 | + }).on('error', () => resolve({ supported: false, hasUpdate: false })); |
| 114 | + }); |
| 115 | + } |
| 116 | + try { |
| 117 | + const result = await autoUpdater.checkForUpdates(); |
| 118 | + const latestVersion = result?.updateInfo?.version; |
| 119 | + const hasUpdate = !!latestVersion && latestVersion !== APP_VERSION; |
| 120 | + return { supported: true, hasUpdate, version: latestVersion }; |
| 121 | + } catch (e) { |
| 122 | + console.error('[update-check] autoUpdater error:', e.message); |
| 123 | + return { supported: false, hasUpdate: false }; |
| 124 | + } |
| 125 | + }); |
| 126 | + |
| 127 | + ipcMain.handle('app:downloadUpdate', async () => { |
| 128 | + await autoUpdater.downloadUpdate(); |
| 129 | + }); |
| 130 | + |
| 131 | + ipcMain.handle('app:installUpdate', () => { |
| 132 | + autoUpdater.quitAndInstall(); |
| 133 | + }); |
| 134 | + |
44 | 135 | // Register IPC handler for file dialog |
45 | 136 | ipcMain.handle('dialog:openFile', async () => { |
46 | 137 | const result = await dialog.showOpenDialog(mainWindow, { |
|
0 commit comments