1- import { BrowserWindow , dialog } from 'electron' ;
1+ import { UpdateStatus } from '@jetstream/desktop/types' ;
2+ import { BrowserWindow } from 'electron' ;
23import logger from 'electron-log' ;
34import { autoUpdater , UpdateInfo } from 'electron-updater' ;
45
56// Configure logging
67autoUpdater . logger = logger ;
78
8- // Disable auto-download - we'll control when to download
9- autoUpdater . autoDownload = false ;
9+ // Enable auto-download - non-blocking background download
10+ autoUpdater . autoDownload = true ;
1011autoUpdater . autoInstallOnAppQuit = true ;
1112
12- function getFocusedOrFirstWindow ( ) : BrowserWindow | null {
13- return BrowserWindow . getFocusedWindow ( ) || BrowserWindow . getAllWindows ( ) [ 0 ] || null ;
13+ // State management
14+ let currentUpdateStatus : UpdateStatus = { status : 'idle' } ;
15+ let lastCheckTime = 0 ;
16+ const MIN_CHECK_INTERVAL = 5 * 60 * 1000 ; // 5 minutes between checks to prevent spam
17+
18+ function sendUpdateStatus ( status : UpdateStatus ) {
19+ currentUpdateStatus = status ;
20+ const windows = BrowserWindow . getAllWindows ( ) ;
21+ windows . forEach ( ( window ) => {
22+ window . webContents . send ( 'update-status' , status ) ;
23+ } ) ;
24+ logger . info ( 'Update status:' , status ) ;
1425}
1526
1627export function initializeAutoUpdater ( ) {
@@ -33,103 +44,106 @@ function setupAutoUpdaterListeners() {
3344
3445 autoUpdater . on ( 'checking-for-update' , ( ) => {
3546 logger . info ( 'Checking for update...' ) ;
47+ sendUpdateStatus ( { status : 'checking' } ) ;
3648 } ) ;
3749
3850 autoUpdater . on ( 'update-available' , ( info : UpdateInfo ) => {
3951 logger . info ( 'Update available:' , info ) ;
40-
41- const updateWindow = getFocusedOrFirstWindow ( ) ;
42- if ( ! updateWindow ) {
43- return ;
44- }
45-
46- dialog
47- . showMessageBox ( updateWindow , {
48- type : 'info' ,
49- title : 'Update Available' ,
50- message : `A new version ${ info . version } is available. Would you like to download it now?` ,
51- detail : 'The update will be installed when you restart the application.' ,
52- buttons : [ 'Download' , 'Later' ] ,
53- defaultId : 0 ,
54- } )
55- . then ( ( result ) => {
56- if ( result . response === 0 ) {
57- autoUpdater . downloadUpdate ( ) ;
58- }
59- } ) ;
52+ sendUpdateStatus ( {
53+ status : 'available' ,
54+ version : info . version ,
55+ } ) ;
56+ // Auto-download will start automatically since autoDownload is true
6057 } ) ;
6158
6259 autoUpdater . on ( 'update-not-available' , ( info ) => {
6360 logger . info ( 'Update not available' , info ) ;
61+ sendUpdateStatus ( { status : 'up-to-date' } ) ;
6462 } ) ;
6563
6664 autoUpdater . on ( 'error' , ( err ) => {
6765 logger . error ( 'Error in auto-updater:' , err ) ;
66+ sendUpdateStatus ( {
67+ status : 'error' ,
68+ error : err . message || 'Unknown error occurred' ,
69+ } ) ;
6870 } ) ;
6971
7072 autoUpdater . on ( 'download-progress' , ( progressObj ) => {
71- let logMessage = 'Download speed: ' + progressObj . bytesPerSecond ;
72- logMessage = logMessage + ' - Downloaded ' + progressObj . percent + '%' ;
73- logMessage = logMessage + ' (' + progressObj . transferred + '/' + progressObj . total + ')' ;
73+ const logMessage =
74+ `Download speed: ${ progressObj . bytesPerSecond } - ` +
75+ `Downloaded ${ progressObj . percent } % ` +
76+ `(${ progressObj . transferred } /${ progressObj . total } )` ;
7477 logger . info ( logMessage ) ;
7578
76- const updateWindow = getFocusedOrFirstWindow ( ) ;
77- // Send progress to renderer
78- if ( updateWindow ) {
79- updateWindow . webContents . send ( 'update-download-progress' , progressObj ) ;
80- }
79+ sendUpdateStatus ( {
80+ status : 'downloading' ,
81+ downloadProgress : {
82+ percent : progressObj . percent ,
83+ transferred : progressObj . transferred ,
84+ total : progressObj . total ,
85+ } ,
86+ } ) ;
8187 } ) ;
8288
8389 autoUpdater . on ( 'update-downloaded' , ( info : UpdateInfo ) => {
8490 logger . info ( 'Update downloaded:' , info ) ;
85-
86- const updateWindow = getFocusedOrFirstWindow ( ) ;
87- if ( ! updateWindow ) {
88- return ;
89- }
90-
91- dialog
92- . showMessageBox ( updateWindow , {
93- type : 'info' ,
94- title : 'Update Ready' ,
95- message : 'Update downloaded' ,
96- detail : `Version ${ info . version } has been downloaded and will be automatically installed on restart.` ,
97- buttons : [ 'Restart Now' , 'Later' ] ,
98- defaultId : 0 ,
99- } )
100- . then ( ( result ) => {
101- if ( result . response === 0 ) {
102- // Use default behavior for NSIS installers on Windows
103- // This ensures proper quit sequence and allows installer to complete
104- autoUpdater . quitAndInstall ( ) ;
105- }
106- } ) ;
91+ sendUpdateStatus ( {
92+ status : 'ready' ,
93+ version : info . version ,
94+ } ) ;
10795 } ) ;
10896}
10997
110- export function checkForUpdates ( silent = false ) {
98+ export function checkForUpdates ( silent = false , userInitiated = false ) {
99+ // Debounce automatic checks to prevent spam
100+ if ( ! userInitiated && Date . now ( ) - lastCheckTime < MIN_CHECK_INTERVAL ) {
101+ logger . info ( 'Skipping update check - too soon since last check' ) ;
102+ return ;
103+ }
104+
105+ lastCheckTime = Date . now ( ) ;
106+
111107 if ( silent ) {
112108 autoUpdater
113109 . checkForUpdates ( )
114110 . then ( ( result ) => {
115- if ( result ?. isUpdateAvailable ) {
116- logger . info ( 'Update available ' , result ?. isUpdateAvailable ) ;
111+ if ( result ?. updateInfo ) {
112+ logger . info ( 'Update check result: ' , result . updateInfo . version ) ;
117113 }
118114 } )
119115 . catch ( ( error ) => {
120- logger . error ( 'Update failure' , error ) ;
116+ logger . error ( 'Update check failed:' , error ) ;
117+ sendUpdateStatus ( {
118+ status : 'error' ,
119+ error : error . message || 'Failed to check for updates' ,
120+ } ) ;
121121 } ) ;
122122 } else {
123+ // User-initiated check - always show feedback
123124 autoUpdater
124- . checkForUpdatesAndNotify ( )
125+ . checkForUpdates ( )
125126 . then ( ( result ) => {
126- if ( result ?. isUpdateAvailable ) {
127- logger . info ( 'Update available ' , result ?. isUpdateAvailable ) ;
127+ if ( result ?. updateInfo ) {
128+ logger . info ( 'Update check result: ' , result . updateInfo . version ) ;
128129 }
129130 } )
130131 . catch ( ( err ) => {
131132 logger . error ( 'Update check failed:' , err ) ;
132- dialog . showErrorBox ( 'Update Error' , `Failed to check for updates: ${ err . message } ` ) ;
133+ sendUpdateStatus ( {
134+ status : 'error' ,
135+ error : err . message || 'Failed to check for updates' ,
136+ } ) ;
133137 } ) ;
134138 }
135139}
140+
141+ export function installUpdate ( ) {
142+ // Use default behavior for NSIS installers on Windows
143+ // This ensures proper quit sequence and allows installer to complete
144+ autoUpdater . quitAndInstall ( ) ;
145+ }
146+
147+ export function getCurrentUpdateStatus ( ) : UpdateStatus {
148+ return currentUpdateStatus ;
149+ }
0 commit comments