diff --git a/src/app/child-dev-project/notes/dashboard-widgets/important-notes/important-notes.component.ts b/src/app/child-dev-project/notes/dashboard-widgets/important-notes/important-notes.component.ts index c862692da2..a931f2edfe 100644 --- a/src/app/child-dev-project/notes/dashboard-widgets/important-notes/important-notes.component.ts +++ b/src/app/child-dev-project/notes/dashboard-widgets/important-notes/important-notes.component.ts @@ -48,7 +48,7 @@ export class ImportantNotesComponent this.notes.pipe(first()).subscribe(() => (this.loading = false)); this.notes.pipe(untilDestroyed(this)).subscribe((next) => { this.notesDataSource.data = next - .filter((note) => this.noteIsRelevant(note)) + .filter((note) => note.warningLevel && this.noteIsRelevant(note)) .sort((a, b) => b.warningLevel._ordinal - a.warningLevel._ordinal); }); } diff --git a/src/app/core/pwa-install/pwa-install.component.spec.ts b/src/app/core/pwa-install/pwa-install.component.spec.ts index 6e1291f2b4..7cd0cc301f 100644 --- a/src/app/core/pwa-install/pwa-install.component.spec.ts +++ b/src/app/core/pwa-install/pwa-install.component.spec.ts @@ -4,7 +4,7 @@ import { PwaInstallComponent } from "./pwa-install.component"; import { PwaInstallModule } from "./pwa-install.module"; import { PwaInstallService, PWAInstallType } from "./pwa-install.service"; import { MatSnackBar } from "@angular/material/snack-bar"; -import { Subject } from "rxjs"; +import { firstValueFrom, Subject } from "rxjs"; import { take } from "rxjs/operators"; import { MockedTestingModule } from "../../utils/mocked-testing.module"; import { FontAwesomeTestingModule } from "@fortawesome/angular-fontawesome/testing"; @@ -12,13 +12,16 @@ import { FontAwesomeTestingModule } from "@fortawesome/angular-fontawesome/testi describe("PwaInstallComponent", () => { let mockPWAInstallService: jasmine.SpyObj; let mockSnackbar: jasmine.SpyObj; - const pwaInstallResult = new Subject(); + const pwaInstallResult = new Subject(); beforeEach(async () => { - mockPWAInstallService = jasmine.createSpyObj( - ["getPWAInstallType", "installPWA", "registerPWAInstallListener"], - { canInstallDirectly: pwaInstallResult.pipe(take(1)).toPromise() } + PwaInstallService.canInstallDirectly = firstValueFrom( + pwaInstallResult.pipe(take(1)) ); + mockPWAInstallService = jasmine.createSpyObj([ + "getPWAInstallType", + "installPWA", + ]); mockSnackbar = jasmine.createSpyObj(["openFromTemplate"]); await TestBed.configureTestingModule({ imports: [ diff --git a/src/app/core/pwa-install/pwa-install.component.ts b/src/app/core/pwa-install/pwa-install.component.ts index 94077ba0e9..9558d70967 100644 --- a/src/app/core/pwa-install/pwa-install.component.ts +++ b/src/app/core/pwa-install/pwa-install.component.ts @@ -1,6 +1,7 @@ import { Component, TemplateRef, ViewChild } from "@angular/core"; import { MatSnackBar } from "@angular/material/snack-bar"; import { PwaInstallService, PWAInstallType } from "./pwa-install.service"; + @Component({ selector: "app-pwa-install", templateUrl: "./pwa-install.component.html", @@ -22,7 +23,7 @@ export class PwaInstallComponent { if (this.pwaInstallType === PWAInstallType.ShowiOSInstallInstructions) { this.showPWAInstallButton = true; } - pwaInstallService.canInstallDirectly.then(() => { + PwaInstallService.canInstallDirectly?.then(() => { this.showPWAInstallButton = true; }); } diff --git a/src/app/core/pwa-install/pwa-install.module.ts b/src/app/core/pwa-install/pwa-install.module.ts index 5137244381..02fdb76044 100644 --- a/src/app/core/pwa-install/pwa-install.module.ts +++ b/src/app/core/pwa-install/pwa-install.module.ts @@ -10,6 +10,7 @@ import { PwaInstallService } from "./pwa-install.service"; import { MatSnackBarModule } from "@angular/material/snack-bar"; import { WINDOW_TOKEN } from "../../utils/di-tokens"; import { Angulartics2Module } from "angulartics2"; + @NgModule({ declarations: [PwaInstallComponent], imports: [ @@ -25,8 +26,4 @@ import { Angulartics2Module } from "angulartics2"; providers: [PwaInstallService, { provide: WINDOW_TOKEN, useValue: window }], exports: [PwaInstallComponent], }) -export class PwaInstallModule { - constructor(pwaInstallService: PwaInstallService) { - pwaInstallService.registerPWAInstallListener(); - } -} +export class PwaInstallModule {} diff --git a/src/app/core/pwa-install/pwa-install.service.spec.ts b/src/app/core/pwa-install/pwa-install.service.spec.ts index 39c3975149..e4b0da6bd9 100644 --- a/src/app/core/pwa-install/pwa-install.service.spec.ts +++ b/src/app/core/pwa-install/pwa-install.service.spec.ts @@ -13,7 +13,6 @@ describe("PwaInstallService", () => { navigator: { userAgent: "mockAgent", }, - addEventListener: () => {}, innerWidth: 2000, matchMedia: () => ({}), }; @@ -48,7 +47,7 @@ describe("PwaInstallService", () => { it("should execute install event when calling install", async () => { const installSpy = jasmine.createSpy(); - spyOn(mockWindow, "addEventListener").and.callFake((_, callback) => + spyOn(window, "addEventListener").and.callFake((_, callback) => callback({ prompt: installSpy, preventDefault: () => {}, @@ -56,16 +55,19 @@ describe("PwaInstallService", () => { }) ); - service.registerPWAInstallListener(); - expect(mockWindow.addEventListener).toHaveBeenCalledWith( + PwaInstallService.registerPWAInstallListener(); + expect(window.addEventListener).toHaveBeenCalledWith( "beforeinstallprompt", jasmine.anything() ); - await expectAsync(service.canInstallDirectly).toBeResolved(); + await expectAsync(PwaInstallService.canInstallDirectly).toBeResolved(); const installPromise = service.installPWA(); expect(installSpy).toHaveBeenCalled(); await expectAsync(installPromise).toBeResolvedTo({ outcome: "accepted" }); + + // reset static property + PwaInstallService["deferredInstallPrompt"] = undefined; }); it("should throw an error when trying to install without install prompt", () => { diff --git a/src/app/core/pwa-install/pwa-install.service.ts b/src/app/core/pwa-install/pwa-install.service.ts index 1b6c33aa29..f1c9cc98e0 100644 --- a/src/app/core/pwa-install/pwa-install.service.ts +++ b/src/app/core/pwa-install/pwa-install.service.ts @@ -6,6 +6,7 @@ export enum PWAInstallType { RunningAsPWA, NotAvailable, } + enum Browser { Opera, MicrosoftInternetExplorer, @@ -15,6 +16,7 @@ enum Browser { Firefox, Other, } + enum OS { iOS, MacOS, @@ -29,15 +31,15 @@ export class PwaInstallService { /** * Resolves once/if it is possible to directly install the app */ - canInstallDirectly: Promise; + static canInstallDirectly: Promise; - private deferredInstallPrompt: any; + private static deferredInstallPrompt: any; constructor(@Inject(WINDOW_TOKEN) private window: Window) {} - registerPWAInstallListener() { + static registerPWAInstallListener() { this.canInstallDirectly = new Promise((resolve) => { - this.window.addEventListener("beforeinstallprompt", (e) => { + window.addEventListener("beforeinstallprompt", (e) => { e.preventDefault(); this.deferredInstallPrompt = e; resolve(); @@ -46,13 +48,13 @@ export class PwaInstallService { } installPWA(): Promise { - if (!this.deferredInstallPrompt) { + if (!PwaInstallService.deferredInstallPrompt) { throw new Error( "InstallPWA called, but PWA install prompt has not fired." ); } - this.deferredInstallPrompt.prompt(); - return this.deferredInstallPrompt.userChoice; + PwaInstallService.deferredInstallPrompt.prompt(); + return PwaInstallService.deferredInstallPrompt.userChoice; } getPWAInstallType(): PWAInstallType { diff --git a/src/assets/locale/messages.de.xlf b/src/assets/locale/messages.de.xlf index 04b7992d4f..0addbd8688 100644 --- a/src/assets/locale/messages.de.xlf +++ b/src/assets/locale/messages.de.xlf @@ -722,7 +722,7 @@ >"/> >  days Tage + >"/> >  Tage Format like 'Days passed > 5 days' Amount of days back diff --git a/src/main.ts b/src/main.ts index 154970196a..7cf946bfbb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -27,11 +27,15 @@ import * as parseXliffToJson from "./app/utils/parse-xliff-to-js"; import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; import { AppSettings } from "./app/core/app-config/app-settings"; import { LoggingService } from "./app/core/logging/logging.service"; +import { PwaInstallService } from "./app/core/pwa-install/pwa-install.service"; if (environment.production) { enableProdMode(); } +// Listening to event as soon as possible +PwaInstallService.registerPWAInstallListener(); + // Initialize remote logging LoggingService.initRemoteLogging({ dsn: environment.remoteLoggingDsn,