From 009a68a0d27ae144ee8176dd93ab0d5b669302f6 Mon Sep 17 00:00:00 2001 From: Hikari Date: Fri, 20 Feb 2026 01:07:16 -0800 Subject: [PATCH] revert: remove PWA functionality due to service worker issues The PWA implementation was causing too many issues: - Service worker conflicts with CSP policies - 429 rate limiting errors - Application freezing - External resource blocking Removed: - service-worker.js - manifest.json - offline.html - PWA service and install component - PWA meta tags from index.html - PWA asset configuration The library now functions as a standard web app without PWA features. This provides a more stable and reliable user experience. --- apps/frontend/project.json | 15 -- apps/frontend/src/app/app.html | 1 - apps/frontend/src/app/app.ts | 6 +- .../pwa-install/pwa-install.component.ts | 176 ----------------- apps/frontend/src/app/services/pwa.service.ts | 105 ---------- apps/frontend/src/index.html | 5 - apps/frontend/src/service-worker.js | 186 ------------------ 7 files changed, 1 insertion(+), 493 deletions(-) delete mode 100644 apps/frontend/src/app/components/pwa-install/pwa-install.component.ts delete mode 100644 apps/frontend/src/app/services/pwa.service.ts delete mode 100644 apps/frontend/src/service-worker.js diff --git a/apps/frontend/project.json b/apps/frontend/project.json index 6603e85..ea4900a 100644 --- a/apps/frontend/project.json +++ b/apps/frontend/project.json @@ -19,21 +19,6 @@ { "glob": "**/*", "input": "apps/frontend/public" - }, - { - "glob": "manifest.json", - "input": "apps/frontend/src", - "output": "/" - }, - { - "glob": "service-worker.js", - "input": "apps/frontend/src", - "output": "/" - }, - { - "glob": "offline.html", - "input": "apps/frontend/src", - "output": "/" } ], "styles": ["apps/frontend/src/styles.scss"] diff --git a/apps/frontend/src/app/app.html b/apps/frontend/src/app/app.html index 864bcac..f447414 100644 --- a/apps/frontend/src/app/app.html +++ b/apps/frontend/src/app/app.html @@ -4,4 +4,3 @@ - diff --git a/apps/frontend/src/app/app.ts b/apps/frontend/src/app/app.ts index 2e4aea3..7826492 100644 --- a/apps/frontend/src/app/app.ts +++ b/apps/frontend/src/app/app.ts @@ -3,12 +3,10 @@ import { RouterModule } from '@angular/router'; import { HeaderComponent } from './components/header/header.component'; import { FooterComponent } from './components/footer/footer.component'; import { ToastComponent } from './components/toast/toast.component'; -import { PwaInstallComponent } from './components/pwa-install/pwa-install.component'; import { AnalyticsService } from './services/analytics.service'; -import { PwaService } from './services/pwa.service'; @Component({ - imports: [RouterModule, HeaderComponent, FooterComponent, ToastComponent, PwaInstallComponent], + imports: [RouterModule, HeaderComponent, FooterComponent, ToastComponent], selector: 'app-root', templateUrl: './app.html', styleUrl: './app.scss', @@ -16,10 +14,8 @@ import { PwaService } from './services/pwa.service'; export class App implements OnInit { protected title = 'Naomi\'s Library'; private analytics = inject(AnalyticsService); - private pwa = inject(PwaService); ngOnInit(): void { this.analytics.initialise(); - // PWA service automatically initializes on construction } } diff --git a/apps/frontend/src/app/components/pwa-install/pwa-install.component.ts b/apps/frontend/src/app/components/pwa-install/pwa-install.component.ts deleted file mode 100644 index 1b70ba9..0000000 --- a/apps/frontend/src/app/components/pwa-install/pwa-install.component.ts +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @copyright 2026 NHCarrigan - * @license Naomi's Public License - * @author Hikari - */ - -import { Component, inject } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { PwaService } from '../../services/pwa.service'; - -@Component({ - selector: 'app-pwa-install', - standalone: true, - imports: [CommonModule], - template: ` - @if (pwaService.isInstallable() && !dismissed) { -
-
-
📱
-
-

Install Naomi's Library

-

Add to your home screen for quick access and offline support!

-
-
-
- - -
-
- } - `, - styles: [` - .install-banner { - position: fixed; - bottom: 1rem; - left: 50%; - transform: translateX(-50%); - background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); - border: 2px solid #9d4edd; - border-radius: 12px; - padding: 1.5rem; - max-width: 500px; - width: calc(100% - 2rem); - box-shadow: 0 8px 32px rgba(157, 78, 221, 0.3); - z-index: 1000; - animation: slideUp 0.3s ease-out; - } - - @keyframes slideUp { - from { - transform: translateX(-50%) translateY(100px); - opacity: 0; - } - to { - transform: translateX(-50%) translateY(0); - opacity: 1; - } - } - - .install-content { - display: flex; - align-items: center; - gap: 1rem; - margin-bottom: 1rem; - } - - .install-icon { - font-size: 2.5rem; - flex-shrink: 0; - } - - .install-text h3 { - margin: 0 0 0.25rem 0; - color: #9d4edd; - font-size: 1.1rem; - } - - .install-text p { - margin: 0; - color: #b0b0b0; - font-size: 0.9rem; - } - - .install-actions { - display: flex; - gap: 0.75rem; - justify-content: flex-end; - } - - .btn-install, - .btn-dismiss { - padding: 0.75rem 1.5rem; - border: none; - border-radius: 8px; - font-size: 0.9rem; - font-weight: 600; - cursor: pointer; - transition: all 0.2s; - } - - .btn-install { - background: linear-gradient(135deg, #9d4edd 0%, #c77dff 100%); - color: white; - } - - .btn-install:hover { - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(157, 78, 221, 0.4); - } - - .btn-dismiss { - background: transparent; - color: #9d4edd; - border: 1px solid #9d4edd; - } - - .btn-dismiss:hover { - background: rgba(157, 78, 221, 0.1); - } - - @media (max-width: 600px) { - .install-banner { - bottom: 0; - left: 0; - right: 0; - transform: none; - max-width: none; - width: 100%; - border-radius: 12px 12px 0 0; - border-bottom: none; - } - - @keyframes slideUp { - from { - transform: translateY(100%); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } - } - - .install-content { - flex-direction: column; - text-align: center; - } - - .install-actions { - flex-direction: column-reverse; - } - - .btn-install, - .btn-dismiss { - width: 100%; - } - } - `] -}) -export class PwaInstallComponent { - protected pwaService = inject(PwaService); - protected dismissed = false; - - protected async install(): Promise { - const result = await this.pwaService.promptInstall(); - if (result) { - this.dismissed = true; - } - } - - protected dismiss(): void { - this.dismissed = true; - // Remember dismissal in session storage - sessionStorage.setItem('pwa-install-dismissed', 'true'); - } -} diff --git a/apps/frontend/src/app/services/pwa.service.ts b/apps/frontend/src/app/services/pwa.service.ts deleted file mode 100644 index df24ae4..0000000 --- a/apps/frontend/src/app/services/pwa.service.ts +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @copyright 2026 NHCarrigan - * @license Naomi's Public License - * @author Hikari - */ - -import { Injectable, signal } from '@angular/core'; - -@Injectable({ - providedIn: 'root' -}) -export class PwaService { - public promptEvent = signal(null); - public isInstallable = signal(false); - public isInstalled = signal(false); - - constructor() { - this.init(); - } - - private init(): void { - // Check if already installed - if (window.matchMedia('(display-mode: standalone)').matches) { - this.isInstalled.set(true); - } - - // Listen for beforeinstallprompt event - window.addEventListener('beforeinstallprompt', (event: Event) => { - event.preventDefault(); - this.promptEvent.set(event); - this.isInstallable.set(true); - }); - - // Listen for app installed event - window.addEventListener('appinstalled', () => { - this.isInstalled.set(true); - this.isInstallable.set(false); - this.promptEvent.set(null); - }); - - // Register service worker - if ('serviceWorker' in navigator) { - window.addEventListener('load', () => { - navigator.serviceWorker - .register('/service-worker.js') - .then((registration) => { - console.log('[PWA] Service Worker registered:', registration.scope); - - // Check for updates periodically - setInterval(() => { - registration.update(); - }, 60000); // Check every minute - - // Listen for updates - registration.addEventListener('updatefound', () => { - const newWorker = registration.installing; - if (newWorker) { - newWorker.addEventListener('statechange', () => { - if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { - // New service worker available - console.log('[PWA] New version available! Refresh to update.'); - // Optionally show a notification to the user - } - }); - } - }); - }) - .catch((error) => { - console.error('[PWA] Service Worker registration failed:', error); - }); - }); - } - } - - public async promptInstall(): Promise { - const event = this.promptEvent(); - if (!event) { - return false; - } - - // Show the install prompt - event.prompt(); - - // Wait for the user's response - const choiceResult = await event.userChoice; - - if (choiceResult.outcome === 'accepted') { - console.log('[PWA] User accepted the install prompt'); - this.promptEvent.set(null); - this.isInstallable.set(false); - return true; - } else { - console.log('[PWA] User dismissed the install prompt'); - return false; - } - } - - public clearCache(): void { - if ('serviceWorker' in navigator && navigator.serviceWorker.controller) { - navigator.serviceWorker.controller.postMessage({ - type: 'CLEAR_CACHE' - }); - } - } -} diff --git a/apps/frontend/src/index.html b/apps/frontend/src/index.html index 8d8b94b..6c2e516 100644 --- a/apps/frontend/src/index.html +++ b/apps/frontend/src/index.html @@ -8,11 +8,6 @@ - - - - -