diff --git a/package.json b/package.json index 87a8da7..fc27fc2 100644 --- a/package.json +++ b/package.json @@ -45,13 +45,13 @@ "homepage": "https://github.com/molvqingtai/WebChat", "dependencies": { "@hookform/resolvers": "^3.9.1", - "@lottiefiles/dotlottie-react": "^0.9.2", + "@lottiefiles/dotlottie-react": "^0.9.3", "@perfsee/jsonr": "^1.13.0", "@radix-ui/react-avatar": "^1.1.1", "@radix-ui/react-checkbox": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-hover-card": "^1.1.2", - "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-icons": "^1.3.1", "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-popover": "^1.1.2", "@radix-ui/react-portal": "^1.1.2", @@ -70,7 +70,7 @@ "clsx": "^2.1.1", "danmu": "^0.14.0", "date-fns": "^4.1.0", - "framer-motion": "^11.11.10", + "framer-motion": "^11.11.11", "idb-keyval": "^6.2.1", "lucide-react": "^0.454.0", "nanoid": "^5.0.8", @@ -86,7 +86,7 @@ "remesh-logger": "^4.1.0", "remesh-react": "^4.1.2", "rxjs": "^7.8.1", - "sonner": "^1.5.0", + "sonner": "^1.6.1", "tailwind-merge": "^2.5.4", "trystero": "^0.20.0", "type-fest": "^4.26.1", @@ -97,27 +97,27 @@ "@commitlint/cli": "^19.5.0", "@commitlint/config-conventional": "^19.5.0", "@eslint-react/eslint-plugin": "^1.15.2", - "@eslint/js": "^9.13.0", + "@eslint/js": "^9.14.0", "@semantic-release/changelog": "^6.0.3", "@semantic-release/exec": "^6.0.3", "@semantic-release/git": "^10.0.1", "@types/eslint": "^9.6.1", "@types/eslint__js": "^8.42.3", "@types/eslint-plugin-tailwindcss": "^3.17.0", - "@types/node": "^22.8.2", + "@types/node": "^22.8.6", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", - "@typescript-eslint/parser": "^8.12.1", + "@typescript-eslint/parser": "^8.12.2", "@vitejs/plugin-react": "^4.3.3", "autoprefixer": "^10.4.20", "cross-env": "^7.0.3", - "eslint": "^9.13.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-tailwindcss": "^3.17.5", "globals": "^15.11.0", "husky": "^9.1.6", - "jiti": "^2.3.3", + "jiti": "^2.4.0", "lint-staged": "^15.2.10", "npm-run-all": "^4.1.5", "postcss": "^8.4.47", @@ -128,8 +128,8 @@ "tailwindcss": "^3.4.14", "tailwindcss-animate": "^1.0.7", "typescript": "^5.6.3", - "typescript-eslint": "^8.12.1", - "vite-plugin-svgr": "^4.2.0", + "typescript-eslint": "^8.12.2", + "vite-plugin-svgr": "^4.3.0", "webext-bridge": "^6.0.1", "wxt": "^0.19.13" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b24d902..9ebfe2b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^3.9.1 version: 3.9.1(react-hook-form@7.53.1(react@18.3.1)) '@lottiefiles/dotlottie-react': - specifier: ^0.9.2 - version: 0.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^0.9.3 + version: 0.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@perfsee/jsonr': specifier: ^1.13.0 version: 1.13.0 @@ -30,8 +30,8 @@ importers: specifier: ^1.1.2 version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-icons': - specifier: ^1.3.0 - version: 1.3.0(react@18.3.1) + specifier: ^1.3.1 + version: 1.3.1(react@18.3.1) '@radix-ui/react-label': specifier: ^2.1.0 version: 2.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -87,8 +87,8 @@ importers: specifier: ^4.1.0 version: 4.1.0 framer-motion: - specifier: ^11.11.10 - version: 11.11.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^11.11.11 + version: 11.11.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) idb-keyval: specifier: ^6.2.1 version: 6.2.1 @@ -135,8 +135,8 @@ importers: specifier: ^7.8.1 version: 7.8.1 sonner: - specifier: ^1.5.0 - version: 1.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^1.6.1 + version: 1.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tailwind-merge: specifier: ^2.5.4 version: 2.5.4 @@ -155,16 +155,16 @@ importers: devDependencies: '@commitlint/cli': specifier: ^19.5.0 - version: 19.5.0(@types/node@22.8.2)(typescript@5.6.3) + version: 19.5.0(@types/node@22.8.6)(typescript@5.6.3) '@commitlint/config-conventional': specifier: ^19.5.0 version: 19.5.0 '@eslint-react/eslint-plugin': specifier: ^1.15.2 - version: 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + version: 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint/js': - specifier: ^9.13.0 - version: 9.13.0 + specifier: ^9.14.0 + version: 9.14.0 '@semantic-release/changelog': specifier: ^6.0.3 version: 6.0.3(semantic-release@24.2.0(typescript@5.6.3)) @@ -184,8 +184,8 @@ importers: specifier: ^8.42.3 version: 8.42.3 '@types/node': - specifier: ^22.8.2 - version: 22.8.2 + specifier: ^22.8.6 + version: 22.8.6 '@types/react': specifier: ^18.3.12 version: 18.3.12 @@ -193,11 +193,11 @@ importers: specifier: ^18.3.1 version: 18.3.1 '@typescript-eslint/parser': - specifier: ^8.12.1 - version: 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + specifier: ^8.12.2 + version: 8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@vitejs/plugin-react': specifier: ^4.3.3 - version: 4.3.3(vite@5.4.10(@types/node@22.8.2)) + version: 4.3.3(vite@5.4.10(@types/node@22.8.6)) autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.4.47) @@ -205,14 +205,14 @@ importers: specifier: ^7.0.3 version: 7.0.3 eslint: - specifier: ^9.13.0 - version: 9.13.0(jiti@2.3.3) + specifier: ^9.14.0 + version: 9.14.0(jiti@2.4.0) eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@9.13.0(jiti@2.3.3)) + version: 9.1.0(eslint@9.14.0(jiti@2.4.0)) eslint-plugin-prettier: specifier: ^5.2.1 - version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.3.3)))(eslint@9.13.0(jiti@2.3.3))(prettier@3.3.3) + version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.14.0(jiti@2.4.0)))(eslint@9.14.0(jiti@2.4.0))(prettier@3.3.3) eslint-plugin-tailwindcss: specifier: ^3.17.5 version: 3.17.5(tailwindcss@3.4.14) @@ -223,8 +223,8 @@ importers: specifier: ^9.1.6 version: 9.1.6 jiti: - specifier: ^2.3.3 - version: 2.3.3 + specifier: ^2.4.0 + version: 2.4.0 lint-staged: specifier: ^15.2.10 version: 15.2.10 @@ -256,17 +256,17 @@ importers: specifier: ^5.6.3 version: 5.6.3 typescript-eslint: - specifier: ^8.12.1 - version: 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + specifier: ^8.12.2 + version: 8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) vite-plugin-svgr: - specifier: ^4.2.0 - version: 4.2.0(rollup@4.21.3)(typescript@5.6.3)(vite@5.4.10(@types/node@22.8.2)) + specifier: ^4.3.0 + version: 4.3.0(rollup@4.21.3)(typescript@5.6.3)(vite@5.4.10(@types/node@22.8.6)) webext-bridge: specifier: ^6.0.1 version: 6.0.1 wxt: specifier: ^0.19.13 - version: 0.19.13(@types/node@22.8.2)(bufferutil@4.0.8)(rollup@4.21.3)(utf-8-validate@6.0.4) + version: 0.19.13(@types/node@22.8.6)(bufferutil@4.0.8)(rollup@4.21.3)(utf-8-validate@6.0.4) packages: @@ -633,6 +633,10 @@ packages: resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-react/ast@1.15.2': resolution: {integrity: sha512-Dtn6Ai/P74CLoZ4mPR/9Mm4xXuulXULaXNXAzusZSNfa3+4podw6LCxKHpLcLqsvfZN3mciW3cC8CAyH7/MZwg==} @@ -676,8 +680,8 @@ packages: resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.13.0': - resolution: {integrity: sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==} + '@eslint/js@9.14.0': + resolution: {integrity: sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.4': @@ -915,12 +919,12 @@ packages: peerDependencies: react-hook-form: ^7.0.0 - '@humanfs/core@0.19.0': - resolution: {integrity: sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==} + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} - '@humanfs/node@0.16.5': - resolution: {integrity: sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==} + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': @@ -931,6 +935,10 @@ packages: resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} engines: {node: '>=18.18'} + '@humanwhocodes/retry@0.4.0': + resolution: {integrity: sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==} + engines: {node: '>=18.18'} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1016,14 +1024,14 @@ packages: '@libp2p/websockets@8.2.0': resolution: {integrity: sha512-UNjqkQ8/emnYswp1ohIIuZCnhI5DlvWF9IaIND2MoTCDavi7yubWfMp8jSWBsAqPnMeLMO8MQ6YlOo4FFC104Q==} - '@lottiefiles/dotlottie-react@0.9.2': - resolution: {integrity: sha512-KSx2BRM2/zwMJRwt68b78n93Da3G3tZT5MmDTPPjy5kIKvS98Q3OBpngjgEDPNax9FHnTZZkmjnhVsBaNbllQA==} + '@lottiefiles/dotlottie-react@0.9.3': + resolution: {integrity: sha512-x4xQlFFulAF/nG044VNMwaXWk8ehg/KEHXpMxGB+L5gv3qohjxv/I7/erHyfhWY9y6C/VMl+PiWZbT54W8+lUQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@lottiefiles/dotlottie-web@0.36.0': - resolution: {integrity: sha512-FVGlQnhT95+aKrf4OiyC4/fP6ESZa8YwYDyvfuAeWktHFdAT/7Gbt76ZmCZU/Bwera6FB7UgJuoAtK/duTFCZQ==} + '@lottiefiles/dotlottie-web@0.36.1': + resolution: {integrity: sha512-KvxOH5Msk0Ivqpgq4p1DGo1IG2XPX4kEVkhssTaOUEvoeCxDLru+DlbUzwG8b5JcJwEBmrAMzCNzCTmn+uMFxQ==} '@lukeed/csprng@1.1.0': resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} @@ -1408,10 +1416,10 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-icons@1.3.0': - resolution: {integrity: sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==} + '@radix-ui/react-icons@1.3.1': + resolution: {integrity: sha512-QvYompk0X+8Yjlo/Fv4McrzxohDdM5GgLHyQcPpcsPvlOSXCGFjdbuyGL5dzRbg0GpknAjQJJZzdiRK7iWVuFQ==} peerDependencies: - react: ^16.x || ^17.x || ^18.x + react: ^16.x || ^17.x || ^18.x || ^19.x '@radix-ui/react-id@1.1.0': resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==} @@ -1646,15 +1654,6 @@ packages: '@resreq/timer@1.1.6': resolution: {integrity: sha512-D8aLPVuRz9ShraIHPU4v9hSWS7HhEDDm4ww9PkqwGRFMvlR3BQ/34UX0Do77PNdpqgJFp4eiRH02gHiV31/3Rw==} - '@rollup/pluginutils@5.1.0': - resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - '@rollup/pluginutils@5.1.3': resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} engines: {node: '>=14.0.0'} @@ -2003,8 +2002,8 @@ packages: '@types/murmurhash3js-revisited@3.0.3': resolution: {integrity: sha512-QvlqvYtGBYIDeO8dFdY4djkRubcrc+yTJtBc7n8VZPlJDUS/00A+PssbvERM8f9bYRmcaSEHPZgZojeQj7kzAA==} - '@types/node@22.8.2': - resolution: {integrity: sha512-NzaRNFV+FZkvK/KLCsNdTvID0SThyrs5SHB6tsD/lajr22FGC73N2QeDPM2wHtVde8mgcXuSsHQkH5cX1pbPLw==} + '@types/node@22.8.6': + resolution: {integrity: sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -2045,8 +2044,8 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.12.1': - resolution: {integrity: sha512-gNg/inLRcPoBsKKIe4Vv38SVSOhk4BKWNO0T56sVff33gRqtTpOsrhHtiOKD1lmIOmCtZMPaW2x/h2FlM+sCEg==} + '@typescript-eslint/eslint-plugin@8.12.2': + resolution: {integrity: sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 @@ -2056,8 +2055,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@8.12.1': - resolution: {integrity: sha512-I/I9Bg7qFa8rOgBnUUHIWTgzbB5wVkSLX+04xGUzTcJUtdq/I2uHWR9mbW6qUYJG/UmkuDcTax5JHvoEWOAHOQ==} + '@typescript-eslint/parser@8.12.2': + resolution: {integrity: sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -2070,6 +2069,10 @@ packages: resolution: {integrity: sha512-bma6sD1iViTt+y9MAwDlBdPTMCqoH/BNdcQk4rKhIZWv3eM0xHmzeSrPJA663PAqFqfpOmtdugycpr0E1mZDVA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.12.2': + resolution: {integrity: sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/type-utils@8.12.1': resolution: {integrity: sha512-zJzrvbDVjIzVKV2TGHcjembEhws8RWXJhmqfO9hS2gRXBN0gDwGhRPEdJ6AZglzfJ+YA1q09EWpSLSXjBJpIMQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2079,10 +2082,23 @@ packages: typescript: optional: true + '@typescript-eslint/type-utils@8.12.2': + resolution: {integrity: sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/types@8.12.1': resolution: {integrity: sha512-anMS4es5lxBe4UVcDXOkcDb3csnm5BvaNIbOFfvy/pJEohorsggdVB8MFbl5EZiEuBnZZ0ei1z7W5b6FdFiV1Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.12.2': + resolution: {integrity: sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.12.1': resolution: {integrity: sha512-k/o9khHOckPeDXilFTIPsP9iAYhhdMh3OsOL3i2072PNpFqhqzRHx472/0DeC8H/WZee3bZG0z2ddGRSPgeOKw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2092,16 +2108,35 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@8.12.2': + resolution: {integrity: sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/utils@8.12.1': resolution: {integrity: sha512-sDv9yFHrhKe1WN8EYuzfhKCh/sFRupe9P+m/lZ5YgVvPoCUGHNN50IO4llSu7JAbftUM/QcCh+GeCortXPrBYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/utils@8.12.2': + resolution: {integrity: sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/visitor-keys@8.12.1': resolution: {integrity: sha512-2RwdwnNGuOQKdGjuhujQHUqBZhEuodg2sLVPvOfWktvA9sOXOVqARjOyHSyhN2LiJGKxV6c8oOcmOtRcAnEeFw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.12.2': + resolution: {integrity: sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -2243,6 +2278,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + adm-zip@0.5.16: resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==} engines: {node: '>=12.0'} @@ -3207,20 +3247,20 @@ packages: peerDependencies: tailwindcss: ^3.4.0 - eslint-scope@8.1.0: - resolution: {integrity: sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==} + eslint-scope@8.2.0: + resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.1.0: - resolution: {integrity: sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.13.0: - resolution: {integrity: sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==} + eslint@9.14.0: + resolution: {integrity: sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -3229,8 +3269,8 @@ packages: jiti: optional: true - espree@10.2.0: - resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esquery@1.6.0: @@ -3418,8 +3458,8 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - framer-motion@11.11.10: - resolution: {integrity: sha512-061Bt1jL/vIm+diYIiA4dP/Yld7vD47ROextS7ESBW5hr4wQFhxB5D5T5zAc3c/5me3cOa+iO5LqhA38WDln/A==} + framer-motion@11.11.11: + resolution: {integrity: sha512-tuDH23ptJAKUHGydJQII9PhABNJBpB+z0P1bmgKK9QFIssHGlfPd6kxMq00LSKwE27WFsb2z0ovY0bpUyMvfRw==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 @@ -4182,8 +4222,8 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true - jiti@2.3.3: - resolution: {integrity: sha512-EX4oNDwcXSivPrw2qKH2LB5PoFxEvgtv2JgwW0bU858HoLQ+kutSvjLMUqBd0PeJYEinLWhoI9Ol0eYMqj/wNQ==} + jiti@2.4.0: + resolution: {integrity: sha512-H5UpaUI+aHOqZXlYOaFP/8AzKsg+guWu+Pr3Y8i7+Y3zr1aXAvCvTAQ1RxSc6oVD8R8c7brgNtTVP91E7upH/g==} hasBin: true js-cookie@2.2.1: @@ -5804,11 +5844,11 @@ packages: resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} engines: {node: '>=10.0.0'} - sonner@1.5.0: - resolution: {integrity: sha512-FBjhG/gnnbN6FY0jaNnqZOMmB73R+5IiyYAw8yBj7L54ER7HB3fOSE5OFiQiE2iXWxeXKvg6fIP4LtVppHEdJA==} + sonner@1.6.1: + resolution: {integrity: sha512-0iD+eDJHyJitl069BC6wVDykQD56FMKk4TD6XkcCcikcDYaGsFKlSU0mZQXYWKPpFof3jlV/u4vGZc2KCqz8OQ==} peerDependencies: - react: ^18.0.0 - react-dom: ^18.0.0 + react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} @@ -6197,8 +6237,8 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript-eslint@8.12.1: - resolution: {integrity: sha512-SsKedZnq4TStkrpqnk+OqTnmkC9CkYBRNKjQ965CLpFruGcRkPF5UhKxbcbF6c/m2r6YAgKw/UtQxdlMjh3mug==} + typescript-eslint@8.12.2: + resolution: {integrity: sha512-UbuVUWSrHVR03q9CWx+JDHeO6B/Hr9p4U5lRH++5tq/EbFq1faYZe50ZSBePptgfIKLEti0aPQ3hFgnPVcd8ZQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' @@ -6457,10 +6497,10 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite-plugin-svgr@4.2.0: - resolution: {integrity: sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==} + vite-plugin-svgr@4.3.0: + resolution: {integrity: sha512-Jy9qLB2/PyWklpYy0xk0UU3TlU0t2UMpJXZvf+hWII1lAmRHrOUKi11Uw8N3rxoNk7atZNYO3pR3vI1f7oi+6w==} peerDependencies: - vite: ^2.6.0 || 3 || 4 || 5 + vite: '>=2.6.0' vite@5.4.10: resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==} @@ -6895,11 +6935,11 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@commitlint/cli@19.5.0(@types/node@22.8.2)(typescript@5.6.3)': + '@commitlint/cli@19.5.0(@types/node@22.8.6)(typescript@5.6.3)': dependencies: '@commitlint/format': 19.5.0 '@commitlint/lint': 19.5.0 - '@commitlint/load': 19.5.0(@types/node@22.8.2)(typescript@5.6.3) + '@commitlint/load': 19.5.0(@types/node@22.8.6)(typescript@5.6.3) '@commitlint/read': 19.5.0 '@commitlint/types': 19.5.0 tinyexec: 0.3.0 @@ -6946,7 +6986,7 @@ snapshots: '@commitlint/rules': 19.5.0 '@commitlint/types': 19.5.0 - '@commitlint/load@19.5.0(@types/node@22.8.2)(typescript@5.6.3)': + '@commitlint/load@19.5.0(@types/node@22.8.6)(typescript@5.6.3)': dependencies: '@commitlint/config-validator': 19.5.0 '@commitlint/execute-rule': 19.5.0 @@ -6954,7 +6994,7 @@ snapshots: '@commitlint/types': 19.5.0 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.6.3) - cosmiconfig-typescript-loader: 5.0.0(@types/node@22.8.2)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@22.8.6)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -7090,20 +7130,22 @@ snapshots: '@esbuild/win32-x64@0.21.5': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@9.13.0(jiti@2.3.3))': + '@eslint-community/eslint-utils@4.4.0(eslint@9.14.0(jiti@2.4.0))': dependencies: - eslint: 9.13.0(jiti@2.3.3) + eslint: 9.14.0(jiti@2.4.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.11.1': {} - '@eslint-react/ast@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@eslint-community/regexpp@4.12.1': {} + + '@eslint-react/ast@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': dependencies: '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/types': 8.12.1 '@typescript-eslint/typescript-estree': 8.12.1(typescript@5.6.3) - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) birecord: 0.1.1 string-ts: 2.2.0 ts-pattern: 5.5.0 @@ -7112,18 +7154,18 @@ snapshots: - supports-color - typescript - '@eslint-react/core@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@eslint-react/core@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': dependencies: - '@eslint-react/ast': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/jsx': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/shared': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/ast': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/jsx': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/shared': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/var': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/var': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.12.1 - '@typescript-eslint/type-utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/type-utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) birecord: 0.1.1 short-unique-id: 5.2.0 ts-pattern: 5.5.0 @@ -7132,46 +7174,46 @@ snapshots: - supports-color - typescript - '@eslint-react/eslint-plugin@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@eslint-react/eslint-plugin@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': dependencies: - '@eslint-react/shared': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/shared': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.12.1 - '@typescript-eslint/type-utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/type-utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint: 9.13.0(jiti@2.3.3) - eslint-plugin-react-debug: 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint-plugin-react-dom: 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint-plugin-react-hooks-extra: 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint-plugin-react-naming-convention: 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint-plugin-react-web-api: 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint-plugin-react-x: 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint: 9.14.0(jiti@2.4.0) + eslint-plugin-react-debug: 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint-plugin-react-dom: 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint-plugin-react-hooks-extra: 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint-plugin-react-naming-convention: 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint-plugin-react-web-api: 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint-plugin-react-x: 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@eslint-react/jsx@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@eslint-react/jsx@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': dependencies: - '@eslint-react/ast': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/ast': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/var': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/var': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.12.1 '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) ts-pattern: 5.5.0 transitivePeerDependencies: - eslint - supports-color - typescript - '@eslint-react/shared@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@eslint-react/shared@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': dependencies: '@eslint-react/tools': 1.15.2 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) picomatch: 4.0.2 transitivePeerDependencies: - eslint @@ -7180,24 +7222,24 @@ snapshots: '@eslint-react/tools@1.15.2': {} - '@eslint-react/types@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@eslint-react/types@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': dependencies: '@eslint-react/tools': 1.15.2 '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) transitivePeerDependencies: - eslint - supports-color - typescript - '@eslint-react/var@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@eslint-react/var@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': dependencies: - '@eslint-react/ast': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/ast': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.12.1 '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) ts-pattern: 5.5.0 transitivePeerDependencies: - eslint @@ -7218,7 +7260,7 @@ snapshots: dependencies: ajv: 6.12.6 debug: 4.3.7 - espree: 10.2.0 + espree: 10.3.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.0 @@ -7228,7 +7270,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.13.0': {} + '@eslint/js@9.14.0': {} '@eslint/object-schema@2.1.4': {} @@ -7580,7 +7622,7 @@ snapshots: '@grpc/grpc-js@1.9.15': dependencies: '@grpc/proto-loader': 0.7.13 - '@types/node': 22.8.2 + '@types/node': 22.8.6 '@grpc/proto-loader@0.7.13': dependencies: @@ -7593,17 +7635,19 @@ snapshots: dependencies: react-hook-form: 7.53.1(react@18.3.1) - '@humanfs/core@0.19.0': {} + '@humanfs/core@0.19.1': {} - '@humanfs/node@0.16.5': + '@humanfs/node@0.16.6': dependencies: - '@humanfs/core': 0.19.0 + '@humanfs/core': 0.19.1 '@humanwhocodes/retry': 0.3.1 '@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/retry@0.3.1': {} + '@humanwhocodes/retry@0.4.0': {} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -7831,13 +7875,13 @@ snapshots: - bufferutil - utf-8-validate - '@lottiefiles/dotlottie-react@0.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@lottiefiles/dotlottie-react@0.9.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@lottiefiles/dotlottie-web': 0.36.0 + '@lottiefiles/dotlottie-web': 0.36.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@lottiefiles/dotlottie-web@0.36.0': {} + '@lottiefiles/dotlottie-web@0.36.1': {} '@lukeed/csprng@1.1.0': {} @@ -8198,7 +8242,7 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@radix-ui/react-icons@1.3.0(react@18.3.1)': + '@radix-ui/react-icons@1.3.1(react@18.3.1)': dependencies: react: 18.3.1 @@ -8442,14 +8486,6 @@ snapshots: dependencies: '@resreq/event-hub': 1.6.0 - '@rollup/pluginutils@5.1.0(rollup@4.21.3)': - dependencies: - '@types/estree': 1.0.5 - estree-walker: 2.0.2 - picomatch: 2.3.1 - optionalDependencies: - rollup: 4.21.3 - '@rollup/pluginutils@5.1.3(rollup@4.21.3)': dependencies: '@types/estree': 1.0.6 @@ -8804,7 +8840,7 @@ snapshots: '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 22.8.2 + '@types/node': 22.8.6 '@types/debug@4.1.12': dependencies: @@ -8812,7 +8848,7 @@ snapshots: '@types/dns-packet@5.6.5': dependencies: - '@types/node': 22.8.2 + '@types/node': 22.8.6 '@types/eslint-plugin-tailwindcss@3.17.0': dependencies: @@ -8863,7 +8899,7 @@ snapshots: '@types/murmurhash3js-revisited@3.0.3': {} - '@types/node@22.8.2': + '@types/node@22.8.6': dependencies: undici-types: 6.19.8 @@ -8884,7 +8920,7 @@ snapshots: '@types/readable-stream@4.0.15': dependencies: - '@types/node': 22.8.2 + '@types/node': 22.8.6 safe-buffer: 5.1.2 '@types/semver@7.5.8': {} @@ -8899,22 +8935,22 @@ snapshots: '@types/ws@8.5.12': dependencies: - '@types/node': 22.8.2 + '@types/node': 22.8.6 '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.8.2 + '@types/node': 22.8.6 optional: true - '@typescript-eslint/eslint-plugin@8.12.1(@typescript-eslint/parser@8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3))(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@typescript-eslint/eslint-plugin@8.12.2(@typescript-eslint/parser@8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3))(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': dependencies: '@eslint-community/regexpp': 4.11.1 - '@typescript-eslint/parser': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.12.1 - '@typescript-eslint/type-utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 8.12.1 - eslint: 9.13.0(jiti@2.3.3) + '@typescript-eslint/parser': 8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.12.2 + '@typescript-eslint/type-utils': 8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.12.2 + eslint: 9.14.0(jiti@2.4.0) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -8924,14 +8960,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@typescript-eslint/parser@8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': dependencies: - '@typescript-eslint/scope-manager': 8.12.1 - '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/typescript-estree': 8.12.1(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 8.12.1 + '@typescript-eslint/scope-manager': 8.12.2 + '@typescript-eslint/types': 8.12.2 + '@typescript-eslint/typescript-estree': 8.12.2(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.12.2 debug: 4.3.7 - eslint: 9.13.0(jiti@2.3.3) + eslint: 9.14.0(jiti@2.4.0) optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: @@ -8942,10 +8978,27 @@ snapshots: '@typescript-eslint/types': 8.12.1 '@typescript-eslint/visitor-keys': 8.12.1 - '@typescript-eslint/type-utils@8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@typescript-eslint/scope-manager@8.12.2': + dependencies: + '@typescript-eslint/types': 8.12.2 + '@typescript-eslint/visitor-keys': 8.12.2 + + '@typescript-eslint/type-utils@8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': dependencies: '@typescript-eslint/typescript-estree': 8.12.1(typescript@5.6.3) - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + debug: 4.3.7 + ts-api-utils: 1.3.0(typescript@5.6.3) + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - eslint + - supports-color + + '@typescript-eslint/type-utils@8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.12.2(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) debug: 4.3.7 ts-api-utils: 1.3.0(typescript@5.6.3) optionalDependencies: @@ -8956,6 +9009,8 @@ snapshots: '@typescript-eslint/types@8.12.1': {} + '@typescript-eslint/types@8.12.2': {} + '@typescript-eslint/typescript-estree@8.12.1(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 8.12.1 @@ -8971,13 +9026,39 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3)': + '@typescript-eslint/typescript-estree@8.12.2(typescript@5.6.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.3.3)) + '@typescript-eslint/types': 8.12.2 + '@typescript-eslint/visitor-keys': 8.12.2 + debug: 4.3.7 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.6.3) + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.14.0(jiti@2.4.0)) '@typescript-eslint/scope-manager': 8.12.1 '@typescript-eslint/types': 8.12.1 '@typescript-eslint/typescript-estree': 8.12.1(typescript@5.6.3) - eslint: 9.13.0(jiti@2.3.3) + eslint: 9.14.0(jiti@2.4.0) + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/utils@8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.14.0(jiti@2.4.0)) + '@typescript-eslint/scope-manager': 8.12.2 + '@typescript-eslint/types': 8.12.2 + '@typescript-eslint/typescript-estree': 8.12.2(typescript@5.6.3) + eslint: 9.14.0(jiti@2.4.0) transitivePeerDependencies: - supports-color - typescript @@ -8987,16 +9068,21 @@ snapshots: '@typescript-eslint/types': 8.12.1 eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.12.2': + dependencies: + '@typescript-eslint/types': 8.12.2 + eslint-visitor-keys: 3.4.3 + '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-react@4.3.3(vite@5.4.10(@types/node@22.8.2))': + '@vitejs/plugin-react@4.3.3(vite@5.4.10(@types/node@22.8.6))': dependencies: '@babel/core': 7.25.2 '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.25.2) '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.25.2) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.4.10(@types/node@22.8.2) + vite: 5.4.10(@types/node@22.8.6) transitivePeerDependencies: - supports-color @@ -9167,12 +9253,14 @@ snapshots: dependencies: event-target-shim: 5.0.1 - acorn-jsx@5.3.2(acorn@8.12.1): + acorn-jsx@5.3.2(acorn@8.14.0): dependencies: - acorn: 8.12.1 + acorn: 8.14.0 acorn@8.12.1: {} + acorn@8.14.0: {} + adm-zip@0.5.16: {} agent-base@7.1.1: @@ -9524,7 +9612,7 @@ snapshots: chrome-launcher@1.1.0: dependencies: - '@types/node': 22.8.2 + '@types/node': 22.8.6 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 2.0.1 @@ -9716,9 +9804,9 @@ snapshots: core-util-is@1.0.3: {} - cosmiconfig-typescript-loader@5.0.0(@types/node@22.8.2)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3): + cosmiconfig-typescript-loader@5.0.0(@types/node@22.8.6)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3): dependencies: - '@types/node': 22.8.2 + '@types/node': 22.8.6 cosmiconfig: 9.0.0(typescript@5.6.3) jiti: 1.21.6 typescript: 5.6.3 @@ -10139,34 +10227,34 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.3.3)): + eslint-config-prettier@9.1.0(eslint@9.14.0(jiti@2.4.0)): dependencies: - eslint: 9.13.0(jiti@2.3.3) + eslint: 9.14.0(jiti@2.4.0) - eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.3.3)))(eslint@9.13.0(jiti@2.3.3))(prettier@3.3.3): + eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.14.0(jiti@2.4.0)))(eslint@9.14.0(jiti@2.4.0))(prettier@3.3.3): dependencies: - eslint: 9.13.0(jiti@2.3.3) + eslint: 9.14.0(jiti@2.4.0) prettier: 3.3.3 prettier-linter-helpers: 1.0.0 synckit: 0.9.1 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 9.1.0(eslint@9.13.0(jiti@2.3.3)) + eslint-config-prettier: 9.1.0(eslint@9.14.0(jiti@2.4.0)) - eslint-plugin-react-debug@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3): + eslint-plugin-react-debug@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3): dependencies: - '@eslint-react/ast': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/core': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/jsx': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/shared': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/ast': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/core': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/jsx': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/shared': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/var': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/var': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.12.1 - '@typescript-eslint/type-utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/type-utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint: 9.13.0(jiti@2.3.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint: 9.14.0(jiti@2.4.0) string-ts: 2.2.0 ts-pattern: 5.5.0 optionalDependencies: @@ -10174,99 +10262,99 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-react-dom@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3): + eslint-plugin-react-dom@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3): dependencies: - '@eslint-react/ast': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/core': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/jsx': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/shared': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/ast': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/core': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/jsx': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/shared': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/var': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/var': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.12.1 '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint: 9.13.0(jiti@2.3.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint: 9.14.0(jiti@2.4.0) ts-pattern: 5.5.0 optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: - supports-color - eslint-plugin-react-hooks-extra@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3): + eslint-plugin-react-hooks-extra@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3): dependencies: - '@eslint-react/ast': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/core': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/jsx': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/shared': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/ast': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/core': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/jsx': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/shared': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/var': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/var': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.12.1 - '@typescript-eslint/type-utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/type-utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint: 9.13.0(jiti@2.3.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint: 9.14.0(jiti@2.4.0) ts-pattern: 5.5.0 optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: - supports-color - eslint-plugin-react-naming-convention@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3): + eslint-plugin-react-naming-convention@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3): dependencies: - '@eslint-react/ast': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/core': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/jsx': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/shared': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/ast': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/core': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/jsx': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/shared': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.12.1 - '@typescript-eslint/type-utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/type-utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint: 9.13.0(jiti@2.3.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint: 9.14.0(jiti@2.4.0) ts-pattern: 5.5.0 optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: - supports-color - eslint-plugin-react-web-api@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3): + eslint-plugin-react-web-api@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3): dependencies: - '@eslint-react/ast': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/core': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/jsx': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/shared': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/ast': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/core': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/jsx': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/shared': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/var': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/var': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.12.1 '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) birecord: 0.1.1 - eslint: 9.13.0(jiti@2.3.3) + eslint: 9.14.0(jiti@2.4.0) ts-pattern: 5.5.0 optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: - supports-color - eslint-plugin-react-x@1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3): + eslint-plugin-react-x@1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3): dependencies: - '@eslint-react/ast': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/core': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/jsx': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/shared': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/ast': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/core': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/jsx': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/shared': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@eslint-react/tools': 1.15.2 - '@eslint-react/types': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@eslint-react/var': 1.15.2(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@eslint-react/types': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@eslint-react/var': 1.15.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.12.1 - '@typescript-eslint/type-utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/type-utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/types': 8.12.1 - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint: 9.13.0(jiti@2.3.3) - is-immutable-type: 5.0.0(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint: 9.14.0(jiti@2.4.0) + is-immutable-type: 5.0.0(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) ts-pattern: 5.5.0 optionalDependencies: typescript: 5.6.3 @@ -10279,27 +10367,27 @@ snapshots: postcss: 8.4.47 tailwindcss: 3.4.14 - eslint-scope@8.1.0: + eslint-scope@8.2.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.1.0: {} + eslint-visitor-keys@4.2.0: {} - eslint@9.13.0(jiti@2.3.3): + eslint@9.14.0(jiti@2.4.0): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.3.3)) - '@eslint-community/regexpp': 4.11.1 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.14.0(jiti@2.4.0)) + '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.18.0 '@eslint/core': 0.7.0 '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.13.0 + '@eslint/js': 9.14.0 '@eslint/plugin-kit': 0.2.0 - '@humanfs/node': 0.16.5 + '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.3.1 + '@humanwhocodes/retry': 0.4.0 '@types/estree': 1.0.6 '@types/json-schema': 7.0.15 ajv: 6.12.6 @@ -10307,9 +10395,9 @@ snapshots: cross-spawn: 7.0.3 debug: 4.3.7 escape-string-regexp: 4.0.0 - eslint-scope: 8.1.0 - eslint-visitor-keys: 4.1.0 - espree: 10.2.0 + eslint-scope: 8.2.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -10326,15 +10414,15 @@ snapshots: optionator: 0.9.4 text-table: 0.2.0 optionalDependencies: - jiti: 2.3.3 + jiti: 2.4.0 transitivePeerDependencies: - supports-color - espree@10.2.0: + espree@10.3.0: dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) - eslint-visitor-keys: 4.1.0 + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 esquery@1.6.0: dependencies: @@ -10576,7 +10664,7 @@ snapshots: fraction.js@4.3.7: {} - framer-motion@11.11.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + framer-motion@11.11.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: tslib: 2.7.0 optionalDependencies: @@ -11101,10 +11189,10 @@ snapshots: is-hexadecimal@2.0.1: {} - is-immutable-type@5.0.0(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3): + is-immutable-type@5.0.0(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3): dependencies: - '@typescript-eslint/type-utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - eslint: 9.13.0(jiti@2.3.3) + '@typescript-eslint/type-utils': 8.12.1(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + eslint: 9.14.0(jiti@2.4.0) ts-api-utils: 1.3.0(typescript@5.6.3) ts-declaration-location: 1.0.4(typescript@5.6.3) typescript: 5.6.3 @@ -11336,7 +11424,7 @@ snapshots: jiti@1.21.6: {} - jiti@2.3.3: {} + jiti@2.4.0: {} js-cookie@2.2.1: {} @@ -12672,7 +12760,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.8.2 + '@types/node': 22.8.6 long: 5.2.3 protons-runtime@5.5.0: @@ -13258,7 +13346,7 @@ snapshots: transitivePeerDependencies: - supports-color - sonner@1.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + sonner@1.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -13700,11 +13788,11 @@ snapshots: typedarray@0.0.6: {} - typescript-eslint@8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3): + typescript-eslint@8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.12.1(@typescript-eslint/parser@8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3))(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@typescript-eslint/parser': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) - '@typescript-eslint/utils': 8.12.1(eslint@9.13.0(jiti@2.3.3))(typescript@5.6.3) + '@typescript-eslint/eslint-plugin': 8.12.2(@typescript-eslint/parser@8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3))(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@typescript-eslint/parser': 8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) + '@typescript-eslint/utils': 8.12.2(eslint@9.14.0(jiti@2.4.0))(typescript@5.6.3) optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: @@ -13947,12 +14035,12 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-node@2.1.3(@types/node@22.8.2): + vite-node@2.1.3(@types/node@22.8.6): dependencies: cac: 6.7.14 debug: 4.3.7 pathe: 1.1.2 - vite: 5.4.10(@types/node@22.8.2) + vite: 5.4.10(@types/node@22.8.6) transitivePeerDependencies: - '@types/node' - less @@ -13964,24 +14052,24 @@ snapshots: - supports-color - terser - vite-plugin-svgr@4.2.0(rollup@4.21.3)(typescript@5.6.3)(vite@5.4.10(@types/node@22.8.2)): + vite-plugin-svgr@4.3.0(rollup@4.21.3)(typescript@5.6.3)(vite@5.4.10(@types/node@22.8.6)): dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.21.3) + '@rollup/pluginutils': 5.1.3(rollup@4.21.3) '@svgr/core': 8.1.0(typescript@5.6.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.6.3)) - vite: 5.4.10(@types/node@22.8.2) + vite: 5.4.10(@types/node@22.8.6) transitivePeerDependencies: - rollup - supports-color - typescript - vite@5.4.10(@types/node@22.8.2): + vite@5.4.10(@types/node@22.8.6): dependencies: esbuild: 0.21.5 postcss: 8.4.47 rollup: 4.21.3 optionalDependencies: - '@types/node': 22.8.2 + '@types/node': 22.8.6 fsevents: 2.3.3 watchpack@2.4.1: @@ -14166,7 +14254,7 @@ snapshots: bufferutil: 4.0.8 utf-8-validate: 6.0.4 - wxt@0.19.13(@types/node@22.8.2)(bufferutil@4.0.8)(rollup@4.21.3)(utf-8-validate@6.0.4): + wxt@0.19.13(@types/node@22.8.6)(bufferutil@4.0.8)(rollup@4.21.3)(utf-8-validate@6.0.4): dependencies: '@aklinker1/rollup-plugin-visualizer': 5.12.0(rollup@4.21.3) '@types/chrome': 0.0.269 @@ -14209,8 +14297,8 @@ snapshots: publish-browser-extension: 2.2.2 scule: 1.3.0 unimport: 3.13.1(rollup@4.21.3) - vite: 5.4.10(@types/node@22.8.2) - vite-node: 2.1.3(@types/node@22.8.2) + vite: 5.4.10(@types/node@22.8.6) + vite-node: 2.1.3(@types/node@22.8.6) web-ext-run: 0.2.1(bufferutil@4.0.8)(utf-8-validate@6.0.4) webextension-polyfill: 0.12.0 transitivePeerDependencies: diff --git a/src/app/content/components/MessageItem.tsx b/src/app/content/components/MessageItem.tsx index bb0b0a7..ce92931 100644 --- a/src/app/content/components/MessageItem.tsx +++ b/src/app/content/components/MessageItem.tsx @@ -58,7 +58,7 @@ const MessageItem: FC = (props) => {
{props.data.username}
- +
diff --git a/src/app/content/index.tsx b/src/app/content/index.tsx index 960b54a..20a2d77 100644 --- a/src/app/content/index.tsx +++ b/src/app/content/index.tsx @@ -56,13 +56,13 @@ export default defineContentScript({ container.append(app) const root = createRoot(app) root.render( - - - - - - - + // + + + + + + // ) return root }, diff --git a/src/app/content/views/Footer/index.tsx b/src/app/content/views/Footer/index.tsx index ad0f6bb..f67182d 100644 --- a/src/app/content/views/Footer/index.tsx +++ b/src/app/content/views/Footer/index.tsx @@ -5,7 +5,7 @@ import MessageInput from '../../components/MessageInput' import EmojiButton from '../../components/EmojiButton' import { Button } from '@/components/ui/Button' import MessageInputDomain from '@/domain/MessageInput' -import { MESSAGE_MAX_LENGTH } from '@/constants/config' +import { MESSAGE_MAX_LENGTH, WEB_RTC_MAX_MESSAGE_SIZE } from '@/constants/config' import RoomDomain from '@/domain/Room' import useCursorPosition from '@/hooks/useCursorPosition' import useShareRef from '@/hooks/useShareRef' @@ -15,7 +15,7 @@ import useTriggerAway from '@/hooks/useTriggerAway' import { ScrollArea } from '@/components/ui/ScrollArea' import { Virtuoso, VirtuosoHandle } from 'react-virtuoso' import UserInfoDomain from '@/domain/UserInfo' -import { blobToBase64, cn, compressImage, getRootNode, getTextSimilarity } from '@/utils' +import { blobToBase64, cn, compressImage, getRootNode, getTextByteSize, getTextSimilarity } from '@/utils' import { Avatar, AvatarFallback } from '@/components/ui/Avatar' import { AvatarImage } from '@radix-ui/react-avatar' import ToastDomain from '@/domain/Toast' @@ -136,6 +136,13 @@ const Footer: FC = () => { }) .filter(Boolean) + const newMessage = { body: transformedMessage, atUsers } + const byteSize = getTextByteSize(JSON.stringify(newMessage)) + + if (byteSize > WEB_RTC_MAX_MESSAGE_SIZE) { + return send(toastDomain.command.WarningCommand('Message size cannot exceed 256KiB.')) + } + send(roomDomain.command.SendTextMessageCommand({ body: transformedMessage, atUsers })) send(messageInputDomain.command.ClearCommand()) } diff --git a/src/app/content/views/Main/index.tsx b/src/app/content/views/Main/index.tsx index 36d3b44..f719116 100644 --- a/src/app/content/views/Main/index.tsx +++ b/src/app/content/views/Main/index.tsx @@ -15,16 +15,18 @@ const Main: FC = () => { const userInfoDomain = useRemeshDomain(UserInfoDomain()) const userInfo = useRemeshQuery(userInfoDomain.query.UserInfoQuery()) const _messageList = useRemeshQuery(messageListDomain.query.ListQuery()) - const messageList = _messageList.map((message) => { - if (message.type === MessageType.Normal) { - return { - ...message, - like: message.likeUsers.some((likeUser) => likeUser.userId === userInfo?.id), - hate: message.hateUsers.some((hateUser) => hateUser.userId === userInfo?.id) + const messageList = _messageList + .map((message) => { + if (message.type === MessageType.Normal) { + return { + ...message, + like: message.likeUsers.some((likeUser) => likeUser.userId === userInfo?.id), + hate: message.hateUsers.some((hateUser) => hateUser.userId === userInfo?.id) + } } - } - return message - }) + return message + }) + .toSorted((a, b) => a.sendTime - b.sendTime) const handleLikeChange = (messageId: string) => { send(roomDomain.command.SendLikeMessageCommand(messageId)) diff --git a/src/app/content/views/Setup/index.tsx b/src/app/content/views/Setup/index.tsx index a018be5..e738b95 100644 --- a/src/app/content/views/Setup/index.tsx +++ b/src/app/content/views/Setup/index.tsx @@ -33,8 +33,6 @@ const mockTextList = [ `![ExampleImage](${ExampleImage})` ] -let printTextList = [...mockTextList] - const generateUserInfo = async (): Promise => { return { id: nanoid(), @@ -52,8 +50,9 @@ const generateMessage = async (userInfo: UserInfo): Promise => { const { name: username, avatar: userAvatar, id: userId } = userInfo return { id: nanoid(), - body: printTextList.shift()!, - date: Date.now(), + body: mockTextList.shift()!, + sendTime: Date.now(), + receiveTime: Date.now(), type: MessageType.Normal, userId, username, @@ -87,19 +86,16 @@ const Setup: FC = () => { } useEffect(() => { - printTextList.length === 0 && (printTextList = [...mockTextList]) const timer = new Timer( async () => { await createMessage(await refreshUserInfo()) }, - { delay: 2000, immediate: true, limit: printTextList.length } + { delay: 2000, immediate: true, limit: mockTextList.length } ) - timer.on('stop', () => { - printTextList.length === 0 && send(messageListDomain.command.ClearListCommand()) - }) timer.start() return () => { timer.stop() + send(messageListDomain.command.ClearListCommand()) } }, []) diff --git a/src/constants/config.ts b/src/constants/config.ts index 78c8786..d509438 100644 --- a/src/constants/config.ts +++ b/src/constants/config.ts @@ -199,3 +199,11 @@ export const APP_STATUS_STORAGE_KEY = 'WEB_CHAT_APP_STATUS' as const * 8kb * (1 - 0.33) = 5488 bytes */ export const MAX_AVATAR_SIZE = 5120 as const + +export const SYNC_HISTORY_MAX_DAYS = 30 as const + +/** + * https://lgrahl.de/articles/demystifying-webrtc-dc-size-limit.html + * Message max size is 256KiB; if the message is too large, it will cause the connection to drop. + */ +export const WEB_RTC_MAX_MESSAGE_SIZE = 262144 as const diff --git a/src/domain/MessageList.ts b/src/domain/MessageList.ts index c715784..d97257b 100644 --- a/src/domain/MessageList.ts +++ b/src/domain/MessageList.ts @@ -24,7 +24,8 @@ export interface NormalMessage extends MessageUser { type: MessageType.Normal id: string body: string - date: number + sendTime: number + receiveTime: number likeUsers: MessageUser[] hateUsers: MessageUser[] atUsers: AtUser[] @@ -34,7 +35,8 @@ export interface PromptMessage extends MessageUser { type: MessageType.Prompt id: string body: string - date: number + sendTime: number + receiveTime: number } export type Message = NormalMessage | PromptMessage @@ -120,6 +122,38 @@ const MessageListDomain = Remesh.domain({ } }) + const UpsertItemCommand = domain.command({ + name: 'MessageList.UpsertItemCommand', + impl: (_, message: Message) => { + return [ + MessageListModule.command.UpsertItemCommand(message), + UpsertItemEvent(message), + ChangeListEvent(), + SyncToStorageEvent() + ] + } + }) + + const UpsertItemEvent = domain.event({ + name: 'MessageList.UpsertItemEvent' + }) + + const ResetListCommand = domain.command({ + name: 'MessageList.ResetListCommand', + impl: (_, messages: Message[]) => { + return [ + MessageListModule.command.SetListCommand(messages), + ResetListEvent(messages), + ChangeListEvent(), + SyncToStorageEvent() + ] + } + }) + + const ResetListEvent = domain.event({ + name: 'MessageList.ResetListEvent' + }) + const ClearListEvent = domain.event({ name: 'MessageList.ClearListEvent' }) @@ -164,14 +198,18 @@ const MessageListDomain = Remesh.domain({ CreateItemCommand, UpdateItemCommand, DeleteItemCommand, - ClearListCommand + UpsertItemCommand, + ClearListCommand, + ResetListCommand }, event: { ChangeListEvent, CreateItemEvent, UpdateItemEvent, DeleteItemEvent, + UpsertItemEvent, ClearListEvent, + ResetListEvent, SyncToStateEvent, SyncToStorageEvent } diff --git a/src/domain/Room.ts b/src/domain/Room.ts index 0dfd44b..6a57d53 100644 --- a/src/domain/Room.ts +++ b/src/domain/Room.ts @@ -4,33 +4,47 @@ import { AtUser, NormalMessage, type MessageUser } from './MessageList' import { PeerRoomExtern } from '@/domain/externs/PeerRoom' import MessageListDomain, { MessageType } from '@/domain/MessageList' import UserInfoDomain from '@/domain/UserInfo' -import { desert, upsert } from '@/utils' +import { desert, getTextByteSize, upsert } from '@/utils' import { nanoid } from 'nanoid' import StatusModule from '@/domain/modules/Status' +import { ToastExtern } from './externs/Toast' +import { SYNC_HISTORY_MAX_DAYS, WEB_RTC_MAX_MESSAGE_SIZE } from '@/constants/config' export { MessageType } export enum SendType { - Like = 'like', - Hate = 'hate', - Text = 'text', - Join = 'join' + Like = 'Like', + Hate = 'Hate', + Text = 'Text', + SyncUser = 'SyncUser', + SyncHistory = 'SyncHistory' } export interface SyncUserMessage extends MessageUser { - type: SendType.Join + type: SendType.SyncUser id: string peerId: string joinTime: number + sendTime: number + lastMessageTime: number +} + +export interface SyncHistoryMessage extends MessageUser { + type: SendType.SyncHistory + sendTime: number + id: string + messages: NormalMessage[] } export interface LikeMessage extends MessageUser { type: SendType.Like + sendTime: number id: string } export interface HateMessage extends MessageUser { type: SendType.Hate + sendTime: number id: string } @@ -38,10 +52,11 @@ export interface TextMessage extends MessageUser { type: SendType.Text id: string body: string + sendTime: number atUsers: AtUser[] } -export type RoomMessage = SyncUserMessage | LikeMessage | HateMessage | TextMessage +export type RoomMessage = SyncUserMessage | SyncHistoryMessage | LikeMessage | HateMessage | TextMessage export type RoomUser = MessageUser & { peerId: string; joinTime: number } @@ -50,6 +65,7 @@ const RoomDomain = Remesh.domain({ impl: (domain) => { const messageListDomain = domain.getDomain(MessageListDomain()) const userInfoDomain = domain.getDomain(UserInfoDomain()) + const toast = domain.getExtern(ToastExtern) const peerRoom = domain.getExtern(PeerRoomExtern) const PeerIdState = domain.state({ @@ -80,6 +96,24 @@ const RoomDomain = Remesh.domain({ } }) + const SelfUserQuery = domain.query({ + name: 'Room.SelfUserQuery', + impl: ({ get }) => { + return get(UserListQuery()).find((user) => user.peerId === get(PeerIdQuery()))! + } + }) + + const LastMessageTimeQuery = domain.query({ + name: 'Room.LastMessageTimeQuery', + impl: ({ get }) => { + return ( + get(messageListDomain.query.ListQuery()) + .filter((message) => message.type === MessageType.Normal) + .toSorted((a, b) => b.sendTime - a.sendTime)[0]?.sendTime ?? new Date(1970, 1, 1).getTime() + ) + } + }) + const JoinIsFinishedQuery = JoinStatusModule.query.IsFinishedQuery const JoinRoomCommand = domain.command({ @@ -100,7 +134,8 @@ const RoomDomain = Remesh.domain({ userAvatar, body: `"${username}" joined the chat`, type: MessageType.Prompt, - date: Date.now() + sendTime: Date.now(), + receiveTime: Date.now() }), JoinStatusModule.command.SetFinishedCommand(), JoinRoomEvent(peerRoom.roomId) @@ -121,7 +156,8 @@ const RoomDomain = Remesh.domain({ userAvatar, body: `"${username}" left the chat`, type: MessageType.Prompt, - date: Date.now() + sendTime: Date.now(), + receiveTime: Date.now() }), UpdateUserListCommand({ type: 'delete', @@ -136,22 +172,21 @@ const RoomDomain = Remesh.domain({ const SendTextMessageCommand = domain.command({ name: 'Room.SendTextMessageCommand', impl: ({ get }, message: string | { body: string; atUsers: AtUser[] }) => { - const { id: userId, name: username, avatar: userAvatar } = get(userInfoDomain.query.UserInfoQuery())! + const self = get(SelfUserQuery()) const textMessage: TextMessage = { + ...self, id: nanoid(), type: SendType.Text, + sendTime: Date.now(), body: typeof message === 'string' ? message : message.body, - userId, - username, - userAvatar, atUsers: typeof message === 'string' ? [] : message.atUsers } const listMessage: NormalMessage = { ...textMessage, type: MessageType.Normal, - date: Date.now(), + receiveTime: Date.now(), likeUsers: [], hateUsers: [], atUsers: typeof message === 'string' ? [] : message.atUsers @@ -165,14 +200,13 @@ const RoomDomain = Remesh.domain({ const SendLikeMessageCommand = domain.command({ name: 'Room.SendLikeMessageCommand', impl: ({ get }, messageId: string) => { - const { id: userId, name: username, avatar: userAvatar } = get(userInfoDomain.query.UserInfoQuery())! + const self = get(SelfUserQuery()) const localMessage = get(messageListDomain.query.ItemQuery(messageId)) as NormalMessage const likeMessage: LikeMessage = { + ...self, id: messageId, - userId, - username, - userAvatar, + sendTime: Date.now(), type: SendType.Like } const listMessage: NormalMessage = { @@ -187,14 +221,13 @@ const RoomDomain = Remesh.domain({ const SendHateMessageCommand = domain.command({ name: 'Room.SendHateMessageCommand', impl: ({ get }, messageId: string) => { - const { id: userId, name: username, avatar: userAvatar } = get(userInfoDomain.query.UserInfoQuery())! + const self = get(SelfUserQuery()) const localMessage = get(messageListDomain.query.ItemQuery(messageId)) as NormalMessage const hateMessage: HateMessage = { + ...self, id: messageId, - userId, - username, - userAvatar, + sendTime: Date.now(), type: SendType.Hate } const listMessage: NormalMessage = { @@ -206,19 +239,90 @@ const RoomDomain = Remesh.domain({ } }) - const SendJoinMessageCommand = domain.command({ - name: 'Room.SendJoinMessageCommand', - impl: ({ get }, targetPeerId: string) => { - const self = get(UserListQuery()).find((user) => user.peerId === peerRoom.peerId)! + const SendSyncUserMessageCommand = domain.command({ + name: 'Room.SendSyncUserMessageCommand', + impl: ({ get }, peerId: string) => { + const self = get(SelfUserQuery()) + const lastMessageTime = get(LastMessageTimeQuery()) const syncUserMessage: SyncUserMessage = { ...self, id: nanoid(), - type: SendType.Join + sendTime: Date.now(), + lastMessageTime, + type: SendType.SyncUser } - peerRoom.sendMessage(syncUserMessage, targetPeerId) - return [SendJoinMessageEvent(syncUserMessage)] + peerRoom.sendMessage(syncUserMessage, peerId) + return [SendSyncUserMessageEvent(syncUserMessage)] + } + }) + + /** + * The maximum sync message is the historical records within 30 days, using the last message as the basis for judgment. + * The number of synced messages may not be all messages within 30 days; if new messages are generated before syncing, they will not be synced. + * Users A, B, C, D, and E: A and B are online, while C, D, and E are offline. + * 1. A and B chat, generating two messages: messageA and messageB. + * 2. A and B go offline. + * 3. C and D come online, generating two messages: messageC and messageD. + * 4. A and B come online, and C and D will push two messages, messageC and messageD, to A and B. However, A and B will not push messageA and messageB to C and D because C and D's latest message timestamps are earlier than A and B's. + * 5. E comes online, and A, B, C, and D will all push messages messageA, messageB, messageC, and messageD to E. + * + * Final results: + * A and B see 4 messages: messageC, messageD, messageA, and messageB. + * C and D see 2 messages: messageA and messageB. + * E sees 4 messages: messageA, messageB, messageC, and messageD. + * + * As shown above, C and D did not sync messages that were earlier than their own. + * On one hand, if we want to fully sync 30 days of messages, we must diff the timestamps of messages within 30 days and then insert them. The current implementation only does incremental additions, and messages will accumulate over time. + * For now, let's keep it this way and see if it's necessary to fully sync the data within 30 days later. + */ + const SendSyncHistoryMessageCommand = domain.command({ + name: 'Room.SendSyncHistoryMessageCommand', + impl: ({ get }, { peerId, lastMessageTime }: { peerId: string; lastMessageTime: number }) => { + const self = get(SelfUserQuery()) + console.log('SendSyncHistoryMessageCommand', peerId, peerRoom.peerId) + + const historyMessages = get(messageListDomain.query.ListQuery()).filter( + (message) => + message.type === MessageType.Normal && + message.sendTime > lastMessageTime && + message.sendTime - Date.now() <= SYNC_HISTORY_MAX_DAYS * 24 * 60 * 60 * 1000 + ) + + /** + * Message chunking to ensure that each message does not exceed WEB_RTC_MAX_MESSAGE_SIZE + * If the message itself exceeds the size limit, skip syncing that message directly. + */ + const pushHistoryMessageList = historyMessages.reduce((acc, cur) => { + const pushHistoryMessage: SyncHistoryMessage = { + ...self, + id: nanoid(), + sendTime: Date.now(), + type: SendType.SyncHistory, + messages: [cur as NormalMessage] + } + const pushHistoryMessageByteSize = getTextByteSize(JSON.stringify(pushHistoryMessage)) + + if (pushHistoryMessageByteSize < WEB_RTC_MAX_MESSAGE_SIZE) { + if (acc.length) { + const mergedSize = getTextByteSize(JSON.stringify(acc[acc.length - 1])) + pushHistoryMessageByteSize + if (mergedSize < WEB_RTC_MAX_MESSAGE_SIZE) { + acc[acc.length - 1].messages.push(cur as NormalMessage) + } else { + acc.push(pushHistoryMessage) + } + } else { + acc.push(pushHistoryMessage) + } + } + return acc + }, []) + + return pushHistoryMessageList.map((message) => { + peerRoom.sendMessage(message, peerId) + return SendSyncHistoryMessageEvent(message) + }) } }) @@ -234,8 +338,12 @@ const RoomDomain = Remesh.domain({ } }) - const SendJoinMessageEvent = domain.event({ - name: 'Room.SendJoinMessageEvent' + const SendSyncHistoryMessageEvent = domain.event({ + name: 'Room.SendSyncHistoryMessageEvent' + }) + + const SendSyncUserMessageEvent = domain.event({ + name: 'Room.SendSyncUserMessageEvent' }) const SendTextMessageEvent = domain.event({ @@ -287,7 +395,7 @@ const RoomDomain = Remesh.domain({ if (peerRoom.peerId === peerId) { return [OnJoinRoomEvent(peerId)] } else { - return [SendJoinMessageCommand(peerId), OnJoinRoomEvent(peerId)] + return [SendSyncUserMessageCommand(peerId), OnJoinRoomEvent(peerId)] } }) ) @@ -308,16 +416,19 @@ const RoomDomain = Remesh.domain({ const messageCommand$ = (() => { switch (message.type) { - case SendType.Join: { + case SendType.SyncUser: { const userList = get(UserListQuery()) - const selfUser = userList.find((user) => user.peerId === peerRoom.peerId)! + const selfUser = get(SelfUserQuery()) // If the browser has multiple tabs open, it can cause the same user to join multiple times with the same peerId but different userId - const isSelfJoinEvent = !!userList.find((user) => user.userId === message.userId) + const isRepeatJoin = userList.some((user) => user.userId === message.userId) // When a new user joins, it triggers join events for all users, i.e., newUser join event and oldUser join event // Use joinTime to determine if it's a new user const isNewJoinEvent = selfUser.joinTime < message.joinTime - return isSelfJoinEvent + const lastMessageTime = get(LastMessageTimeQuery()) + const needSyncHistory = lastMessageTime > message.lastMessageTime + + return isRepeatJoin ? EMPTY : of( UpdateUserListCommand({ type: 'create', user: message }), @@ -327,17 +438,29 @@ const RoomDomain = Remesh.domain({ id: nanoid(), body: `"${message.username}" joined the chat`, type: MessageType.Prompt, - date: Date.now() + receiveTime: Date.now() + }) + : null, + needSyncHistory + ? SendSyncHistoryMessageCommand({ + peerId: message.peerId, + lastMessageTime: message.lastMessageTime }) : null ) } + + case SendType.SyncHistory: { + toast.success('Syncing history messages.') + return of(...message.messages.map((message) => messageListDomain.command.UpsertItemCommand(message))) + } + case SendType.Text: return of( messageListDomain.command.CreateItemCommand({ ...message, type: MessageType.Normal, - date: Date.now(), + receiveTime: Date.now(), likeUsers: [], hateUsers: [] }) @@ -348,10 +471,11 @@ const RoomDomain = Remesh.domain({ return EMPTY } const _message = get(messageListDomain.query.ItemQuery(message.id)) as NormalMessage - const type = message.type === 'like' ? 'likeUsers' : 'hateUsers' + const type = message.type === 'Like' ? 'likeUsers' : 'hateUsers' return of( messageListDomain.command.UpdateItemCommand({ ..._message, + receiveTime: Date.now(), [type]: desert( _message[type], { @@ -382,7 +506,7 @@ const RoomDomain = Remesh.domain({ impl: ({ get }) => { const onLeaveRoom$ = fromEventPattern(peerRoom.onLeaveRoom).pipe( map((peerId) => { - // console.log('onLeaveRoom', peerId) + console.log('onLeaveRoom', peerId, get(SelfUserQuery()).peerId) const user = get(UserListQuery()).find((user) => user.peerId === peerId) if (user) { @@ -393,7 +517,8 @@ const RoomDomain = Remesh.domain({ id: nanoid(), body: `"${user.username}" left the chat`, type: MessageType.Prompt, - date: Date.now() + sendTime: Date.now(), + receiveTime: Date.now() }), OnLeaveRoomEvent(peerId) ] @@ -425,6 +550,8 @@ const RoomDomain = Remesh.domain({ impl: ({ get }) => { const beforeUnload$ = fromEvent(window, 'beforeunload').pipe( map(() => { + console.log('beforeunload') + return get(JoinStatusModule.query.IsFinishedQuery()) ? LeaveRoomCommand() : null }) ) @@ -444,13 +571,15 @@ const RoomDomain = Remesh.domain({ SendTextMessageCommand, SendLikeMessageCommand, SendHateMessageCommand, - SendJoinMessageCommand + SendSyncUserMessageCommand, + SendSyncHistoryMessageCommand }, event: { SendTextMessageEvent, SendLikeMessageEvent, SendHateMessageEvent, - SendJoinMessageEvent, + SendSyncUserMessageEvent, + SendSyncHistoryMessageEvent, JoinRoomEvent, LeaveRoomEvent, OnMessageEvent, diff --git a/src/domain/impls/PeerRoom2.ts b/src/domain/impls/PeerRoom2.ts index 64cd1c1..2336d70 100644 --- a/src/domain/impls/PeerRoom2.ts +++ b/src/domain/impls/PeerRoom2.ts @@ -5,6 +5,8 @@ import { stringToHex } from '@/utils' import { nanoid } from 'nanoid' import EventHub from '@resreq/event-hub' import { RoomMessage } from '../Room' +import { JSONR } from '@/utils' + export interface Config { peerId?: string roomId: string @@ -50,11 +52,11 @@ class PeerRoom extends EventHub { if (!this.room) { this.emit('error', new Error('Room not joined')) } else { - this.room.send(JSON.stringify(message), id) + this.room.send(JSONR.stringify(message)!, id) } }) } else { - this.room.send(JSON.stringify(message), id) + this.room.send(JSONR.stringify(message)!, id) } return this } @@ -65,11 +67,11 @@ class PeerRoom extends EventHub { if (!this.room) { this.emit('error', new Error('Room not joined')) } else { - this.room.on('message', (message) => callback(JSON.parse(message) as RoomMessage)) + this.room.on('message', (message) => callback(JSONR.parse(message) as RoomMessage)) } }) } else { - this.room.on('message', (message) => callback(JSON.parse(message) as RoomMessage)) + this.room.on('message', (message) => callback(JSONR.parse(message) as RoomMessage)) } return this } diff --git a/src/domain/impls/Storage.ts b/src/domain/impls/Storage.ts index f3047dc..fba5ebb 100644 --- a/src/domain/impls/Storage.ts +++ b/src/domain/impls/Storage.ts @@ -7,6 +7,7 @@ import { webExtensionDriver } from '@/utils/webExtensionDriver' import { Storage } from '@/domain/externs/Storage' import { EVENT } from '@/constants/event' +import { JSONR } from '@/utils' export const localStorage = createStorage({ driver: localStorageDriver({ base: `${STORAGE_NAME}:` }) @@ -22,8 +23,8 @@ export const browserSyncStorage = createStorage({ export const LocalStorageImpl = LocalStorageExtern.impl({ name: STORAGE_NAME, - get: localStorage.getItem, - set: localStorage.setItem, + get: async (key) => JSONR.parse(await localStorage.getItem(key)), + set: (key, value) => localStorage.setItem(key, JSONR.stringify(value)!), remove: localStorage.removeItem, clear: localStorage.clear, watch: async (callback) => { @@ -45,8 +46,8 @@ export const LocalStorageImpl = LocalStorageExtern.impl({ export const IndexDBStorageImpl = IndexDBStorageExtern.impl({ name: STORAGE_NAME, - get: indexDBStorage.getItem, - set: indexDBStorage.setItem, + get: async (key) => JSONR.parse(await indexDBStorage.getItem(key)), + set: (key, value) => indexDBStorage.setItem(key, JSONR.stringify(value)), remove: indexDBStorage.removeItem, clear: indexDBStorage.clear, watch: indexDBStorage.watch as Storage['watch'], @@ -55,8 +56,8 @@ export const IndexDBStorageImpl = IndexDBStorageExtern.impl({ export const BrowserSyncStorageImpl = BrowserSyncStorageExtern.impl({ name: STORAGE_NAME, - get: browserSyncStorage.getItem, - set: browserSyncStorage.setItem, + get: async (key) => JSONR.parse(await browserSyncStorage.getItem(key)), + set: (key, value) => browserSyncStorage.setItem(key, JSONR.stringify(value)), remove: browserSyncStorage.removeItem, clear: browserSyncStorage.clear, watch: browserSyncStorage.watch as Storage['watch'], diff --git a/src/utils/getTextByteSize.ts b/src/utils/getTextByteSize.ts new file mode 100644 index 0000000..8bafcb8 --- /dev/null +++ b/src/utils/getTextByteSize.ts @@ -0,0 +1,3 @@ +export const getTextByteSize = (text: string) => { + return new TextEncoder().encode(text).length +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 05865ff..d5e36d2 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -15,3 +15,5 @@ export { default as getCursorPosition } from './getCursorPosition' export { default as getTextSimilarity } from './getTextSimilarity' export { default as getRootNode } from './getRootNode' export { default as blobToBase64 } from './blobToBase64' +export * as JSONR from './jsonr' +export { getTextByteSize } from './getTextByteSize' diff --git a/src/utils/jsonr.ts b/src/utils/jsonr.ts new file mode 100644 index 0000000..cc24233 --- /dev/null +++ b/src/utils/jsonr.ts @@ -0,0 +1,10 @@ +import JSONR from '@perfsee/jsonr' +import { isNullish } from '@/utils' + +export const parse = (value: string | number | boolean | null): T | null => { + return !isNullish(value) ? JSONR.parse(value!.toString()) : null +} + +export const stringify = (value: any): string | null => { + return !isNullish(value) ? JSONR.stringify(value) : null +}