From 1a02b845b84351b17db90a534e3eb8503bbb967d Mon Sep 17 00:00:00 2001 From: Sean Engelhardt Date: Fri, 10 May 2019 13:04:40 +0200 Subject: [PATCH] Enhance update service Updates will be observed from site component (Makes pure projectors ignore updates, unless the user navigates manually) Updates can now be delayed using the "noInterruption" route data. If the "noInterruption" route data was set, updates notifications will not be shown in this view. The update notification will appear, after the user navigates to a view without "noInterruption" flag. --- client/src/app/app-routing.module.ts | 6 +- client/src/app/app.component.ts | 3 - .../app/core/ui-services/update.service.ts | 36 ++++++----- .../components/start/start.component.html | 1 + client/src/app/site/site.component.ts | 63 ++++++++++++++++++- 5 files changed, 85 insertions(+), 24 deletions(-) diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts index 5a0e0f54b..ab555c939 100644 --- a/client/src/app/app-routing.module.ts +++ b/client/src/app/app-routing.module.ts @@ -23,7 +23,11 @@ const routes: Routes = [ { path: 'privacypolicy', component: LoginPrivacyPolicyComponent } ] }, - { path: 'projector', loadChildren: './fullscreen-projector/fullscreen-projector.module#FullscreenProjectorModule' }, + { + path: 'projector', + loadChildren: './fullscreen-projector/fullscreen-projector.module#FullscreenProjectorModule', + data: { noInterruption: true } + }, { path: '', loadChildren: './site/site.module#SiteModule' }, { path: '**', redirectTo: '' } ]; diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index e84c32610..f48ce793d 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts @@ -12,7 +12,6 @@ import { OperatorService } from './core/core-services/operator.service'; import { ServertimeService } from './core/core-services/servertime.service'; import { ThemeService } from './core/ui-services/theme.service'; import { DataStoreUpgradeService } from './core/core-services/data-store-upgrade.service'; -import { UpdateService } from './core/ui-services/update.service'; import { PrioritizeService } from './core/core-services/prioritize.service'; import { PingService } from './core/core-services/ping.service'; import { SpinnerService } from './core/ui-services/spinner.service'; @@ -44,7 +43,6 @@ export class AppComponent { * @param configService to call the constructor of the ConfigService * @param loadFontService to call the constructor of the LoadFontService * @param dataStoreUpgradeService - * @param update Service Worker Updates */ public constructor( translate: TranslateService, @@ -60,7 +58,6 @@ export class AppComponent { configService: ConfigService, loadFontService: LoadFontService, dataStoreUpgradeService: DataStoreUpgradeService, // to start it. - update: UpdateService, prioritizeService: PrioritizeService, pingService: PingService ) { diff --git a/client/src/app/core/ui-services/update.service.ts b/client/src/app/core/ui-services/update.service.ts index b1448e447..d42ae564f 100644 --- a/client/src/app/core/ui-services/update.service.ts +++ b/client/src/app/core/ui-services/update.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@angular/core'; -import { SwUpdate } from '@angular/service-worker'; -import { MatSnackBar } from '@angular/material'; +import { SwUpdate, UpdateAvailableEvent } from '@angular/service-worker'; import { NotifyService } from '../core-services/notify.service'; +import { Observable } from 'rxjs'; /** * Handle Service Worker updates using the SwUpdate service form angular. @@ -13,6 +13,13 @@ import { NotifyService } from '../core-services/notify.service'; export class UpdateService { private static NOTIFY_NAME = 'swCheckForUpdate'; + /** + * @returns the updateSubscription + */ + public get updateObservable(): Observable { + return this.swUpdate.available; + } + /** * Constructor. * Listens to available updates @@ -20,27 +27,22 @@ export class UpdateService { * @param swUpdate Service Worker update service * @param matSnackBar Currently to show that an update is available */ - public constructor(private swUpdate: SwUpdate, matSnackBar: MatSnackBar, private notify: NotifyService) { - swUpdate.available.subscribe(() => { - // TODO: Find a better solution OR make an update-bar like for history mode - const ref = matSnackBar.open('A new update is available!', 'Refresh', { - duration: 0 - }); - - // Enforces an update - ref.onAction().subscribe(() => { - this.swUpdate.activateUpdate().then(() => { - document.location.reload(); - }); - }); - }); - + public constructor(private swUpdate: SwUpdate, private notify: NotifyService) { // Listen on requests from other users to check for updates. this.notify.getMessageObservable(UpdateService.NOTIFY_NAME).subscribe(() => { this.checkForUpdate(); }); } + /** + * Manually applies the update if one was found + */ + public applyUpdate(): void { + this.swUpdate.activateUpdate().then(() => { + document.location.reload(); + }); + } + /** * Trigger that to manually check for updates */ diff --git a/client/src/app/site/common/components/start/start.component.html b/client/src/app/site/common/components/start/start.component.html index 70f0f6080..32a1a0126 100644 --- a/client/src/app/site/common/components/start/start.component.html +++ b/client/src/app/site/common/components/start/start.component.html @@ -7,6 +7,7 @@

{{ welcomeTitle | translate }}

+
diff --git a/client/src/app/site/site.component.ts b/client/src/app/site/site.component.ts index 002074684..a5b3fe3e7 100644 --- a/client/src/app/site/site.component.ts +++ b/client/src/app/site/site.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { Router, NavigationEnd } from '@angular/router'; +import { Router, NavigationEnd, ActivationEnd } from '@angular/router'; import { FormGroup, FormControl } from '@angular/forms'; -import { MatDialog, MatSidenav } from '@angular/material'; +import { MatDialog, MatSidenav, MatSnackBar } from '@angular/material'; import { Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; @@ -16,6 +16,16 @@ import { OpenSlidesStatusService } from '../core/core-services/openslides-status import { TimeTravelService } from '../core/core-services/time-travel.service'; import { langToLocale } from 'app/shared/utils/lang-to-locale'; import { ConfigService } from 'app/core/ui-services/config.service'; +import { UpdateService } from 'app/core/ui-services/update.service'; +import { filter } from 'rxjs/operators'; + +/** + * Interface to describe possible routing data + */ +interface RoutingData { + basePerm?: string; + noInterruption?: boolean; +} @Component({ selector: 'os-site', @@ -45,6 +55,16 @@ export class SiteComponent extends BaseComponent implements OnInit { */ public searchform: FormGroup; + /** + * Hold the current routing data to make certain checks + */ + private routingData: RoutingData; + + /** + * Set to true if an update was suppressed + */ + private delayedUpdateAvailable = false; + /** * Constructor * @@ -62,6 +82,7 @@ export class SiteComponent extends BaseComponent implements OnInit { title: Title, translate: TranslateService, configService: ConfigService, + private updateService: UpdateService, private authService: AuthService, private router: Router, public operator: OperatorService, @@ -69,7 +90,8 @@ export class SiteComponent extends BaseComponent implements OnInit { public dialog: MatDialog, public mainMenuService: MainMenuService, public OSStatus: OpenSlidesStatusService, - public timeTravel: TimeTravelService + public timeTravel: TimeTravelService, + private matSnackBar: MatSnackBar ) { super(title, translate); @@ -83,6 +105,18 @@ export class SiteComponent extends BaseComponent implements OnInit { }); this.searchform = new FormGroup({ query: new FormControl([]) }); + + // detect routing data such as base perm and noInterruption + this.router.events + .pipe(filter(event => event instanceof ActivationEnd && event.snapshot.children.length === 0)) + .subscribe((event: ActivationEnd) => { + this.routingData = event.snapshot.data as RoutingData; + + // if the current route has no "noInterruption" flag and an update is available, show the update + if (this.delayedUpdateAvailable && !this.routingData.noInterruption) { + this.showUpdateNotification(); + } + }); } /** @@ -125,6 +159,29 @@ export class SiteComponent extends BaseComponent implements OnInit { } } }); + + // check for updates + this.updateService.updateObservable.subscribe(() => { + if (this.routingData.noInterruption) { + this.delayedUpdateAvailable = true; + } else { + this.showUpdateNotification(); + } + }); + } + + /** + * Shows the update notification + */ + private showUpdateNotification(): void { + const ref = this.matSnackBar.open('A new update is available!', 'Refresh', { + duration: 0 + }); + + // Enforces an update + ref.onAction().subscribe(() => { + this.updateService.applyUpdate(); + }); } /**