feat(desktop): packaging + self-hosted auto-update (electron-builder/updater)

- package.json build config: NSIS installer, app icon, generic publish provider →
  https://remote.bizgaze.com/downloads/ (self-hosted update feed).
- main.js: electron-updater checks the feed on launch + every 6h, downloads in the
  background, installs on restart. Active only in packaged builds.
- build/icon.ico app icon; PACKAGING.md documents build/release/signing.
- Key design: web/UI changes reach installed apps instantly (they load the live server);
  only native shell changes need an auto-updated build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 17:03:18 +05:30
parent 2404538270
commit 1500d42cd2
6 changed files with 183 additions and 11 deletions
+12
View File
@@ -10,6 +10,12 @@
// Server origin is configurable so the same build works against prod or a dev server.
const { app, BrowserWindow, session, desktopCapturer, shell, Menu, ipcMain, nativeImage } = require('electron');
const path = require('path');
// Auto-update: only NATIVE shell changes (this .exe) need this — all web/UI changes arrive
// live from the server. Checks the self-hosted feed (publish config in package.json →
// https://remote.bizgaze.com/downloads/latest.yml), downloads in the background, and installs
// on the next restart. No-op in dev (unpackaged).
let autoUpdater = null;
try { ({ autoUpdater } = require('electron-updater')); } catch (_) { /* not installed in dev */ }
// Renderer asks (via preload) to raise the window — e.g. when an OS notification is clicked.
ipcMain.on('focus-window', () => {
@@ -93,6 +99,12 @@ app.whenReady().then(() => {
createWindow();
Menu.setApplicationMenu(null); // hide the default menu bar; the web UI is the chrome
app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow(); });
// Check for shell updates on launch, then every 6 hours. Only in packaged builds.
if (app.isPackaged && autoUpdater) {
const check = () => autoUpdater.checkForUpdatesAndNotify().catch(() => {});
check();
setInterval(check, 6 * 60 * 60 * 1000);
}
});
app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit(); });