\n To use this app, please update to the latest version.
\n
\n \n\n","import { Inject, Injectable } from \"@angular/core\";\nimport { MatDialog } from \"@angular/material/dialog\";\nimport { MatSnackBar } from \"@angular/material/snack-bar\";\nimport { Router } from \"@angular/router\";\nimport { SwUpdate } from \"@angular/service-worker\";\n\nimport { switchMap } from \"rxjs/operators\";\n\nimport { WINDOW } from \"src/app/core/services/window.service\";\nimport { UpdateAppComponent } from \"../components/update-app/update-app.component\";\n\n@Injectable({\n providedIn: \"root\",\n})\nexport class PwaUpdatePromptService {\n constructor(\n private matSnackBar: MatSnackBar,\n private swUpdate: SwUpdate,\n private router: Router,\n private dialog: MatDialog,\n @Inject(WINDOW) private window: Window\n ) {}\n\n promptForUpdate() {\n this.matSnackBar\n .open(\"An update is available for myQQ!\", \"Update\")\n .onAction()\n .pipe(switchMap(() => this.swUpdate.activateUpdate()))\n .subscribe(() => {\n this.router.navigate([\"/\"]).then(() => this.window.location.reload());\n });\n }\n\n promptForAndroidDownload() {\n this.matSnackBar\n .open(\"Download our new and improved Android app!\", \"Download\")\n .onAction()\n .subscribe(() => {\n this.downloadAndroidApp();\n });\n }\n\n downloadAndroidApp() {\n window.open(\n \"https://play.google.com/store/apps/details?id=com.dontdrivedirty.myqq.twa\",\n \"_blank\"\n );\n }\n\n forceUpdate() {\n const dialog = this.dialog.open(UpdateAppComponent, {\n disableClose: true,\n });\n\n dialog\n .afterClosed()\n .pipe(switchMap(() => this.swUpdate.activateUpdate()))\n .subscribe(() => {\n this.router.navigate([\"/\"]).then(() => this.window.location.reload());\n });\n }\n}\n","import { Inject, Injectable } from \"@angular/core\";\nimport { Platform } from \"@angular/cdk/platform\";\nimport { Router } from \"@angular/router\";\nimport { SwUpdate } from \"@angular/service-worker\";\n\nimport { Store } from \"@ngrx/store\";\nimport { interval, Observable } from \"rxjs\";\n\nimport { log, LogAction, LogLevels } from \"src/app/core/ngrx/logger\";\nimport { WINDOW } from \"src/app/core/services/window.service\";\nimport { environment } from \"src/environments/environment\";\n\nimport { PwaUpdatePromptService } from \"./pwa-update-prompt.service\";\nimport { isReplete } from \"@nll/datum/Datum\";\nimport { isSuccess } from \"@nll/datum/DatumEither\";\nimport { getAppMinVersion, selectAppMinVersion } from \"src/app/core/ngrx/myqq\";\nimport { filter, skip, take } from \"rxjs/operators\";\nimport { version } from \"src/environments/version\";\nimport * as semver from \"semver\";\nimport { UnleashService } from \"./unleash.service\";\n\ninterface RelatedApp {\n id: string;\n platform: string;\n url?: string;\n}\n\nconst pwaMode = environment.pwaMode;\nconst twaId = environment.twaId;\nconst checkUpdateInterval = 1; // Hours\n\n/**\n * This service handles various ancillary PWA-related tasks, such as:\n * - Prompt users to install, as appropriate for device, in not-too-naggy intervals\n * - Check for updates and prompt to reload if using an old version\n * - Try to determine if myQQ is running as a PWA/TWA (=== in standalone mode) and if the TWA binary is installed on the device.\n *\n * @todo unit test\n */\n\n@Injectable({\n providedIn: \"root\",\n})\nexport class PwaService {\n public pwaMode: string;\n public isInStandaloneMode: boolean;\n public isMobile: boolean;\n public device: \"ios\" | \"android\" | \"unknown\";\n public isInstalled: boolean = null; // Is the TWA installed on this device, regardless of whether it is being used now?\n\n constructor(\n private swUpdate: SwUpdate,\n private platform: Platform,\n private store$: Store