PWA support
@flyze/lib-core-angular 1.0.0-alpha.34· latestPwaModule wraps @angular/service-worker to detect that an app is running as an installed PWA,
notice that a new version is ready, and activate it.
Read the limitations section before relying on this module. The update path works; the install path does not, and the timing constants are wrong.
PwaModule.forRoot(config) provides PwaService, PwaUpdateService and the config under the
PwaConfigService token
(pwa.module.ts:16). A
@Optional() @SkipSelf() constructor guard throws if the module is imported more than once
(pwa.module.ts:27) — importing without
forRoot() provides nothing and injection fails instead.
interface PwaConfig { update: { auto: boolean; needsUserPermission: boolean };}PwaService.initialize() must be called explicitly — nothing happens on injection
(pwa.service.ts:35). It
resolves appIsPwa, starts network tracking, and — only when running as a PWA — starts update
checks and the install listeners.
Detecting a PWA
Section titled “Detecting a PWA”PwaUpdateService.appIsPwa() returns SwUpdate.isEnabled
(pwa-update.service.ts:58),
which is true when a service worker is registered and controlling the page. That is a proxy, not the
real question: a browser tab of a service-worker-enabled app reports true while an installed app
whose worker has not taken control yet reports false. It says “the service worker is active”, not
“the app was installed”.
The update flow
Section titled “The update flow”checkForUpdates() subscribes to SwUpdate.versionUpdates, filtered to VERSION_READY
(pwa-update.service.ts:34). On such an
event updateAvailable$ emits true, and then the config decides:
auto | needsUserPermission | Behavior |
|---|---|---|
false | — | nothing — updateAvailable$ only |
true | false | activate and reload immediately |
true | true | ask first — but see the limitations |
promptUser() calls activateUpdate() and then document.location.reload()
(pwa-update.service.ts:78). Note the flag
names read backwards from what they do: needsUserPermission: false is the silent path.
Observables: updateAvailable$ and updated$ on PwaUpdateService, installAvailable$,
installed$ and networkAvailable$ on PwaService.
Limitations
Section titled “Limitations”All of these are in shipped code today.
- The install prompt never fires. The listeners are registered for
'window:beforeinstallprompt'and'window:appinstalled'(pwa.service.ts:68) —window:is Angular’s@HostListenerprefix, not part of the DOM event name, which isbeforeinstallprompt. SoinstallPromptis never captured,installAvailable$never emitstrue, andinstall()can never do anything. installed$is the wrong subject. It is assignedinstallAvailableSubject$.asObservable()(pwa.service.ts:26), so it mirrors install-availability andinstalledSubject$is written but never read.- The periodic update check runs every 21.6 seconds.
interval(6 * 60 * 60)(pwa-update.service.ts:28) is milliseconds — the intended six hours needs* 1000. It also runs unconditionally from the constructor, is never unsubscribed, and is independent ofcheckForUpdates(). needsUserPermission: truesilently never updates.allowUpdateModalis an empty method with its body commented out (pwa-update.service.ts:62), left over from a removed dialog component. The callback is never invoked, so no update is ever activated in that mode.MatDialogis still injected and unused.catchErrorused as a promise handler.activateUpdate().then(onSuccess, catchError(…))(pwa-update.service.ts:79) passes an RxJS operator where a rejection handler belongs, so a failed activation does not run the intended reset.- Duplicate network tracking.
checkNetworkAvailable()reimplementsNetworkStatusService(network-status) with a hardcodedtrueseed and no duplicate suppression. updated$andupdateAvailable$both emittrueafter a successful activation (pwa-update.service.ts:81), which reads like a copy-paste of the failure branch.
Practical guidance: use updateAvailable$ plus auto: true, needsUserPermission: false, or drive
SwUpdate directly. Use network-status for connectivity, and do not build an
install button on this module.