From 9bdb99739454e01a2ee3ea58f7d7b8d923e3781b Mon Sep 17 00:00:00 2001 From: Till JS Date: Sun, 22 Mar 2026 18:16:43 +0100 Subject: [PATCH] refactor(pwa): replace custom service workers with Vite PWA plugin and centralize offline page Remove hand-written sw.js, offline.html, and manifest.json from todo/skilltree/zitare web apps in favor of the Workbox-based service worker generated by @vite-pwa/sveltekit. This fixes an issue where the custom SW could get stuck serving the offline fallback page even when the server was reachable. Also extracts the duplicated offline page (~80 lines each across 19 apps) into a shared OfflinePage component in @manacore/shared-ui with 3 props (appName, offlineMessage, accentColor), reducing each app's offline route to an 8-line wrapper. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 99 +------- .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 107 +------- .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 81 +------ .../apps/web/src/routes/offline/+page.svelte | 81 +------ apps/skilltree/apps/web/package.json | 1 + apps/skilltree/apps/web/src/app.html | 4 - .../apps/web/src/routes/offline/+page.svelte | 81 +------ apps/skilltree/apps/web/static/manifest.json | 21 -- .../apps/web/src/routes/offline/+page.svelte | 109 +-------- apps/todo/apps/web/src/app.html | 11 +- .../apps/web/src/routes/(app)/+layout.svelte | 25 -- .../apps/web/src/routes/offline/+page.svelte | 81 +------ apps/todo/apps/web/static/manifest.json | 71 ------ apps/todo/apps/web/static/offline.html | 228 ------------------ apps/todo/apps/web/static/sw.js | 147 ----------- apps/todo/apps/web/vite.config.ts | 26 +- apps/zitare/apps/web/src/app.html | 1 - .../apps/web/src/routes/offline/+page.svelte | 81 +------ apps/zitare/apps/web/static/manifest.json | 16 -- packages/shared-ui/src/index.ts | 1 + .../shared-ui/src/pages/OfflinePage.svelte | 119 +++++++++ pnpm-lock.yaml | 3 + 33 files changed, 262 insertions(+), 2023 deletions(-) delete mode 100644 apps/skilltree/apps/web/static/manifest.json delete mode 100644 apps/todo/apps/web/static/manifest.json delete mode 100644 apps/todo/apps/web/static/offline.html delete mode 100644 apps/todo/apps/web/static/sw.js delete mode 100644 apps/zitare/apps/web/static/manifest.json create mode 100644 packages/shared-ui/src/pages/OfflinePage.svelte diff --git a/apps/calendar/apps/web/src/routes/offline/+page.svelte b/apps/calendar/apps/web/src/routes/offline/+page.svelte index 36adfed8e..76a8833c3 100644 --- a/apps/calendar/apps/web/src/routes/offline/+page.svelte +++ b/apps/calendar/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Calendar - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Deine Termine werden lokal gespeichert und sind offline verfügbar. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/chat/apps/web/src/routes/offline/+page.svelte b/apps/chat/apps/web/src/routes/offline/+page.svelte index 75e882d8f..002eacbf0 100644 --- a/apps/chat/apps/web/src/routes/offline/+page.svelte +++ b/apps/chat/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Chat - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Chat benötigt eine Internetverbindung, um Nachrichten zu senden. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/clock/apps/web/src/routes/offline/+page.svelte b/apps/clock/apps/web/src/routes/offline/+page.svelte index a92deb44f..688302729 100644 --- a/apps/clock/apps/web/src/routes/offline/+page.svelte +++ b/apps/clock/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Clock - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Die Uhr funktioniert auch offline - Timer und Stoppuhr sind verfügbar. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/contacts/apps/web/src/routes/offline/+page.svelte b/apps/contacts/apps/web/src/routes/offline/+page.svelte index a7201a22d..e470a41ca 100644 --- a/apps/contacts/apps/web/src/routes/offline/+page.svelte +++ b/apps/contacts/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Contacts - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Kontakte benötigt eine Internetverbindung für Synchronisierung. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/context/apps/web/src/routes/offline/+page.svelte b/apps/context/apps/web/src/routes/offline/+page.svelte index 0e0e9125b..5edc1aa8f 100644 --- a/apps/context/apps/web/src/routes/offline/+page.svelte +++ b/apps/context/apps/web/src/routes/offline/+page.svelte @@ -1,96 +1,9 @@ - - Offline - Context - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Einige Funktionen sind offline nicht verfügbar. Bitte überprüfe deine Internetverbindung. - {/if} -

- - {#if !isOnline} -
- - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/manacore/apps/web/src/routes/offline/+page.svelte b/apps/manacore/apps/web/src/routes/offline/+page.svelte index a4099a75b..645202281 100644 --- a/apps/manacore/apps/web/src/routes/offline/+page.svelte +++ b/apps/manacore/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - ManaCore - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - ManaCore benötigt eine Internetverbindung. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/manadeck/apps/web/src/routes/offline/+page.svelte b/apps/manadeck/apps/web/src/routes/offline/+page.svelte index bf53d0b27..c230e7254 100644 --- a/apps/manadeck/apps/web/src/routes/offline/+page.svelte +++ b/apps/manadeck/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - ManaDeck - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - ManaDeck benötigt eine Internetverbindung für deine Kartendecks. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/matrix/apps/web/src/routes/offline/+page.svelte b/apps/matrix/apps/web/src/routes/offline/+page.svelte index c01851a05..6001f0198 100644 --- a/apps/matrix/apps/web/src/routes/offline/+page.svelte +++ b/apps/matrix/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Matrix - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Matrix benötigt eine Internetverbindung für Nachrichten. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/mukke/apps/web/src/routes/offline/+page.svelte b/apps/mukke/apps/web/src/routes/offline/+page.svelte index 75ac35d68..aec9d7ece 100644 --- a/apps/mukke/apps/web/src/routes/offline/+page.svelte +++ b/apps/mukke/apps/web/src/routes/offline/+page.svelte @@ -1,104 +1,9 @@ - - Offline - Mukke - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Mukke benötigt eine Internetverbindung für Audio. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/nutriphi/apps/web/src/routes/offline/+page.svelte b/apps/nutriphi/apps/web/src/routes/offline/+page.svelte index 196a195ee..0f5551298 100644 --- a/apps/nutriphi/apps/web/src/routes/offline/+page.svelte +++ b/apps/nutriphi/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - NutriPhi - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - NutriPhi benötigt eine Internetverbindung für Analysen. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/photos/apps/web/src/routes/offline/+page.svelte b/apps/photos/apps/web/src/routes/offline/+page.svelte index ff1e4d574..624f20ee6 100644 --- a/apps/photos/apps/web/src/routes/offline/+page.svelte +++ b/apps/photos/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Photos - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Photos benötigt eine Internetverbindung für deine Fotos. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/picture/apps/web/src/routes/offline/+page.svelte b/apps/picture/apps/web/src/routes/offline/+page.svelte index 30febdf61..c926d4d7e 100644 --- a/apps/picture/apps/web/src/routes/offline/+page.svelte +++ b/apps/picture/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Picture - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Picture benötigt eine Internetverbindung, um Bilder zu generieren. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/planta/apps/web/src/routes/offline/+page.svelte b/apps/planta/apps/web/src/routes/offline/+page.svelte index 707073996..f54465f11 100644 --- a/apps/planta/apps/web/src/routes/offline/+page.svelte +++ b/apps/planta/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Planta - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Planta benötigt eine Internetverbindung für Pflegetipps. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/presi/apps/web/src/routes/offline/+page.svelte b/apps/presi/apps/web/src/routes/offline/+page.svelte index fd9c4d07a..83a30c8f5 100644 --- a/apps/presi/apps/web/src/routes/offline/+page.svelte +++ b/apps/presi/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Presi - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Presi benötigt eine Internetverbindung für Präsentationen. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/questions/apps/web/src/routes/offline/+page.svelte b/apps/questions/apps/web/src/routes/offline/+page.svelte index c2a6e4edf..51bdb64cc 100644 --- a/apps/questions/apps/web/src/routes/offline/+page.svelte +++ b/apps/questions/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Questions - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Questions benötigt eine Internetverbindung für Antworten. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/skilltree/apps/web/package.json b/apps/skilltree/apps/web/package.json index 5f282e8a4..9f23f2a7b 100644 --- a/apps/skilltree/apps/web/package.json +++ b/apps/skilltree/apps/web/package.json @@ -42,6 +42,7 @@ "@manacore/shared-icons": "workspace:*", "@manacore/shared-tailwind": "workspace:*", "@manacore/shared-theme": "workspace:*", + "@manacore/shared-ui": "workspace:^", "@manacore/shared-utils": "workspace:*", "idb": "^8.0.0", "svelte-i18n": "^4.0.1", diff --git a/apps/skilltree/apps/web/src/app.html b/apps/skilltree/apps/web/src/app.html index ffd7ecba8..2ca7377f4 100644 --- a/apps/skilltree/apps/web/src/app.html +++ b/apps/skilltree/apps/web/src/app.html @@ -7,12 +7,8 @@ - - - - diff --git a/apps/skilltree/apps/web/src/routes/offline/+page.svelte b/apps/skilltree/apps/web/src/routes/offline/+page.svelte index 5560f8669..e89183093 100644 --- a/apps/skilltree/apps/web/src/routes/offline/+page.svelte +++ b/apps/skilltree/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - SkillTree - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Deine Skills werden lokal gespeichert und sind offline verfügbar. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/skilltree/apps/web/static/manifest.json b/apps/skilltree/apps/web/static/manifest.json deleted file mode 100644 index d7d1624a9..000000000 --- a/apps/skilltree/apps/web/static/manifest.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "SkillTree", - "short_name": "SkillTree", - "description": "Track your skills like a game. Level up in real life.", - "start_url": "/", - "display": "standalone", - "background_color": "#111827", - "theme_color": "#10b981", - "icons": [ - { - "src": "/icons/icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/icons/icon-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] -} diff --git a/apps/storage/apps/web/src/routes/offline/+page.svelte b/apps/storage/apps/web/src/routes/offline/+page.svelte index d075bbc25..b64455de3 100644 --- a/apps/storage/apps/web/src/routes/offline/+page.svelte +++ b/apps/storage/apps/web/src/routes/offline/+page.svelte @@ -1,106 +1,9 @@ - - Offline - Storage - - -
-
-
- -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Storage benötigt eine Internetverbindung für Cloud-Dateien. Kürzlich besuchte Seiten sind - möglicherweise noch verfügbar. - {/if} -

- - {#if !isOnline} -
- - - -
- {:else} -
- - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/todo/apps/web/src/app.html b/apps/todo/apps/web/src/app.html index a164e2dda..ab2442430 100644 --- a/apps/todo/apps/web/src/app.html +++ b/apps/todo/apps/web/src/app.html @@ -8,22 +8,13 @@ - - - - + - - - - - - Todo %sveltekit.head% diff --git a/apps/todo/apps/web/src/routes/(app)/+layout.svelte b/apps/todo/apps/web/src/routes/(app)/+layout.svelte index 3ef9dc01c..92a8f8c65 100644 --- a/apps/todo/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/todo/apps/web/src/routes/(app)/+layout.svelte @@ -279,31 +279,6 @@ } catch { // localStorage not available } - - // Register Service Worker for PWA - if ('serviceWorker' in navigator) { - try { - const registration = await navigator.serviceWorker.register('/sw.js', { - scope: '/', - }); - console.log('Todo PWA: Service Worker registered', registration.scope); - - // Check for updates - registration.addEventListener('updatefound', () => { - const newWorker = registration.installing; - if (newWorker) { - newWorker.addEventListener('statechange', () => { - if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { - // New version available - console.log('Todo PWA: New version available'); - } - }); - } - }); - } catch (error) { - console.error('Todo PWA: Service Worker registration failed', error); - } - } }); diff --git a/apps/todo/apps/web/src/routes/offline/+page.svelte b/apps/todo/apps/web/src/routes/offline/+page.svelte index 4d8069d3d..424257895 100644 --- a/apps/todo/apps/web/src/routes/offline/+page.svelte +++ b/apps/todo/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Todo - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Deine Aufgaben werden lokal gespeichert und sind offline verfügbar. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/todo/apps/web/static/manifest.json b/apps/todo/apps/web/static/manifest.json deleted file mode 100644 index 5afff146a..000000000 --- a/apps/todo/apps/web/static/manifest.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "name": "Todo - Aufgabenverwaltung", - "short_name": "Todo", - "description": "Aufgaben und Projekte verwalten mit Kanban-Board, Subtasks und mehr", - "start_url": "/", - "scope": "/", - "display": "standalone", - "background_color": "#ffffff", - "theme_color": "#8b5cf6", - "orientation": "any", - "categories": ["productivity", "utilities"], - "lang": "de", - "dir": "ltr", - "icons": [ - { - "src": "/icons/icon.svg", - "sizes": "any", - "type": "image/svg+xml", - "purpose": "any" - }, - { - "src": "/icons/icon.svg", - "sizes": "any", - "type": "image/svg+xml", - "purpose": "maskable" - } - ], - "shortcuts": [ - { - "name": "Neue Aufgabe", - "short_name": "Neu", - "description": "Neue Aufgabe erstellen", - "url": "/?action=new", - "icons": [ - { - "src": "/icons/icon.svg", - "sizes": "any", - "type": "image/svg+xml" - } - ] - }, - { - "name": "Kanban Board", - "short_name": "Kanban", - "description": "Kanban-Ansicht öffnen", - "url": "/kanban", - "icons": [ - { - "src": "/icons/icon.svg", - "sizes": "any", - "type": "image/svg+xml" - } - ] - }, - { - "name": "Einstellungen", - "short_name": "Settings", - "description": "App-Einstellungen öffnen", - "url": "/settings", - "icons": [ - { - "src": "/icons/icon.svg", - "sizes": "any", - "type": "image/svg+xml" - } - ] - } - ], - "screenshots": [], - "prefer_related_applications": false -} diff --git a/apps/todo/apps/web/static/offline.html b/apps/todo/apps/web/static/offline.html deleted file mode 100644 index 7b932041a..000000000 --- a/apps/todo/apps/web/static/offline.html +++ /dev/null @@ -1,228 +0,0 @@ - - - - - - Offline - Todo - - - -
-
- - - -
- -

Du bist offline

-

Keine Internetverbindung. Sobald du wieder online bist, kannst du deine Aufgaben verwalten.

- -
- - Verbindung wird gesucht... -
- - - -
-

Was du tun kannst

-
    -
  • Überprüfe deine WLAN-Verbindung
  • -
  • Prüfe deine mobilen Daten
  • -
  • Versuche es in einigen Sekunden erneut
  • -
-
-
- - - - diff --git a/apps/todo/apps/web/static/sw.js b/apps/todo/apps/web/static/sw.js deleted file mode 100644 index fba14179a..000000000 --- a/apps/todo/apps/web/static/sw.js +++ /dev/null @@ -1,147 +0,0 @@ -const CACHE_NAME = 'todo-v3'; -const OFFLINE_URL = '/offline.html'; - -// Assets, die immer gecacht werden sollen -const STATIC_CACHE_URLS = ['/', '/offline.html', '/icons/icon.svg', '/manifest.json']; - -// Cache-Strategien für verschiedene Ressourcen -const CACHE_STRATEGIES = { - // Netzwerk zuerst, dann Cache (für HTML/Navigation) - networkFirst: [/\/$/, /\.html$/, /^\/kanban/, /^\/settings/, /^\/mana/, /^\/feedback/], - // Cache zuerst, dann Netzwerk (für Assets) - nur für gebaute Assets, nicht /src/ - cacheFirst: [ - /\/_app\//, // SvelteKit gebaute Assets - /\.woff2?$/, - /\.ttf$/, - /\.otf$/, - /\.ico$/, - ], - // Nur Netzwerk (für API-Calls und Dev-Server) - networkOnly: [/\/api\//, /^\/src\//, /^\/@/, /^\/node_modules\//], -}; - -// Service Worker Installation -self.addEventListener('install', (event) => { - event.waitUntil( - caches - .open(CACHE_NAME) - .then((cache) => { - console.log('Todo Service Worker: Caching static assets'); - return cache.addAll(STATIC_CACHE_URLS); - }) - .then(() => self.skipWaiting()) - ); -}); - -// Service Worker Aktivierung -self.addEventListener('activate', (event) => { - event.waitUntil( - caches - .keys() - .then((cacheNames) => { - return Promise.all( - cacheNames - .filter((cacheName) => cacheName.startsWith('todo-') && cacheName !== CACHE_NAME) - .map((cacheName) => caches.delete(cacheName)) - ); - }) - .then(() => self.clients.claim()) - ); -}); - -// Fetch-Event Handler -self.addEventListener('fetch', (event) => { - const { request } = event; - const url = new URL(request.url); - - // Ignoriere Chrome Extension Requests - if (url.protocol === 'chrome-extension:') { - return; - } - - // Ignoriere Cross-Origin Requests (z.B. Backend API) - if (url.origin !== self.location.origin) { - return; - } - - // Bestimme die Cache-Strategie - const strategy = getStrategy(url.pathname); - - if (strategy === 'networkFirst') { - event.respondWith(networkFirst(request)); - } else if (strategy === 'cacheFirst') { - event.respondWith(cacheFirst(request)); - } else if (strategy === 'networkOnly') { - event.respondWith(networkOnly(request)); - } else { - // Standard: Network First - event.respondWith(networkFirst(request)); - } -}); - -// Cache-Strategien Implementierung -async function networkFirst(request) { - try { - const networkResponse = await fetch(request); - if (networkResponse.ok) { - const cache = await caches.open(CACHE_NAME); - cache.put(request, networkResponse.clone()); - } - return networkResponse; - } catch (error) { - const cachedResponse = await caches.match(request); - if (cachedResponse) { - return cachedResponse; - } - - // Wenn es eine Navigation ist und wir offline sind, zeige die Offline-Seite - if (request.mode === 'navigate') { - const offlineResponse = await caches.match(OFFLINE_URL); - if (offlineResponse) { - return offlineResponse; - } - } - - throw error; - } -} - -async function cacheFirst(request) { - const cachedResponse = await caches.match(request); - if (cachedResponse) { - return cachedResponse; - } - - try { - const networkResponse = await fetch(request); - if (networkResponse.ok) { - const cache = await caches.open(CACHE_NAME); - cache.put(request, networkResponse.clone()); - } - return networkResponse; - } catch (error) { - console.error('Todo SW: Fetch failed:', error); - throw error; - } -} - -async function networkOnly(request) { - return fetch(request); -} - -// Hilfsfunktion zur Bestimmung der Cache-Strategie -function getStrategy(pathname) { - for (const [strategy, patterns] of Object.entries(CACHE_STRATEGIES)) { - if (patterns.some((pattern) => pattern.test(pathname))) { - return strategy; - } - } - return 'networkFirst'; -} - -// Message Handler für Updates -self.addEventListener('message', (event) => { - if (event.data && event.data.type === 'SKIP_WAITING') { - self.skipWaiting(); - } -}); diff --git a/apps/todo/apps/web/vite.config.ts b/apps/todo/apps/web/vite.config.ts index 33fc11fcc..0e4bac7ff 100644 --- a/apps/todo/apps/web/vite.config.ts +++ b/apps/todo/apps/web/vite.config.ts @@ -12,10 +12,30 @@ export default defineConfig({ sveltekit(), SvelteKitPWA( createPWAConfig({ - name: 'Todo - Aufgaben', + name: 'Todo - Aufgabenverwaltung', shortName: 'Todo', - description: 'Aufgaben und Projekte verwalten', - themeColor: '#10b981', + description: 'Aufgaben und Projekte verwalten mit Kanban-Board, Subtasks und mehr', + themeColor: '#8b5cf6', + shortcuts: [ + { + name: 'Neue Aufgabe', + short_name: 'Neu', + description: 'Neue Aufgabe erstellen', + url: '/?action=new', + }, + { + name: 'Kanban Board', + short_name: 'Kanban', + description: 'Kanban-Ansicht öffnen', + url: '/kanban', + }, + { + name: 'Einstellungen', + short_name: 'Settings', + description: 'App-Einstellungen öffnen', + url: '/settings', + }, + ], }) ), ], diff --git a/apps/zitare/apps/web/src/app.html b/apps/zitare/apps/web/src/app.html index 9aa783ac2..e4f70b844 100644 --- a/apps/zitare/apps/web/src/app.html +++ b/apps/zitare/apps/web/src/app.html @@ -6,7 +6,6 @@ - Zitare %sveltekit.head% diff --git a/apps/zitare/apps/web/src/routes/offline/+page.svelte b/apps/zitare/apps/web/src/routes/offline/+page.svelte index 76429d77b..47ab4e10e 100644 --- a/apps/zitare/apps/web/src/routes/offline/+page.svelte +++ b/apps/zitare/apps/web/src/routes/offline/+page.svelte @@ -1,78 +1,9 @@ - - Offline - Zitare - - -
-
-
- - - - -
- -

- {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} -

- -

- {#if isOnline} - Du wirst gleich weitergeleitet... - {:else} - Zitare benötigt eine Internetverbindung für neue Zitate. - {/if} -

- - {#if !isOnline} -
- - - - - Zur Startseite - - - -
- {:else} -
- - - - - Weiterleitung... -
- {/if} -
-
+ diff --git a/apps/zitare/apps/web/static/manifest.json b/apps/zitare/apps/web/static/manifest.json deleted file mode 100644 index cea7176de..000000000 --- a/apps/zitare/apps/web/static/manifest.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "Zitare", - "short_name": "Zitare", - "description": "Inspirierende Zitate jeden Tag", - "start_url": "/", - "display": "standalone", - "background_color": "#1a1a2e", - "theme_color": "#8b5cf6", - "icons": [ - { - "src": "/favicon.png", - "sizes": "192x192", - "type": "image/png" - } - ] -} diff --git a/packages/shared-ui/src/index.ts b/packages/shared-ui/src/index.ts index aa4414d68..23a588fea 100644 --- a/packages/shared-ui/src/index.ts +++ b/packages/shared-ui/src/index.ts @@ -155,6 +155,7 @@ export type { QuickInputItem, QuickAction, CreatePreview, InputBarSettings } fro // Pages export { default as AppsPage } from './pages/AppsPage.svelte'; +export { default as OfflinePage } from './pages/OfflinePage.svelte'; // Charts - Statistics Visualization export { diff --git a/packages/shared-ui/src/pages/OfflinePage.svelte b/packages/shared-ui/src/pages/OfflinePage.svelte new file mode 100644 index 000000000..30948268f --- /dev/null +++ b/packages/shared-ui/src/pages/OfflinePage.svelte @@ -0,0 +1,119 @@ + + + + Offline - {appName} + + +
+
+
+ + + + +
+ +

+ {isOnline ? 'Verbindung wiederhergestellt!' : 'Du bist offline'} +

+ +

+ {#if isOnline} + Du wirst gleich weitergeleitet... + {:else} + {offlineMessage} + {/if} +

+ + {#if !isOnline} +
+ { + e.currentTarget.style.filter = 'brightness(0.85)'; + }} + onmouseleave={(e) => { + e.currentTarget.style.filter = ''; + }} + > + + + + Zur Startseite + + + +
+ {:else} +
+ + + + + Weiterleitung... +
+ {/if} +
+
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3d0361a3d..277715191 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4959,6 +4959,9 @@ importers: '@manacore/shared-theme': specifier: workspace:* version: link:../../../../packages/shared-theme + '@manacore/shared-ui': + specifier: workspace:^ + version: link:../../../../packages/shared-ui '@manacore/shared-utils': specifier: workspace:* version: link:../../../../packages/shared-utils