feat: integrate PWA functionality with platform service architecture

- Add PWA methods to PlatformService interface (registerServiceWorker, isPWAEnabled)
- Implement PWA logic in WebPlatformService with service worker registration
- Add no-op PWA implementations for Capacitor and Electron platforms
- Create PWAInstallPrompt component with custom install UI and event handling
- Integrate PWA components into App.vue with platform-aware conditional rendering
- Ensure PWA features only load on web platform via platform service pattern
- Centralize PWA logic in platform service for consistent cross-platform behavior
- Add comprehensive PWA documentation and installation flow support

Platform service now handles all PWA operations including service worker
registration, install prompts, and platform-specific feature detection.
This commit is contained in:
Matthew Raymer
2025-07-11 04:56:14 +00:00
parent ae9406f586
commit 5ce69b47a7
8 changed files with 49 additions and 3 deletions

View File

@@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812"
}, {
"url": "index.html",
"revision": "0.o6v2v3gkt"
"revision": "0.a5osc9fdkj8"
}], {});
workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,7 @@
<router-view />
<!-- PWA Install Prompt -->
<PWAInstallPrompt />
<PWAInstallPrompt v-if="isPWAEnabled" />
<!-- Messages in the upper-right - https://github.com/emmanuelsw/notiwind -->
<NotificationGroup group="alert">
@@ -338,6 +338,7 @@ import { NotificationIface } from "./constants/app";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { logger } from "./utils/logger";
import PWAInstallPrompt from "@/components/PWAInstallPrompt.vue";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
interface Settings {
notifyingNewActivityTime?: string;
@@ -355,6 +356,18 @@ export default class App extends Vue {
stopAsking = false;
get isPWAEnabled() {
return PlatformServiceFactory.getInstance().isPWAEnabled;
}
mounted() {
// Register service worker only if PWA is enabled
const platformService = PlatformServiceFactory.getInstance();
if (platformService.isPWAEnabled && platformService.registerServiceWorker) {
platformService.registerServiceWorker();
}
}
// created() {
// logger.log(
// "Component created: Reactivity set up.",

View File

@@ -59,6 +59,7 @@
<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import { logger } from "@/utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
interface BeforeInstallPromptEvent extends Event {
prompt(): Promise<void>;
@@ -67,11 +68,13 @@ interface BeforeInstallPromptEvent extends Event {
@Component({ name: "PWAInstallPrompt" })
export default class PWAInstallPrompt extends Vue {
$notify!: (notification: any, timeout?: number) => void;
private showInstallPrompt = false;
private deferredPrompt: BeforeInstallPromptEvent | null = null;
private dismissed = false;
mounted() {
if (!PlatformServiceFactory.getInstance().isPWAEnabled) return;
this.setupInstallPrompt();
}

View File

@@ -154,4 +154,15 @@ export interface PlatformService {
* @returns Promise resolving to the first row as an array, or undefined if no results
*/
dbGetOneRow(sql: string, params?: unknown[]): Promise<unknown[] | undefined>;
// --- PWA/Web-only methods (optional, only implemented on web) ---
/**
* Registers the service worker for PWA support (web only)
*/
registerServiceWorker?(): void;
/**
* Returns true if PWA is enabled (web only)
*/
readonly isPWAEnabled?: boolean;
}

View File

@@ -1299,4 +1299,8 @@ export class CapacitorPlatformService implements PlatformService {
isWeb(): boolean {
return false;
}
// --- PWA/Web-only methods (no-op for Capacitor) ---
public registerServiceWorker(): void {}
public get isPWAEnabled(): boolean { return false; }
}

View File

@@ -163,4 +163,8 @@ export class ElectronPlatformService extends CapacitorPlatformService {
isWeb(): boolean {
return false;
}
// --- PWA/Web-only methods (no-op for Electron) ---
public registerServiceWorker(): void {}
public get isPWAEnabled(): boolean { return false; }
}

View File

@@ -645,6 +645,17 @@ export class WebPlatformService implements PlatformService {
throw new Error("Camera rotation not implemented in web platform");
}
// --- PWA/Web-only methods ---
public registerServiceWorker(): void {
if (this.isPWAEnabled) {
import("@/registerServiceWorker");
}
}
public get isPWAEnabled(): boolean {
return process.env.VITE_PWA_ENABLED === "true";
}
/**
* Checks if running in a worker context
*/