Skip to content

Commit

Permalink
fix: install button is always visible (#1466)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheSlimvReal authored Sep 28, 2022
1 parent f591c06 commit 9a052b6
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 23 deletions.
13 changes: 8 additions & 5 deletions src/app/core/pwa-install/pwa-install.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@ 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";

describe("PwaInstallComponent", () => {
let mockPWAInstallService: jasmine.SpyObj<PwaInstallService>;
let mockSnackbar: jasmine.SpyObj<MatSnackBar>;
const pwaInstallResult = new Subject();
const pwaInstallResult = new Subject<any>();

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: [
Expand Down
3 changes: 2 additions & 1 deletion src/app/core/pwa-install/pwa-install.component.ts
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -22,7 +23,7 @@ export class PwaInstallComponent {
if (this.pwaInstallType === PWAInstallType.ShowiOSInstallInstructions) {
this.showPWAInstallButton = true;
}
pwaInstallService.canInstallDirectly.then(() => {
PwaInstallService.canInstallDirectly?.then(() => {
this.showPWAInstallButton = true;
});
}
Expand Down
7 changes: 2 additions & 5 deletions src/app/core/pwa-install/pwa-install.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand All @@ -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 {}
12 changes: 7 additions & 5 deletions src/app/core/pwa-install/pwa-install.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ describe("PwaInstallService", () => {
navigator: {
userAgent: "mockAgent",
},
addEventListener: () => {},
innerWidth: 2000,
matchMedia: () => ({}),
};
Expand Down Expand Up @@ -48,24 +47,27 @@ 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: () => {},
userChoice: Promise.resolve({ outcome: "accepted" }),
})
);

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", () => {
Expand Down
16 changes: 9 additions & 7 deletions src/app/core/pwa-install/pwa-install.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export enum PWAInstallType {
RunningAsPWA,
NotAvailable,
}

enum Browser {
Opera,
MicrosoftInternetExplorer,
Expand All @@ -15,6 +16,7 @@ enum Browser {
Firefox,
Other,
}

enum OS {
iOS,
MacOS,
Expand All @@ -29,15 +31,15 @@ export class PwaInstallService {
/**
* Resolves once/if it is possible to directly install the app
*/
canInstallDirectly: Promise<void>;
static canInstallDirectly: Promise<void>;

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();
Expand All @@ -46,13 +48,13 @@ export class PwaInstallService {
}

installPWA(): Promise<any> {
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 {
Expand Down
4 changes: 4 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 9a052b6

Please sign in to comment.