diff --git a/apps/electron-backend/src/main.ts b/apps/electron-backend/src/main.ts index 1b1fefc13..23c215079 100644 --- a/apps/electron-backend/src/main.ts +++ b/apps/electron-backend/src/main.ts @@ -86,6 +86,13 @@ export default class Main { trace('startup', 'bootstrap-events:start'); } + const appUpdateService = new AppUpdateService({ + app, + getMainWindow: () => App.mainWindow, + updater: autoUpdater, + }); + AppUpdateEvents.bootstrapAppUpdateEvents(appUpdateService); + // Initialize database before other events await initDatabase(); @@ -105,12 +112,6 @@ export default class Main { DatabaseEvents.bootstrapDatabaseEvents(); EpgEvents.bootstrapEpgEvents(); RemoteControlEvents.bootstrapRemoteControlEvents(); - const appUpdateService = new AppUpdateService({ - app, - getMainWindow: () => App.mainWindow, - updater: autoUpdater, - }); - AppUpdateEvents.bootstrapAppUpdateEvents(appUpdateService); void appUpdateService.checkForUpdatesOnStartup(); // Set main window for downloads and reset stale downloads diff --git a/apps/web/src/app/settings/settings.component.spec.ts b/apps/web/src/app/settings/settings.component.spec.ts index f77917018..04745326e 100644 --- a/apps/web/src/app/settings/settings.component.spec.ts +++ b/apps/web/src/app/settings/settings.component.spec.ts @@ -422,6 +422,35 @@ describe('SettingsComponent', () => { expect(component.appUpdateStatus()).toEqual(retriedStatus); }); + it('waits for the desktop app update bridge method before loading status', async () => { + const retriedStatus: ElectronBridgeAppUpdateStatus = { + ...DEFAULT_APP_UPDATE_STATUS, + status: ELECTRON_BRIDGE_APP_UPDATE_STATUSES.Unsupported, + supportedSelfUpdate: false, + }; + await fixture.whenStable(); + delete (window.electron as Partial) + .getAppUpdateStatus; + let retryCount = 0; + const getStatus = jest.fn().mockResolvedValue(retriedStatus); + jest.spyOn( + privateApi(component), + 'waitForAppUpdateStatusRetry' + ).mockImplementation(async () => { + retryCount += 1; + + if (retryCount === 1) { + window.electron.getAppUpdateStatus = getStatus; + } + }); + + await privateApi(component).loadAppUpdateStatus(); + + expect(retryCount).toBe(1); + expect(getStatus).toHaveBeenCalledTimes(1); + expect(component.appUpdateStatus()).toEqual(retriedStatus); + }); + it('forwards app update actions to the desktop bridge', async () => { await component.checkForAppUpdate(); await component.downloadAppUpdate(); diff --git a/apps/web/src/app/settings/settings.component.ts b/apps/web/src/app/settings/settings.component.ts index dcc563037..462f4ebee 100644 --- a/apps/web/src/app/settings/settings.component.ts +++ b/apps/web/src/app/settings/settings.component.ts @@ -85,8 +85,8 @@ import { import { SettingsSnackbarService } from './settings-snackbar.service'; import { AppUpdateReleaseNotesDialogComponent } from './app-update-release-notes-dialog.component'; -const APP_UPDATE_STATUS_LOAD_ATTEMPTS = 5; -const APP_UPDATE_STATUS_LOAD_RETRY_DELAY_MS = 100; +const APP_UPDATE_STATUS_LOAD_ATTEMPTS = 60; +const APP_UPDATE_STATUS_LOAD_RETRY_DELAY_MS = 250; @Component({ templateUrl: './settings.component.html', @@ -320,28 +320,40 @@ export class SettingsComponent implements OnInit, OnDestroy { } private async loadAppUpdateStatus(): Promise { - if (!this.isDesktop || !window.electron?.getAppUpdateStatus) { + if (!this.isDesktop) { return; } + let lastError: unknown; + for ( let attempt = 1; attempt <= APP_UPDATE_STATUS_LOAD_ATTEMPTS; attempt += 1 ) { - try { - this.appUpdateStatus.set( - await window.electron.getAppUpdateStatus() + const electron = window.electron; + + if (electron?.getAppUpdateStatus) { + try { + this.appUpdateStatus.set( + await electron.getAppUpdateStatus() + ); + return; + } catch (error) { + lastError = error; + } + } + + if (attempt === APP_UPDATE_STATUS_LOAD_ATTEMPTS) { + console.warn( + 'Failed to load app update status:', + lastError ?? + new Error('Desktop app update bridge is unavailable') ); return; - } catch (error) { - if (attempt === APP_UPDATE_STATUS_LOAD_ATTEMPTS) { - console.warn('Failed to load app update status:', error); - return; - } - - await this.waitForAppUpdateStatusRetry(); } + + await this.waitForAppUpdateStatusRetry(); } }