diff --git a/ui/src/app/pages/apps-routes/app-available-list/app-available-list.page.ts b/ui/src/app/pages/apps-routes/app-available-list/app-available-list.page.ts index 9c3eb5852..0b0dcec31 100644 --- a/ui/src/app/pages/apps-routes/app-available-list/app-available-list.page.ts +++ b/ui/src/app/pages/apps-routes/app-available-list/app-available-list.page.ts @@ -35,7 +35,7 @@ export class AppAvailableListPage { markAsLoadingDuringP(this.$loading$, Promise.all([ this.getApps(), - this.osUpdateService.checkForUpdates(), // checks for an os update, banner component renders conditionally + this.osUpdateService.checkWhenNotAvailable$().toPromise(), // checks for an os update, banner component renders conditionally pauseFor(600), ])) } diff --git a/ui/src/app/services/api/api.service.ts b/ui/src/app/services/api/api.service.ts index 9d4ec9506..18cc0f6bb 100644 --- a/ui/src/app/services/api/api.service.ts +++ b/ui/src/app/services/api/api.service.ts @@ -67,7 +67,7 @@ export module ReqRes { export type PostLoginRes = Unit export type GetCheckAuthRes = { } export type GetServerRes = ApiServer - export type GetVersionLatestRes = { versionLatest: string, canUpdate: boolean } + export type GetVersionLatestRes = { versionLatest: string, canUpdate: boolean } // canUpdate not supported at least at 0.2.8 export type GetServerMetricsRes = ServerMetrics export type GetAppAvailableRes = ApiAppAvailableFull export type GetAppAvailableVersionInfoRes = AppAvailableVersionSpecificInfo diff --git a/ui/src/app/services/os-update.service.ts b/ui/src/app/services/os-update.service.ts index eb955fe92..704608085 100644 --- a/ui/src/app/services/os-update.service.ts +++ b/ui/src/app/services/os-update.service.ts @@ -1,9 +1,8 @@ import { Injectable } from '@angular/core' import { NavController } from '@ionic/angular' import { BehaviorSubject, forkJoin, Observable, of } from 'rxjs' -import { catchError, concatMap, distinctUntilChanged, filter, map, take, tap } from 'rxjs/operators' +import { catchError, concatMap, distinctUntilChanged, map, take, tap } from 'rxjs/operators' import { ServerModel, ServerStatus } from '../models/server-model' -import { traceWheel } from '../util/misc.util' import { ApiService } from './api/api.service' import { Emver } from './emver.service' @@ -25,22 +24,16 @@ export class OsUpdateService { private readonly navCtrl: NavController, ) { } - // emits everytime autoCheckUpdates becomes (or is) true - autoCheck$ (): Observable { - return this.serverModel.watch().autoCheckUpdates.pipe( - traceWheel('auto check updates 1'), - distinctUntilChanged(), - filter(check => check), - traceWheel('auto check updates 2'), - concatMap(() => this.apiService.getVersionLatest()), - traceWheel('getVersionLatest'), - map(({ canUpdate, versionLatest }) => canUpdate ? versionLatest : undefined), - tap(this.$updateAvailable$), + // emits the latest version or re-checks to see if there's a new latest version + checkWhenNotAvailable$ (): Observable { + return this.$updateAvailable$.pipe( + take(1), + concatMap(vl => vl ? of(vl) : this.checkForUpdates$()), ) } - // can call this imperatively and take the return value as gospel, or watch the $updateAvailable$ subject for the same info. - checkForUpdates (): Promise { + // can sub to this imperatively and take the return value as gospel, or watch the $updateAvailable$ subject for the same info. + checkForUpdates$ (): Observable { return forkJoin([ this.serverModel.watch().versionInstalled.pipe(take(1)), this.apiService.getVersionLatest(), @@ -52,7 +45,7 @@ export class OsUpdateService { }), // cache the result for components to learn update available without having to have called this method tap(this.$updateAvailable$), - ).toPromise() + ) } async checkForAppsUpdate (): Promise { diff --git a/ui/src/app/services/startup-alerts.notifier.ts b/ui/src/app/services/startup-alerts.notifier.ts index c3980647f..cc561e03b 100644 --- a/ui/src/app/services/startup-alerts.notifier.ts +++ b/ui/src/app/services/startup-alerts.notifier.ts @@ -1,10 +1,10 @@ import { Injectable } from '@angular/core' import { AlertController, ModalController, NavController } from '@ionic/angular' -import { combineLatest, EMPTY, iif, Observable, of } from 'rxjs' -import { concatMap, filter, take } from 'rxjs/operators' +import { combineLatest, Observable, of } from 'rxjs' +import { concatMap, filter, map, switchMap, take } from 'rxjs/operators' import { OSWelcomePage } from '../modals/os-welcome/os-welcome.page' import { ServerModel } from '../models/server-model' -import { exists, traceWheel } from '../util/misc.util' +import { exists } from '../util/misc.util' import { ApiService } from './api/api.service' import { ConfigService } from './config.service' import { LoaderService } from './loader.service' @@ -26,51 +26,57 @@ export class GlobalAlertsNotifier { init () { console.log('init') - this.osWelcome$().pipe( - concatMap(() => this.autoUpdateCheck$()), + of({ }).pipe( + concatMap( + () => this.welcomeNeeded$().pipe( + take(1), // we only show welcome at most once per app instance + concatMap(vi => vi ? this.presentOsWelcome(vi) : of({ })), + ), + ), + concatMap( + () => this.osUpdateAlertNeeded$().pipe( + switchMap(vl => vl ? this.presentUpdateDailogues(vl) : of({ })), + ), + ), ).subscribe() } - private osWelcome$ (): Observable { + // emits versionInstalled when welcomeAck is false and f.e and b.e have same version + private welcomeNeeded$ (): Observable { const { welcomeAck, versionInstalled } = this.server.watch() return combineLatest([ welcomeAck, versionInstalled ]).pipe( - filter( ([_, vi]) => !!vi), - traceWheel('osWelcome'), - take(1), // we will check and show welcome message at most once per app instance - concatMap(([wa, vi]) => iif( - () => !wa && vi === this.config.version, - this.presentOsWelcome(vi), - EMPTY, - )), + filter(([_, vi]) => !!vi), + map(([wa, vi]) => !wa && vi === this.config.version ? vi : undefined), ) } - private autoUpdateCheck$ (): Observable { - // this emits iff autoCheck is on and update available - return this.osUpdateService.autoCheck$().pipe( - traceWheel('autoUpdateCheck'), - filter(exists), - concatMap(async vl => { - const { update } = await this.presentAlertNewOS(vl) - if (update) { - return this.loader.displayDuringP( - this.osUpdateService.updateEmbassyOS(vl), - ).catch(e => alert(e)) - } - - try { - const newApps = await this.osUpdateService.checkForAppsUpdate() - if (newApps) { - return this.presentAlertNewApps() - } - } catch (e) { - console.error(`Exception checking for new apps: `, e) - } - }), + // emits versionLatest whenever autoCheckUpdates becomes true and checkForUpdates yields a new version + private osUpdateAlertNeeded$ (): Observable { + return this.server.watch().autoCheckUpdates.pipe( + filter(exists), // + concatMap(() => this.osUpdateService.checkForUpdates$()), ) } + private async presentUpdateDailogues (vl : string): Promise { + const { update } = await this.presentAlertNewOS(vl) + if (update) { + return this.loader.displayDuringP( + this.osUpdateService.updateEmbassyOS(vl), + ).catch(e => alert(e)) + } + + try { + const newApps = await this.osUpdateService.checkForAppsUpdate() + if (newApps) { + return this.presentAlertNewApps() + } + } catch (e) { + console.error(`Exception checking for new apps: `, e) + } + } + private async presentOsWelcome (vi: string): Promise { return new Promise(async resolve => { const modal = await this.modalCtrl.create({