diff --git a/electron-builder.json5 b/electron-builder.json5 index 05ad4f3..fd9886a 100644 --- a/electron-builder.json5 +++ b/electron-builder.json5 @@ -33,5 +33,10 @@ "perMachine": false, "allowToChangeInstallationDirectory": true, "deleteAppDataOnUninstall": false + }, + publish:{ + provider: 'generic', + channel: 'latest', + url: 'https://github.com/electron-vite/electron-vite-react/releases/download/v0.9.9/', } } \ No newline at end of file diff --git a/electron/main/index.ts b/electron/main/index.ts index d99e0cf..a4540b7 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -1,6 +1,7 @@ import { app, BrowserWindow, shell, ipcMain } from 'electron' import { release } from 'node:os' import { join } from 'node:path' +import { update } from '../preload/update' // The built directory structure // @@ -72,6 +73,7 @@ async function createWindow() { if (url.startsWith('https:')) shell.openExternal(url) return { action: 'deny' } }) + update(win) } app.whenReady().then(createWindow) @@ -113,4 +115,5 @@ ipcMain.handle('open-win', (_, arg) => { } else { childWindow.loadFile(indexHtml, { hash: arg }) } -}) \ No newline at end of file +}) + diff --git a/electron/preload/update.ts b/electron/preload/update.ts new file mode 100644 index 0000000..76b0a05 --- /dev/null +++ b/electron/preload/update.ts @@ -0,0 +1,95 @@ +import { autoUpdater } from "electron-updater" +import { app, ipcMain } from "electron"; +export const update = (win: Electron.CrossProcessExports.BrowserWindow) => { + + // When set to false, the update download will be triggered through the API + autoUpdater.autoDownload = false; + + autoUpdater.disableWebInstaller = false + + autoUpdater.allowDowngrade = false; + + // Save the version status of whether the update needs to be installed, + // Because the user needs to update immediately and later after the update is downloaded + let NEED_INSTALL = false; + + // Check whether update is used + ipcMain.on('check-update',()=>{ + autoUpdater.checkForUpdatesAndNotify() + .then((res) => { + win.webContents.send('check-update-type',{ checkUpdate: true}) + }).catch(err => { + // network error + win.webContents.send('check-update-type', { checkUpdate: false}) + }); + }) + + // start check + autoUpdater.on('checking-for-update', function () { + console.log('checking-for-update') + }) + // update available + autoUpdater.on('update-available', (arg) => { + console.log('update-available') + win.webContents.send('is-update-available', { isUpdate: true, oldVersion: app.getVersion(), newVersion: arg?.version }) + }) + // update not available + autoUpdater.on('update-not-available', (arg) => { + console.log('update-not-available') + win.webContents.send('is-update-available', { isUpdate: false, oldVersion: app.getVersion(), newVersion: arg?.version }) + }) + + const startDownload = (callback: any, successCallback: any) => { + // Monitor the download progress and push it to the update window + autoUpdater.on('download-progress', (data) => { + console.log("progress", data) + win.webContents.send('download-progress-data', data) + callback && callback instanceof Function && callback(null, data); + }); + // Listen for download errors and push to the update window + autoUpdater.on('error', (err) => { + callback && callback instanceof Function && callback(err); + }); + // Listen to the download completion and push it to the update window + autoUpdater.on('update-downloaded', () => { + NEED_INSTALL = true; + successCallback && successCallback instanceof Function && successCallback(); + }); + + autoUpdater.downloadUpdate(); + }; + + // Listen to the process message sent by the application layer and start downloading updates + ipcMain.on('start-download', (event) => { + console.log("start") + startDownload( + (err: any, progressInfo: { percent: any; }) => { + if (err) { + // callback download error message + event.sender.send('update-error', { updateError:true}); + } else { + // callback update progress message + event.sender.send('update-progress', { progressInfo: progressInfo.percent }); + } + }, + () => { + // callback update downed message + event.sender.send('update-downed'); + } + ); + }); + + // install now + ipcMain.on('quit-and-install', () => { + autoUpdater.quitAndInstall(false, true); + }) + + // install later + app.on('will-quit', () => { + console.log("NEED_INSTALL=true") + if (NEED_INSTALL) { + autoUpdater.quitAndInstall(true, false); + } + }); + +} \ No newline at end of file diff --git a/package.json b/package.json index 08962a4..a373bcc 100644 --- a/package.json +++ b/package.json @@ -36,5 +36,8 @@ }, "engines": { "node": "^14.18.0 || >=16.0.0" + }, + "dependencies": { + "electron-updater": "^5.3.0" } } diff --git a/src/App.tsx b/src/App.tsx index a5cb431..c4c091d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,21 +1,22 @@ -import nodeLogo from "./assets/node.svg" +import nodeLogo from './assets/node.svg' import { useState } from 'react' import './App.scss' +import Update from '@/components/update' console.log('[App.tsx]', `Hello world from Electron ${process.versions.electron}!`) + function App() { const [count, setCount] = useState(0) - return ( -
src/App.tsx
and save to test HMR
+
Click on the Electron + Vite logo to learn more
-/public
folder /public
folder