diff --git a/.gitignore b/.gitignore index feb53eb..0c423d4 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,7 @@ app manifest-checksum* settings.gradle + +**/public/workbox-*.js +**/public/sw.js +**/public/worker-*.js diff --git a/next.config.js b/next.config.js index 7f0acbb..c477aa0 100644 --- a/next.config.js +++ b/next.config.js @@ -2,6 +2,7 @@ const webpack = require("webpack"); const withPWA = require("next-pwa")({ dest: "public", + customWorkerDir: "src/workers", }); /** @type {import('next').NextConfig} */ diff --git a/package.json b/package.json index 91c8997..b8a7a66 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@mui/material": "^5.15.16", "@mui/material-nextjs": "^5.15.11", "@web5/api": "^0.9.2", + "babel-loader": "^9.1.3", "crypto-browserify": "^3.12.0", "formik": "^2.4.6", "next": "14.2.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b762ed4..6e7fd08 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ dependencies: '@web5/api': specifier: ^0.9.2 version: 0.9.2 + babel-loader: + specifier: ^9.1.3 + version: 9.1.3(@babel/core@7.24.5)(webpack@5.91.0) crypto-browserify: specifier: ^3.12.0 version: 3.12.0 @@ -2554,6 +2557,17 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + /ajv-formats@2.1.1(ajv@8.12.0): + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.12.0 + dev: false + /ajv-keywords@3.5.2(ajv@6.12.6): resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: @@ -2562,6 +2576,15 @@ packages: ajv: 6.12.6 dev: false + /ajv-keywords@5.1.0(ajv@8.12.0): + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + dependencies: + ajv: 8.12.0 + fast-deep-equal: 3.1.3 + dev: false + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -2801,6 +2824,19 @@ packages: webpack: 5.91.0 dev: false + /babel-loader@9.1.3(@babel/core@7.24.5)(webpack@5.91.0): + resolution: {integrity: sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==} + engines: {node: '>= 14.15.0'} + peerDependencies: + '@babel/core': ^7.12.0 + webpack: '>=5' + dependencies: + '@babel/core': 7.24.5 + find-cache-dir: 4.0.0 + schema-utils: 4.2.0 + webpack: 5.91.0 + dev: false + /babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} @@ -3158,6 +3194,10 @@ packages: engines: {node: '>= 6'} dev: true + /common-path-prefix@3.0.0: + resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + dev: false + /common-tags@1.8.2: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} engines: {node: '>=4.0.0'} @@ -3999,6 +4039,14 @@ packages: pkg-dir: 4.2.0 dev: false + /find-cache-dir@4.0.0: + resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} + engines: {node: '>=14.16'} + dependencies: + common-path-prefix: 3.0.0 + pkg-dir: 7.0.0 + dev: false + /find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} dev: false @@ -4019,6 +4067,14 @@ packages: path-exists: 4.0.0 dev: true + /find-up@6.3.0: + resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + dev: false + /flat-cache@3.2.0: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} @@ -4945,6 +5001,13 @@ packages: p-locate: 5.0.0 dev: true + /locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-locate: 6.0.0 + dev: false + /lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} dev: false @@ -5379,6 +5442,13 @@ packages: yocto-queue: 0.1.0 dev: true + /p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: false + /p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -5393,6 +5463,13 @@ packages: p-limit: 3.1.0 dev: true + /p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-limit: 4.0.0 + dev: false + /p-map@2.1.0: resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} engines: {node: '>=6'} @@ -5448,6 +5525,11 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + /path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -5527,6 +5609,13 @@ packages: find-up: 4.1.0 dev: false + /pkg-dir@7.0.0: + resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} + engines: {node: '>=14.16'} + dependencies: + find-up: 6.3.0 + dev: false + /popper.js@1.16.1: resolution: {integrity: sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==} deprecated: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1 @@ -6046,6 +6135,16 @@ packages: ajv-keywords: 3.5.2(ajv@6.12.6) dev: false + /schema-utils@4.2.0: + resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} + engines: {node: '>= 12.13.0'} + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + ajv-keywords: 5.1.0(ajv@8.12.0) + dev: false + /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -7111,6 +7210,11 @@ packages: engines: {node: '>=10'} dev: true + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: false + /yup@1.4.0: resolution: {integrity: sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==} dependencies: diff --git a/src/components/timer/index.tsx b/src/components/timer/index.tsx index 06724ed..2d953ec 100644 --- a/src/components/timer/index.tsx +++ b/src/components/timer/index.tsx @@ -25,6 +25,20 @@ class Timer { this._timerId = crypto.randomUUID(); this.tickHandler = tickHandler; this._intervalId = null; + + // Start a background sync to update timer state + } + + async sendTimerMessage() { + if ("serviceWorker" in navigator && "SyncManager" in window) { + const registration = await navigator.serviceWorker.ready; + try { + // @ts-ignore + await registration.sync.register("timer-sync"); + } catch { + console.log("Background Sync could not be registered!"); + } + } } get totalTime() { @@ -51,6 +65,7 @@ class Timer { if (!this._isPlaying && this._remainingTime > 0) { this._isPlaying = true; this._intervalId = setInterval(() => { + this.sendTimerMessage(); if (this._remainingTime > 0) { this._remainingTime -= 10; // Decrease by 10 milliseconds each tick this.update(); @@ -58,20 +73,6 @@ class Timer { this.setFinished(); } }, 10); // Tick every 10 milliseconds - - // Start a background sync to update timer state - if ("serviceWorker" in navigator && "SyncManager" in window) { - navigator.serviceWorker.ready - .then((registration) => { - console.log("registering sync"); - // TODO: Remove - // @ts-ignore - return registration.sync.register("timerSync"); - }) - .catch((err) => { - console.error("Background sync registration failed:", err); - }); - } } } diff --git a/src/workers/index.ts b/src/workers/index.ts new file mode 100644 index 0000000..aad5c15 --- /dev/null +++ b/src/workers/index.ts @@ -0,0 +1,14 @@ +"use strict"; + +self.addEventListener("sync", (event) => { + console.log("got sync message", event); + // @ts-ignore + if (event.tag === "timer-sync") { + console.log("got timer sync message"); + const logMessage = (e: any) => { + console.log("got timer", e); + }; + // @ts-ignore + event.waitUntil(logMessage); + } +});