From 41e88e0acf6e6fa79f22f961784beaad06119663 Mon Sep 17 00:00:00 2001 From: Ulas Date: Sun, 29 Mar 2026 15:35:01 +0200 Subject: [PATCH] Add PWA native feel: manifest, meta tags, install prompt, SW optimization, dynamic theme-color Configure manifest.json with scope, maskable icons, and categories. Add iOS/Android meta tags for standalone behavior. Create pwa.css for native touch/scroll handling and safe area insets. Add oikos-install-prompt Web Component with Chrome install flow and iOS guidance. Optimize service worker with network-first navigation and expanded precache (v19). Add dynamic theme-color per route and modal overlay dimming in standalone mode. Generate placeholder icons via sharp script. Co-Authored-By: Claude Opus 4.6 --- package-lock.json | 1191 ++++++++++----------- package.json | 5 +- public/components/modal.js | 13 + public/components/oikos-install-prompt.js | 331 ++++++ public/icons/apple-touch-icon.png | Bin 12204 -> 3487 bytes public/icons/favicon-32.png | Bin 1411 -> 595 bytes public/icons/icon-192.png | Bin 13318 -> 3753 bytes public/icons/icon-512.png | Bin 47327 -> 13471 bytes public/icons/icon-maskable-192.png | Bin 0 -> 2474 bytes public/icons/icon-maskable-512.png | Bin 0 -> 9989 bytes public/index.html | 21 +- public/manifest.json | 47 +- public/router.js | 73 +- public/styles/pwa.css | 65 ++ public/sw-register.js | 12 +- public/sw.js | 49 +- scripts/generate-icons.js | 88 ++ 17 files changed, 1206 insertions(+), 689 deletions(-) create mode 100644 public/components/oikos-install-prompt.js create mode 100644 public/icons/icon-maskable-192.png create mode 100644 public/icons/icon-maskable-512.png create mode 100644 public/styles/pwa.css create mode 100644 scripts/generate-icons.js diff --git a/package-lock.json b/package-lock.json index 62d2696..1920e29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,10 +7,10 @@ "": { "name": "oikos", "version": "1.0.0", + "license": "MIT", "dependencies": { "bcrypt": "^5.1.1", "better-sqlite3": "^9.6.0", - "connect-sqlite3": "^0.9.15", "dotenv": "^16.4.7", "express": "^4.21.2", "express-rate-limit": "^7.5.0", @@ -18,6 +18,9 @@ "helmet": "^8.0.0", "node-fetch": "^3.3.2" }, + "devDependencies": { + "sharp": "^0.34.5" + }, "engines": { "node": ">=20.0.0" }, @@ -26,12 +29,506 @@ "tsdav": "^2.0.10" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "node_modules/@emnapi/runtime": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", + "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", + "dev": true, "license": "MIT", - "optional": true + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.11", @@ -73,42 +570,6 @@ } } }, - "node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "license": "MIT", - "optional": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -163,33 +624,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "license": "MIT", - "optional": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -387,36 +821,6 @@ "node": ">= 0.8" } }, - "node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -455,16 +859,6 @@ "node": ">=10" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=6" - } - }, "node_modules/color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", @@ -480,17 +874,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, - "node_modules/connect-sqlite3": { - "version": "0.9.16", - "resolved": "https://registry.npmjs.org/connect-sqlite3/-/connect-sqlite3-0.9.16.tgz", - "integrity": "sha512-2gqo0QmcBBL8p8+eqpBETn7RgM/PaoKvpQGl8PfjEgwlr0VuMYNMxRJRrRCo3KR3fxMYeSsCw2tGNG0JKN9Nvg==", - "dependencies": { - "sqlite3": "^5.0.2" - }, - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -703,6 +1086,7 @@ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "iconv-lite": "^0.6.2" } @@ -713,6 +1097,7 @@ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -729,23 +1114,6 @@ "once": "^1.4.0" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "license": "MIT", - "optional": true - }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -1260,13 +1628,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC", - "optional": true - }, "node_modules/gtoken": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", @@ -1320,13 +1681,6 @@ "node": ">=18.0.0" } }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "license": "BSD-2-Clause", - "optional": true - }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -1347,46 +1701,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "license": "MIT", - "optional": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-proxy-agent/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "optional": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/http-proxy-agent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT", - "optional": true - }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -1423,16 +1737,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1465,33 +1769,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "license": "ISC", - "optional": true - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1515,16 +1792,6 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, - "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 12" - } - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -1543,13 +1810,6 @@ "node": ">=8" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "license": "MIT", - "optional": true - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -1563,13 +1823,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC", - "optional": true - }, "node_modules/json-bigint": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", @@ -1603,19 +1856,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -1640,34 +1880,6 @@ "semver": "bin/semver.js" } }, - "node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "license": "ISC", - "optional": true, - "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -1782,76 +1994,6 @@ "node": ">=8" } }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "license": "MIT", - "optional": true, - "dependencies": { - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "optionalDependencies": { - "encoding": "^0.1.12" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", @@ -1960,84 +2102,6 @@ "url": "https://opencollective.com/node-fetch" } }, - "node_modules/node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "license": "MIT", - "optional": true, - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/node-gyp/node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -2117,22 +2181,6 @@ "wrappy": "1" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2184,27 +2232,6 @@ "node": ">=10" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "license": "ISC", - "optional": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "license": "MIT", - "optional": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2305,16 +2332,6 @@ "node": ">= 6" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -2436,6 +2453,51 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -2559,115 +2621,6 @@ "simple-concat": "^1.0.0" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "license": "MIT", - "optional": true, - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "optional": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socks-proxy-agent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT", - "optional": true - }, - "node_modules/sqlite3": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", - "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^7.0.0", - "prebuild-install": "^7.1.1", - "tar": "^6.1.11" - }, - "optionalDependencies": { - "node-gyp": "8.x" - }, - "peerDependencies": { - "node-gyp": "8.x" - }, - "peerDependenciesMeta": { - "node-gyp": { - "optional": true - } - } - }, - "node_modules/sqlite3/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "license": "MIT" - }, - "node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -2838,6 +2791,14 @@ "license": "MIT", "optional": true }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -2875,26 +2836,6 @@ "node": ">= 0.8" } }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "license": "ISC", - "optional": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -2974,22 +2915,6 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "optional": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", diff --git a/package.json b/package.json index 1eaea85..6a47635 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "dependencies": { "bcrypt": "^5.1.1", "better-sqlite3": "^9.6.0", -"dotenv": "^16.4.7", + "dotenv": "^16.4.7", "express": "^4.21.2", "express-rate-limit": "^7.5.0", "express-session": "^1.18.1", @@ -33,5 +33,8 @@ "license": "MIT", "engines": { "node": ">=20.0.0" + }, + "devDependencies": { + "sharp": "^0.34.5" } } diff --git a/public/components/modal.js b/public/components/modal.js index 44f87bf..7be0742 100644 --- a/public/components/modal.js +++ b/public/components/modal.js @@ -13,6 +13,9 @@ let activeOverlay = null; let previouslyFocused = null; let focusTrapHandler = null; +// Overlay-Dimming: theme-color abdunkeln im Standalone-Modus +const OVERLAY_THEME_COLOR = '#1A1A1A'; + const FOCUSABLE = [ 'a[href]', 'button:not([disabled])', @@ -126,6 +129,11 @@ export function openModal({ title, content, onSave, onDelete, size = 'md' } = {} // Callback für Aufrufer (Form-Events binden etc.) if (typeof onSave === 'function') onSave(panel); + + // Standalone: Statusbar abdunkeln (Overlay-Effekt) + if (window.oikos?.setThemeColor) { + window.oikos.setThemeColor(OVERLAY_THEME_COLOR, OVERLAY_THEME_COLOR); + } } // -------------------------------------------------------- @@ -155,4 +163,9 @@ export function closeModal() { previouslyFocused.focus(); previouslyFocused = null; } + + // Standalone: Statusbar-Farbe zur aktuellen Route wiederherstellen + if (window.oikos?.restoreThemeColor) { + window.oikos.restoreThemeColor(); + } } diff --git a/public/components/oikos-install-prompt.js b/public/components/oikos-install-prompt.js new file mode 100644 index 0000000..c55efb8 --- /dev/null +++ b/public/components/oikos-install-prompt.js @@ -0,0 +1,331 @@ +/** + * Modul: Install-Prompt Web Component + * Zweck: Dezentes Banner für PWA-Installation (Chrome/Android) und iOS-Anleitung + * Abhängigkeiten: Design Tokens aus tokens.css (via CSS custom properties) + * + * Verhalten: + * - Chrome/Android: Fängt beforeinstallprompt ab, zeigt Install-Banner + * - iOS (Safari): Zeigt Anleitung "Zum Home-Bildschirm" + * - Standalone-Modus: Zeigt nichts an + * - Dismiss: 30 Tage via localStorage gespeichert + */ + +const DISMISS_KEY = 'oikos-install-dismissed'; +const DISMISS_DURATION_MS = 30 * 24 * 60 * 60 * 1000; // 30 Tage + +class OikosInstallPrompt extends HTMLElement { + constructor() { + super(); + this._deferredPrompt = null; + this._shadow = this.attachShadow({ mode: 'open' }); + } + + connectedCallback() { + // Bereits im Standalone-Modus — nichts anzeigen + if ( + window.matchMedia('(display-mode: standalone)').matches || + navigator.standalone === true + ) { + return; + } + + // Dismiss noch aktiv? + const dismissed = localStorage.getItem(DISMISS_KEY); + if (dismissed && Date.now() - Number(dismissed) < DISMISS_DURATION_MS) { + return; + } + + if (this._isIOS()) { + this._showIOSPrompt(); + } else { + this._listenForInstallPrompt(); + } + } + + disconnectedCallback() { + window.removeEventListener('beforeinstallprompt', this._onBeforeInstall); + } + + /** iOS Safari erkennen (kein beforeinstallprompt-Support) */ + _isIOS() { + return ( + navigator.standalone === undefined && + /iPhone|iPad/.test(navigator.userAgent) && + !window.MSStream + ); + } + + /** Chrome/Android: beforeinstallprompt abfangen */ + _listenForInstallPrompt() { + this._onBeforeInstall = (e) => { + e.preventDefault(); + this._deferredPrompt = e; + this._showBanner(false); + }; + window.addEventListener('beforeinstallprompt', this._onBeforeInstall); + } + + /** Banner rendern */ + _showBanner(isIOS) { + this._shadow.innerHTML = ''; + + const style = document.createElement('style'); + style.textContent = ` + :host { + display: block; + position: fixed; + bottom: calc(var(--nav-height-mobile, 56px) + env(safe-area-inset-bottom, 0px) + 8px); + left: var(--space-3, 12px); + right: var(--space-3, 12px); + z-index: var(--z-toast, 300); + pointer-events: none; + } + + .banner { + display: flex; + align-items: center; + gap: var(--space-3, 12px); + padding: var(--space-3, 12px) var(--space-4, 16px); + background: var(--color-surface, #fff); + border: 1px solid var(--color-border, #e8e7e2); + border-radius: var(--radius-md, 12px); + box-shadow: var(--shadow-md, 0 2px 8px rgba(0,0,0,0.08)); + pointer-events: auto; + transform: translateY(calc(100% + 20px)); + transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1); + } + + .banner--visible { + transform: translateY(0); + } + + .icon { + width: 40px; + height: 40px; + border-radius: var(--radius-sm, 8px); + flex-shrink: 0; + } + + .text { + flex: 1; + min-width: 0; + } + + .title { + font-family: var(--font-sans, system-ui); + font-size: var(--text-base, 0.875rem); + font-weight: var(--font-weight-semibold, 600); + color: var(--color-text-primary, #1c1c1a); + line-height: var(--line-height-tight, 1.25); + } + + .subtitle { + font-family: var(--font-sans, system-ui); + font-size: var(--text-sm, 0.8125rem); + color: var(--color-text-secondary, #6c6b67); + line-height: var(--line-height-base, 1.5); + margin-top: 2px; + } + + .btn-install { + flex-shrink: 0; + padding: var(--space-2, 8px) var(--space-4, 16px); + background: var(--color-btn-primary, #2554C7); + color: #fff; + border: none; + border-radius: var(--radius-sm, 8px); + font-family: var(--font-sans, system-ui); + font-size: var(--text-sm, 0.8125rem); + font-weight: var(--font-weight-semibold, 600); + cursor: pointer; + min-height: 36px; + min-width: 36px; + transition: background 0.15s ease; + } + + .btn-install:hover { + background: var(--color-btn-primary-hover, #1E429A); + } + + .btn-dismiss { + flex-shrink: 0; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + background: none; + border: none; + border-radius: var(--radius-xs, 4px); + cursor: pointer; + color: var(--color-text-tertiary, #737370); + padding: 0; + min-height: 32px; + min-width: 32px; + transition: background 0.15s ease; + } + + .btn-dismiss:hover { + background: var(--color-surface-3, #efeee9); + } + + .btn-dismiss svg { + width: 18px; + height: 18px; + } + + /* iOS share icon inline */ + .share-icon { + display: inline-block; + width: 1em; + height: 1em; + vertical-align: -0.1em; + } + + @media (min-width: 1024px) { + :host { + /* Desktop: Sidebar statt Bottom-Nav, Banner unten rechts */ + bottom: calc(var(--space-4, 16px) + env(safe-area-inset-bottom, 0px)); + left: auto; + right: var(--space-4, 16px); + max-width: 380px; + } + } + `; + + const banner = document.createElement('div'); + banner.className = 'banner'; + banner.setAttribute('role', 'alert'); + + // App-Icon + const icon = document.createElement('img'); + icon.className = 'icon'; + icon.src = '/icons/icon-192.png'; + icon.alt = 'Oikos'; + icon.width = 40; + icon.height = 40; + banner.appendChild(icon); + + // Text + const text = document.createElement('div'); + text.className = 'text'; + + const title = document.createElement('div'); + title.className = 'title'; + title.textContent = 'Oikos installieren'; + + const subtitle = document.createElement('div'); + subtitle.className = 'subtitle'; + + if (isIOS) { + // iOS: Teilen-Icon als SVG inline + subtitle.innerHTML = ''; + subtitle.append( + document.createTextNode('Tippe auf '), + this._createShareIcon(), + document.createTextNode(' → „Zum Home-Bildschirm"') + ); + } else { + subtitle.textContent = 'Zur App hinzufügen'; + } + + text.appendChild(title); + text.appendChild(subtitle); + banner.appendChild(text); + + // Install-Button (nur Chrome/Android) + if (!isIOS) { + const btn = document.createElement('button'); + btn.className = 'btn-install'; + btn.textContent = 'Installieren'; + btn.addEventListener('click', () => this._onInstallClick()); + banner.appendChild(btn); + } + + // Dismiss-Button + const dismiss = document.createElement('button'); + dismiss.className = 'btn-dismiss'; + dismiss.setAttribute('aria-label', 'Schließen'); + dismiss.innerHTML = ``; + dismiss.addEventListener('click', () => this._dismiss()); + banner.appendChild(dismiss); + + this._shadow.appendChild(style); + this._shadow.appendChild(banner); + + // Slide-in Animation nach nächstem Frame + requestAnimationFrame(() => { + requestAnimationFrame(() => { + banner.classList.add('banner--visible'); + }); + }); + } + + /** iOS Teilen-Icon (Box mit Pfeil nach oben) */ + _createShareIcon() { + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('viewBox', '0 0 24 24'); + svg.setAttribute('fill', 'none'); + svg.setAttribute('stroke', 'currentColor'); + svg.setAttribute('stroke-width', '2'); + svg.setAttribute('stroke-linecap', 'round'); + svg.setAttribute('stroke-linejoin', 'round'); + svg.classList.add('share-icon'); + + const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + path.setAttribute('d', 'M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8'); + const polyline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline'); + polyline.setAttribute('points', '16 6 12 2 8 6'); + const line = document.createElementNS('http://www.w3.org/2000/svg', 'line'); + line.setAttribute('x1', '12'); + line.setAttribute('y1', '2'); + line.setAttribute('x2', '12'); + line.setAttribute('y2', '15'); + + svg.appendChild(path); + svg.appendChild(polyline); + svg.appendChild(line); + return svg; + } + + /** Install-Button geklickt */ + async _onInstallClick() { + if (!this._deferredPrompt) return; + + try { + this._deferredPrompt.prompt(); + const result = await this._deferredPrompt.userChoice; + console.log('[oikos-install-prompt] Ergebnis:', result.outcome); + + if (result.outcome === 'accepted') { + this._remove(); + } + } catch (err) { + console.error('[oikos-install-prompt] Fehler:', err); + } + + this._deferredPrompt = null; + } + + /** Dismiss: 30 Tage merken, Banner entfernen */ + _dismiss() { + localStorage.setItem(DISMISS_KEY, String(Date.now())); + this._remove(); + } + + /** Banner mit Slide-out entfernen */ + _remove() { + const banner = this._shadow.querySelector('.banner'); + if (!banner) return; + + banner.classList.remove('banner--visible'); + banner.addEventListener('transitionend', () => this.remove(), { once: true }); + } + + /** iOS: Banner direkt anzeigen */ + _showIOSPrompt() { + this._showBanner(true); + } +} + +customElements.define('oikos-install-prompt', OikosInstallPrompt); diff --git a/public/icons/apple-touch-icon.png b/public/icons/apple-touch-icon.png index a26d81fde6c8433f70693c55fe19643cca5650ea..9b596c13cdaa22cd67d0e1dfb17596d201a09d7c 100644 GIT binary patch literal 3487 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 literal 12204 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 JPDHLkV1l`c1rGoK delta 1393 zcmV-%1&;dD1cM8ZBYy=-NklUx-yj9LGO1_w3)+-CVD3t}C%Bo0>?uL53D8 zC}EU_L0Crg5ClPzklL$3(39XpP!AeW4?RSY#X?X}gqTGbMXn~HtCHT;a(7+bz4y%T z*TbB-_uO;Oss#-UGv}O{`F?+Y=J)#@qpC{MM#f<1G#ot-rGH6?UGgDWq3XMYF5to_ z5GP}L9t&7t{w&zA7@oZ!28vXh2?V}53-ABzNr2yEr~#9ji+BPqHO@%D`FX|pef{0A zcO7iK*Pj;!@cl<&VhXIS0SC!V{UgTs2SZNNnx<6!9!;$sF2T;v{JSStfIT|~hmOP8 zRPErP=CcMaPr@5t!SE>9FHXVPtI2_B))}eE0%vflrpjs{ zqX|h!442@&V-OuV=WSyRNDhFZ{-sGt7Mw2&(%`JA=jwM+hE6EapA(Ia)*zvJ^8|2z z1C$N@iWB(qv_Ztwf#wkk9Z{?ZBUgl|?EJx+v2V5qf`6i5MA))adGWyl0JEAMAN^t| z$JT3veCeh7K`<&*DncZh0ttYrcbIzrXfndnD`Cf~0xgjzwe#TuU9FBE&pW1^;in6R zikRwk6$Ow=GoKOVrY!O~w4V#zQ+?!y4$U=KFv=)?#^ZN8S^^ym0BZ8HT zx4O`ib>$d}ZI0cKz+*Fjr`y~P!)xmcEa(s_PEk=*q}tQqh!Q!;S2=(G|d3A4a>#d7JItsXQw>Br6%=xWUeygCKrQxF-LH_OM3 zi+^Jw{V<6xM6vCIo`XjDgZM`28|W$FQK&kMA6X1K)WmUs(e$Jp`vq!kJM= zvlT`s3P}hL2hjj-LLkyi?hR4RCEq$*p?}y8*DJoXx;Oy`e}GF9psF1FUfH_B(%Y$Y zw<+zB($!WixjdMq!2wAV&cOA^+=viqUar=}1j)QLg5~pSRvMr7lGRk{7tZfA%!O(9pk*!sh#=!Z%6)DFwiFXuNhHpQPIl3QT<-c+4- zDe#o-aSki7&th7uWK;wfYyEX1rGJrBv~x+RR@Fo*DYX=oXhE01<4_N-3StVxrT|G4 zGbRBr0tHD*C;u)E_6;Nm&zgJxRfL5-P1ub~l5$ICGKHT6Pp=;nz(m@*UVYaH9>z_B z9oXkq!IC-t+BJZS<_3>?Tjqe|uB(AdEDZEEvtwg7cAyBauZP)f^>;rw#A^QmKBvR7 zXL}C=eJ!=0(@%c&ze^`ezUH@jJBR9Rfs-OJ(A&(O?L9oPrmOz%m?XO$ItD{0gpn(b zN+o-!-crImGR;<5Sd7>-*ujpC-3;`#RAa?I-U3DhklNZ200000NkvXXu0mjfn0}%R diff --git a/public/icons/icon-192.png b/public/icons/icon-192.png index 01e8ae3facbdad653fa2358c2b045334ee880166..43c0c4446de4e02e04ced50107003d567ca70993 100644 GIT binary patch literal 3753 zcmXX}c|4Tc|9@sNwq`7o(nK_o+zQE>i?KwAL`jKE_hJS$m`J9WLD?cjk}P8>B10rg zVWuo`#ZY(bOSpq57y^7c4f%_LFY$m=7s&u1i54~pkdY}504O&bOS5yKne*<%WS3^S`Zzai{J|E> zlA*(r`+fD$x{u}MsvZ@mS5*+2{U7rV<7!c5qU%7j$T>?91Um0O*~F`-BULnBMSk)< z{gQeh51SzQk5-Ytwpwtb{?3U{OzXzA`oYC|a!IFBG4;!o(Qw(5!RnJ0@pj$z*v!L; zHI@n)P55Gi_lIO$;w%yjsD~aSj*gdCe5dtE+RJ{sN^CMbU$zsA7?T{=vQ+Sn`^W(- z)qdu(T;jBxu{+Ylj8!jmQ!P}?P2DX3Ro()mzuc+UrO!or9)b6qH7^KnRLW7o#jtt9$V3kh(-^tT_>9OQUP7pqsaB3 zI~}93$8ULh@nLAjJ&}riH7_uA?AY=+QviAB78_Sz3=6U4nqI`d(kJaSLk@WaM69N}k&haK2PoqT@^-#9IUxD}#HvoYlbh=SW9r(ak;Q1F^HDC3E0T~Md2Ql}%MR+$b$%s^K zUuk@NI3(k9ob*@bQ$o4x!0ghJC>?Pq3nAljijsSlB4m1clZqUGxQ?b|Nj?9Ht0y^t zE7j=;+a~bybfD4^Ns82iV>lojLV%*+NzTd{R2ZZNK^HfWHqeM9f_-Be()LUmGjMOJ z&@LOshAW6ENPQ5RkJ)Gmp<{B9LWm3P7D6fCgpjA+p>0SpLkNwCZWDUM=7PLb{q4a? z7qHv(S)LidSL%~-BJ@HKvO^q<=Joa*Oif^WUI|NdfHKev=s-lFttW*O0z)Ey6p61Y z0tzR-X2+!N;ld^E=a<34!!@;dfn!N`nH?9X7kXi{BO-4bV%C~pT>FvJ$lJvu9M|$j z1w>Tkq=pXx0d zXis0WV5T`3>F2g=$uWN%nA1)9lbMMdn>JDL7~>x0G)UfFbfElJxsi?*lehMO{ket+ z+Pip7l+R19Pmbf1`@)o=485SvjKcs}Ws4?o29sYW@x)xF0JF38i-_Kq8rs5nYDe(TdS*Z^#aZ3rN zo-buuBl-o17g}nbV#CDlnFP}G^PP75E48`}wog^UH|f6@JtfG{do@ADje*{cb!5#^ z*^Jo~m23~Imt`y*( z=n5Eb$tmZa8`QToAP<6s)Wwl+q*T(dcUR+K!qjqN$&3CaeVQQzMzE!wIpVfEr0D(vq!}g3Cvss`{?PM8rAY3REdJT^t5Z-~+Z%bteSQ>@XFb2+gA(@J zJ>G0G-Q7pNIhm@nyvZ~Qn06Gj>Nc3PWJhp8l6*?#C7aHS zhelSTIel&G z!S^peWKtpg$y@4H7E13bxubFpinF7PC33*GMh#)!7Yszn!@;=+vFPxAWLm9pBEZS5HMMc-6fCH{5D{ z1+EgG%z@_AvIGgMErWrtJ!kdOS(#KBlS^?V+{QhOMzpQ(CDf1CyMGS`p1+tdzCbmE zSX|bJ#pT_y|2-nYkb5F%%@Mqv|6xSrG)Ad|XSVUxqsfPVCdMU9gyrwr>e{1Z+V^d5 z_2bvlE3x$-L9|U-x<=<=QrgQ{6KuRa{vKu%bq4jzIlw%IR|ov-%K=LTGCuZ>m63 ze-$IO#{ZqrtBW&-t|ZpEF)JlY>U8ZehBrdN%O^|;SIO9%P&z$ipt%q z(^+Q@Jjt!1{p1xtcLk4>gGbu!)};y?PVSU+SbK?E5vR^(A6U1or{GJ@2C>CH9T)dC zM){XMo)qW8gW!tiSNwP`kreof*qy$-(T_}%J!+FSGT?w1gSq0+jE9rv_Lru_pPYuG z^cqr>Z`}ibY59X=p_BH99~5yeXTQ{JzJksE9;v9jbNRh`=kIRxa6x~@yY}IT+v;o| zYyh0R{_s1==UQgoz5-&RLp`ZvQG!rd^j{~9i=265<$U0ci=a7$T9(+xuSiS!@DzliXDn3ON(i0V);UQprG=2z?pPs|zQbAwRhkJk3WIZFT5OOgkFjbm zqJ>?-`s=8fJHmW=AbJE**ORaws*@EG`-+WX`#VH~`pPn@c>waFo2o-kb&hHaQ>#%2 zK=Fp-Vl3rLuTT@zO^k#$Jk{W*)7rRWKmC;=d*d>n~gPF}nF5y}VVqMcAk?)%ZLK+);F zz%dYnA^Gbpl%v_rK-X3!YL;Vssab-~Sh7?Ib^UOF7XTOcrPdMYdrjP}A{1Jd2_ZOj z2BOr7)%tD$_;Ep5f_lgd=_rcS7_Hx!sABSE@iN=)r6IcPNONksC!;Hya*qN%U}O@Q zH#P@4Uwz&(GGd9vccBiQ1TPF#6d!)*A8*PGI<(c!fC~InlwsAGJ14ARN#C;Y7{{L_ zEL&nz_oG9IF_nGEPX)=*OGWErJXIUj8xR>hIzkL{_9vYdru(5<^`Oj$7gAR!zz1!prY_-LQvHuoe zIdWcVH@KjW(P#N?SvGkxJ{L;-`V(;ACQN;~GPiJzu#kL^{rVH5YEOH#OI*O+&qa-! z=X|qvl_GJ8OAW#w$f|*bA{NQCVVz{Q97m*t5qGA_#;T+NUcPvo(w+OGMzQ< z29Z}c?Yq2kKTTr~waaEdmVxWF!!Dy^j>+QVEnR!U8BEyQpSjO}4VH+$u_e#Ng`a;= ebU`~_0IPl)PU(@L4uf}3z~-cbCBxh^^8Wx_+~R5g literal 13318 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 JUfMkT{{Yba02lxO diff --git a/public/icons/icon-512.png b/public/icons/icon-512.png index 99f8a4a6e816c34c3813f5280a70b322554142c7..943377912bb5a3727a3c941c907776eea28f771c 100644 GIT binary patch literal 13471 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 diff --git a/public/icons/icon-maskable-192.png b/public/icons/icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..d99355aa724864aa76ad4672b50166dc18617e3f GIT binary patch literal 2474 zcmeHJ=U0=-9)3e25K4$AD2PDfWfzr>^diLrQBkCZ;^Gq5MF~Yzg2~d0h-gF>7EuHV zA__r>*pQ+q0xBgy7I39SDTWpy6eSSI&dc%s3-{CgFwc9=l&AdW%*>naeq_I*oSGa2 zL5c?tIC+BaE4ax@1N0mWlK~&}nFIcj5G0R-8v@G9R|S0m2b~G^^JN@)&B`68{` zRte?oW9n(Y(hWJ|l((SPC>JhYzQYVoOeS0p^1ta{rkJi}sFlnbu}9pAm#}9luZVU7@o2K zo%FF-GKy%d4)BheG9V~cR|D9s1ff)uy0J)r6S7D^8Jv!iVmK_KkV)?lu0jX0#_g0j z2y11e4S}U2Xn49%4h7H;2_cANy<}Lm&H+{(V8W`AuvJEi5p4LN5v;l!1*>j_Z5OLz z0D36O0Rj(CRajM73RabeZF?xl04$Z>1ZZ}pNyAw; zf|xdeI0WlPnDXd<;81&CI}pw}c-dn8()a{h$O*&PNKco7bJt4&tAxIdYF~lt+++Y( zxW#-Itg6nuh@I&Qv|civoXRaJ!XG%%kf|NFGj6%qH1efsP{v}v1s7N7vNoK>na#pz zs^MueJ&@S*uQdpnfF(8aU*iVxnF#8@{Te0 zlzh)(Rag#{C&RU)y_Il!ZYgUz7?Uv;uzv5QK{9T-iZO)1JLF~3-o zADS-3JdM*k+U=+7Bw6>SrOLRU5Y>tB<;vE?xb_u-F`{2d;+pN@can`)b0E=Vx&hh4=7nsLZa`UWX^&d5N2&Mm=x;qDj+%>tK)fZ8UxhL6f zzg&AdnYt)T;U@?_J&(kj?W_H=g(CLlvYrkVqOP?wI=xugjmXmU6@{#L_QXG-A1t<( ztqyw$A_UQCzvD`N)~&NZ$DY+JV0)_okJ)kS={%p5x$?jgt&87hW>>Obw`s95nsx6E zNjLHJdmVvChp(lii*8%l5=tMhVaA!VR2yP!YpHJ+QHBB8rNoSL)!X*1uD1jtZ-Urtbtb<7<3mTM7(VKb6mt;gT*4bqs856HK8 zc~fO{rdep^TB2i{xQ`U_^F&MZp2x@6J3b0Uhd26`T4u!8ehEMCb(q1^e}6@|t~C0i zULo$Oop{ZKGau!n*kM;Wr*uf45y~tb8@%1=v}e*c(VD zPXBkqMRk!mY{&0~gDW@GCkAf>U)YRe-hcHXPgE&*V}Fb;F712WAgH){?dunegmvsm z`duzy`#k?!way!rrix|l`-NtV)jjqYd#z886u|NPh_4q~?7Jl@dZ52bTK(xaYVnbc zlaz$P`>Z{qHSC>lH16i1XBU1R7^vwz3qPSD;yso_3lA4pROHyx4$Zu>UrW?o5};;g-iKf{k}>~?GS z-U+r->yJP|a?q5}uZFl1TeP^YbaknjA>xYdqt_)XHO|xw&mnLXb&Ro1NQP~pZ|RAb z-GFgZG-kW@T5UkHLc?>LepSz7Ag60o7nai3=r^|}eM7!>B=XNGP~#9iiGyHbn}}50 zp^op!2Df8j3Vc&_$x|CkzwK3w_aA<4z9c!Hm3af&jJ3>sxoL7!aE0ox;nBTqSMOso z%m1(<+^nbx=$xL@=)bLCSf*-T;XzItEjPmzqPvdn7nmHdZaAc7`Sfh|*kaAqbm79I zmQ!tU5?XkJxxiEAhfF55UhCbkO;T JQ{_H#^1nzn9>V|t literal 0 HcmV?d00001 diff --git a/public/icons/icon-maskable-512.png b/public/icons/icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..3f4186508631215ae348f03d85ac79060f0d4d0a GIT binary patch literal 9989 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 - - + + + + + + + + + + + + Oikos - + @@ -24,6 +34,7 @@ + @@ -60,6 +71,10 @@ + + + + diff --git a/public/manifest.json b/public/manifest.json index 8ebb9fd..b3006bc 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,43 +1,20 @@ { "name": "Oikos Familienplaner", "short_name": "Oikos", - "description": "Selbstgehosteter Familienplaner für Kalender, Aufgaben, Einkauf und mehr.", + "description": "Selbstgehosteter Familienplaner", "start_url": "/", + "scope": "/", "display": "standalone", - "background_color": "#F5F4F1", - "theme_color": "#2563EB", "orientation": "portrait-primary", - "lang": "de", + "theme_color": "#007AFF", + "background_color": "#F5F5F7", + "lang": "de-DE", + "categories": ["productivity", "lifestyle"], "icons": [ - { - "src": "/icons/icon-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "any" - }, - { - "src": "/icons/icon-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "/icons/icon-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "any" - }, - { - "src": "/icons/icon-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "/icons/apple-touch-icon.png", - "sizes": "180x180", - "type": "image/png", - "purpose": "any" - } - ] + { "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }, + { "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" }, + { "src": "/icons/icon-maskable-192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable" }, + { "src": "/icons/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" } + ], + "screenshots": [] } diff --git a/public/router.js b/public/router.js index 2e199fb..1c4bf49 100644 --- a/public/router.js +++ b/public/router.js @@ -8,21 +8,61 @@ import { auth } from '/api.js'; // -------------------------------------------------------- // Routen-Definitionen -// Jede Route hat: path, page (dynamisch geladen), requiresAuth +// Jede Route hat: path, page (dynamisch geladen), requiresAuth, module (für theme-color) // -------------------------------------------------------- const ROUTES = [ - { path: '/login', page: '/pages/login.js', requiresAuth: false }, - { path: '/', page: '/pages/dashboard.js', requiresAuth: true }, - { path: '/tasks', page: '/pages/tasks.js', requiresAuth: true }, - { path: '/shopping', page: '/pages/shopping.js', requiresAuth: true }, - { path: '/meals', page: '/pages/meals.js', requiresAuth: true }, - { path: '/calendar', page: '/pages/calendar.js', requiresAuth: true }, - { path: '/notes', page: '/pages/notes.js', requiresAuth: true }, - { path: '/contacts', page: '/pages/contacts.js', requiresAuth: true }, - { path: '/budget', page: '/pages/budget.js', requiresAuth: true }, - { path: '/settings', page: '/pages/settings.js', requiresAuth: true }, + { path: '/login', page: '/pages/login.js', requiresAuth: false, module: null }, + { path: '/', page: '/pages/dashboard.js', requiresAuth: true, module: 'dashboard' }, + { path: '/tasks', page: '/pages/tasks.js', requiresAuth: true, module: 'tasks' }, + { path: '/shopping', page: '/pages/shopping.js', requiresAuth: true, module: 'shopping' }, + { path: '/meals', page: '/pages/meals.js', requiresAuth: true, module: 'meals' }, + { path: '/calendar', page: '/pages/calendar.js', requiresAuth: true, module: 'calendar' }, + { path: '/notes', page: '/pages/notes.js', requiresAuth: true, module: 'notes' }, + { path: '/contacts', page: '/pages/contacts.js', requiresAuth: true, module: 'contacts' }, + { path: '/budget', page: '/pages/budget.js', requiresAuth: true, module: 'budget' }, + { path: '/settings', page: '/pages/settings.js', requiresAuth: true, module: 'settings' }, ]; +// -------------------------------------------------------- +// Standalone-Modus: Dynamische theme-color Anpassung +// Statusbar-Farbe spiegelt aktuelle Seite / Modal-State wider +// -------------------------------------------------------- +const isStandalone = window.matchMedia('(display-mode: standalone)').matches + || navigator.standalone === true; + +/** + * Setzt die theme-color Meta-Tags (Light + Dark Variante). + * @param {string} lightColor + * @param {string} [darkColor] — Falls nicht angegeben, wird lightColor für beide gesetzt + */ +function setThemeColor(lightColor, darkColor) { + if (!isStandalone) return; + const metas = document.querySelectorAll('meta[name="theme-color"]'); + if (metas.length >= 2) { + metas[0].setAttribute('content', lightColor); + metas[1].setAttribute('content', darkColor || lightColor); + } else if (metas.length === 1) { + metas[0].setAttribute('content', lightColor); + } +} + +/** Liest eine CSS Custom Property vom :root */ +function getCSSToken(name) { + return getComputedStyle(document.documentElement).getPropertyValue(name).trim(); +} + +/** Setzt theme-color passend zum aktuellen Modul */ +function updateThemeColorForRoute(route) { + if (!route?.module) { + setThemeColor('#007AFF', '#1C1C1E'); + return; + } + const color = getCSSToken(`--module-${route.module}`); + if (color) { + setThemeColor(color, color); + } +} + // -------------------------------------------------------- // Modul-Cache: verhindert redundante dynamic imports bei Navigation // -------------------------------------------------------- @@ -88,6 +128,7 @@ async function navigate(path, userOrPushState = true, pushState = true) { await renderPage(route); updateNav(path); + updateThemeColorForRoute(route); } /** @@ -348,4 +389,12 @@ window.addEventListener('auth:expired', () => { navigate(location.pathname, false); // Globale Exporte -window.oikos = { navigate, showToast }; +window.oikos = { + navigate, + showToast, + setThemeColor, + restoreThemeColor: () => { + const route = ROUTES.find((r) => r.path === currentPath); + updateThemeColorForRoute(route); + }, +}; diff --git a/public/styles/pwa.css b/public/styles/pwa.css new file mode 100644 index 0000000..751b397 --- /dev/null +++ b/public/styles/pwa.css @@ -0,0 +1,65 @@ +/** + * Modul: PWA Native Feel + * Zweck: Natives Touch- und Scrollverhalten, Safe Areas, Touch-Targets + * Abhängigkeiten: tokens.css, layout.css + */ + +/* ── Kein Rubber-Banding / Pull-to-Refresh des Browsers ── */ +html, body { + overscroll-behavior: none; +} + +/* ── Kein Tap-Highlight auf allen Elementen (Android Chrome) ── + * reset.css setzt es nur auf html; hier global für alle Elemente */ +* { + -webkit-tap-highlight-color: transparent; +} + +/* ── Safe Area Insets (Notch, Dynamic Island, Gesture Bar) ── */ +body { + padding-top: env(safe-area-inset-top); + padding-bottom: env(safe-area-inset-bottom); + padding-left: env(safe-area-inset-left); + padding-right: env(safe-area-inset-right); +} + +/* ── Bottom Nav über der Gesture Bar ── + * layout.css nutzt --safe-area-inset-bottom Token; + * hier als Fallback direkt via env() */ +.nav-bottom { + padding-bottom: env(safe-area-inset-bottom); +} + +/* ── Touch-Targets: min 44×44px (Apple HIG / WCAG 2.5.5) ── */ +button, a, [role="button"], input[type="checkbox"], input[type="radio"] { + min-height: 44px; + min-width: 44px; +} + +/* ── Smooth Momentum-Scrolling in scrollbaren Containern ── */ +.scroll-container, +.nav-bottom__scroll { + overflow-y: auto; + -webkit-overflow-scrolling: touch; + overscroll-behavior-y: contain; +} + +/* ── Kein Text-Selection in UI-Elementen (nur in Content-Bereichen) ── */ +nav, +.nav-bottom, +.nav-sidebar, +.cal-toolbar, +.tasks-toolbar, +.notes-toolbar, +.contacts-toolbar, +.modal-panel__header { + -webkit-user-select: none; + user-select: none; +} + +/* ── Standalone-Modus: Status-Bar-Bereich berücksichtigen ── */ +@media (display-mode: standalone) { + body { + padding-top: env(safe-area-inset-top); + } +} diff --git a/public/sw-register.js b/public/sw-register.js index d198577..e0ade6c 100644 --- a/public/sw-register.js +++ b/public/sw-register.js @@ -1,6 +1,7 @@ /** * Modul: Service Worker Registrierung - * Zweck: Ausgelagert aus index.html um CSP-Inline-Script-Verletzung zu vermeiden + * Zweck: Ausgelagert aus index.html um CSP-Inline-Script-Verletzung zu vermeiden. + * Handhabt nahtlose Updates via controllerchange. * Abhängigkeiten: keine */ @@ -10,4 +11,13 @@ if ('serviceWorker' in navigator) { console.warn('[SW] Registrierung fehlgeschlagen:', err); }); }); + + // Nahtloses Update: Neuer SW hat skipWaiting() + clients.claim() aufgerufen + // → Controller wechselt → Seite neu laden für konsistenten Stand + let refreshing = false; + navigator.serviceWorker.addEventListener('controllerchange', () => { + if (refreshing) return; + refreshing = true; + window.location.reload(); + }); } diff --git a/public/sw.js b/public/sw.js index 68b36d6..7768c22 100644 --- a/public/sw.js +++ b/public/sw.js @@ -12,9 +12,9 @@ * API: Immer Netzwerk (kein Caching von Nutzerdaten) */ -const SHELL_CACHE = 'oikos-shell-v18'; -const PAGES_CACHE = 'oikos-pages-v18'; -const ASSETS_CACHE = 'oikos-assets-v18'; +const SHELL_CACHE = 'oikos-shell-v19'; +const PAGES_CACHE = 'oikos-pages-v19'; +const ASSETS_CACHE = 'oikos-assets-v19'; const ALL_CACHES = [SHELL_CACHE, PAGES_CACHE, ASSETS_CACHE]; // App-Shell: sofort benötigt für ersten Render @@ -28,6 +28,7 @@ const APP_SHELL = [ '/lucide.min.js', '/styles/tokens.css', '/styles/reset.css', + '/styles/pwa.css', '/styles/layout.css', '/styles/login.css', '/styles/dashboard.css', @@ -39,10 +40,15 @@ const APP_SHELL = [ '/styles/contacts.css', '/styles/budget.css', '/styles/settings.css', + '/components/oikos-install-prompt.js', '/manifest.json', '/favicon.ico', '/icons/favicon-32.png', '/icons/apple-touch-icon.png', + '/icons/icon-192.png', + '/icons/icon-512.png', + '/icons/icon-maskable-192.png', + '/icons/icon-maskable-512.png', ]; // Seiten-Module: lazy geladen, aber vorab gecacht für Offline @@ -107,6 +113,12 @@ self.addEventListener('fetch', (event) => { // Nur GET cachen if (request.method !== 'GET') return; + // Navigation Requests: Network-first, Fallback auf gecachte Shell + if (request.mode === 'navigate') { + event.respondWith(networkFirst(request, SHELL_CACHE)); + return; + } + // Bilder + Fonts: Cache-First, langer TTL if (isAsset(url.pathname)) { event.respondWith(cacheFirst(request, ASSETS_CACHE)); @@ -119,10 +131,39 @@ self.addEventListener('fetch', (event) => { return; } - // App-Shell (HTML, JS, CSS): Stale-While-Revalidate + // App-Shell (JS, CSS): Stale-While-Revalidate event.respondWith(staleWhileRevalidate(request, SHELL_CACHE)); }); +// -------------------------------------------------------- +// Strategie: Network-First (für Navigation Requests) +// Versucht Netzwerk, fällt auf gecachte Shell zurück (Offline). +// -------------------------------------------------------- +async function networkFirst(request, cacheName) { + const cache = await caches.open(cacheName); + + try { + const response = await fetch(request); + if (response.ok && response.type === 'basic') { + cache.put(request, response.clone()); + } + return response; + } catch { + // Offline: gecachte Shell liefern + const cached = await cache.match(request); + if (cached) return cached; + + // Fallback auf index.html (SPA-Routing) + const shell = await cache.match('/index.html'); + if (shell) return shell; + + return new Response('Keine Verbindung', { + status: 503, + headers: { 'Content-Type': 'text/plain; charset=utf-8' }, + }); + } +} + // -------------------------------------------------------- // Strategie: Stale-While-Revalidate // Liefert sofort aus Cache, aktualisiert im Hintergrund. diff --git a/scripts/generate-icons.js b/scripts/generate-icons.js new file mode 100644 index 0000000..e95386f --- /dev/null +++ b/scripts/generate-icons.js @@ -0,0 +1,88 @@ +/** + * Icon Generator for Oikos PWA + * Generates placeholder icons (accent color #007AFF with white "O") + * Sizes: 192px and 512px, both "any" and "maskable" variants + * Maskable icons include safe zone padding (min 10%) + * + * Usage: node scripts/generate-icons.js + * Dependencies: sharp (devDependency) + */ + +import sharp from 'sharp'; +import { mkdirSync } from 'node:fs'; +import { join, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const ICONS_DIR = join(__dirname, '..', 'public', 'icons'); +const ACCENT = '#007AFF'; +const BG_LIGHT = '#F5F5F7'; + +mkdirSync(ICONS_DIR, { recursive: true }); + +/** + * Create an SVG with a centered "O" on accent background. + * @param {number} size - Icon dimension in px + * @param {boolean} maskable - If true, add 20% padding for safe zone + */ +function createSvg(size, maskable) { + const fontSize = maskable ? size * 0.4 : size * 0.55; + const bgRadius = maskable ? 0 : size * 0.18; + + return ` + + O +`; +} + +/** + * Create Apple Touch Icon (180x180) with slight rounding + */ +function createAppleTouchSvg() { + const size = 180; + const fontSize = size * 0.55; + return ` + + O +`; +} + +/** + * Create favicon (32x32) + */ +function createFaviconSvg() { + const size = 32; + const fontSize = size * 0.6; + return ` + + O +`; +} + +const icons = [ + { name: 'icon-192.png', size: 192, maskable: false }, + { name: 'icon-512.png', size: 512, maskable: false }, + { name: 'icon-maskable-192.png', size: 192, maskable: true }, + { name: 'icon-maskable-512.png', size: 512, maskable: true }, + { name: 'apple-touch-icon.png', size: 180, svg: createAppleTouchSvg() }, + { name: 'favicon-32.png', size: 32, svg: createFaviconSvg() }, +]; + +for (const icon of icons) { + const svg = icon.svg || createSvg(icon.size, icon.maskable); + const outputPath = join(ICONS_DIR, icon.name); + + await sharp(Buffer.from(svg)) + .png() + .toFile(outputPath); + + console.log(` ✓ ${icon.name} (${icon.size}x${icon.size})`); +} + +console.log('\nIcons generated in public/icons/');