@@ -2,6 +2,7 @@ const { app, BrowserWindow, Menu, shell, dialog, ipcMain, session } = require("e
22const path = require ( "path" ) ;
33const fs = require ( "fs" ) ;
44const crypto = require ( "crypto" ) ;
5+ const { autoUpdater } = require ( "electron-updater" ) ;
56
67let mainWindow ;
78const userDataPath = app . getPath ( "userData" ) ;
@@ -570,7 +571,7 @@ function createWindow() {
570571 ] } ,
571572 { label : "Help" , submenu : [
572573 { label : "About NoteForge" , click : ( ) => dialog . showMessageBox ( mainWindow , {
573- type : "info" , title : "About NoteForge" , message : "NoteForge v2.5.0 " ,
574+ type : "info" , title : "About NoteForge" , message : "NoteForge v2.5.1 " ,
574575 detail : "Encrypted offline note-taking.\nAES-256-GCM · scrypt (N=65536)\nDerived key session · Auto-lock\n\nData: " + userDataPath ,
575576 } ) } ,
576577 ] } ,
@@ -579,6 +580,65 @@ function createWindow() {
579580 Menu . setApplicationMenu ( Menu . buildFromTemplate ( menuTemplate ) ) ;
580581}
581582
582- app . whenReady ( ) . then ( createWindow ) ;
583+ app . whenReady ( ) . then ( ( ) => {
584+ createWindow ( ) ;
585+ setupAutoUpdater ( ) ;
586+ } ) ;
583587app . on ( "window-all-closed" , ( ) => { if ( process . platform !== "darwin" ) app . quit ( ) ; } ) ;
584588app . on ( "activate" , ( ) => { if ( ! mainWindow ) createWindow ( ) ; } ) ;
589+
590+ /* ═══════════════════════════════════════════════════════════════
591+ AUTO-UPDATER — checks GitHub Releases on startup
592+ Only network activity the app makes. Everything else stays offline.
593+ ═══════════════════════════════════════════════════════════════ */
594+ autoUpdater . autoDownload = false ;
595+ autoUpdater . autoInstallOnAppQuit = true ;
596+
597+ function setupAutoUpdater ( ) {
598+ if ( IS_DEV ) return ; // don't check for updates in dev mode
599+
600+ // Check for updates 5 seconds after launch (non-blocking)
601+ setTimeout ( ( ) => {
602+ autoUpdater . checkForUpdates ( ) . catch ( ( ) => { } ) ; // silently fail if offline
603+ } , 5000 ) ;
604+
605+ autoUpdater . on ( "update-available" , ( info ) => {
606+ if ( ! mainWindow ) return ;
607+ dialog . showMessageBox ( mainWindow , {
608+ type : "info" ,
609+ title : "Update Available" ,
610+ message : `NoteForge ${ info . version } is available.` ,
611+ detail : "Would you like to download it? The update will be installed when you close the app." ,
612+ buttons : [ "Download" , "Later" ] ,
613+ defaultId : 0 ,
614+ } ) . then ( result => {
615+ if ( result . response === 0 ) {
616+ autoUpdater . downloadUpdate ( ) ;
617+ mainWindow ?. webContents . send ( "menu-action" , "update-downloading" ) ;
618+ }
619+ } ) ;
620+ } ) ;
621+
622+ autoUpdater . on ( "update-downloaded" , ( ) => {
623+ if ( ! mainWindow ) return ;
624+ dialog . showMessageBox ( mainWindow , {
625+ type : "info" ,
626+ title : "Update Ready" ,
627+ message : "Update downloaded. It will be installed when you quit NoteForge." ,
628+ buttons : [ "Restart Now" , "Later" ] ,
629+ defaultId : 0 ,
630+ } ) . then ( result => {
631+ if ( result . response === 0 ) autoUpdater . quitAndInstall ( ) ;
632+ } ) ;
633+ } ) ;
634+
635+ autoUpdater . on ( "error" , ( ) => { } ) ; // silently ignore update errors (offline, etc.)
636+ }
637+
638+ ipcMain . handle ( "check-for-updates" , async ( ) => {
639+ if ( IS_DEV ) return { update : false } ;
640+ try {
641+ const result = await autoUpdater . checkForUpdates ( ) ;
642+ return { update : ! ! result ?. updateInfo , version : result ?. updateInfo ?. version } ;
643+ } catch { return { update : false } ; }
644+ } ) ;
0 commit comments