diff --git a/cli/package-lock.json b/cli/package-lock.json index 9464f86663..5373f3cdd1 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1370,17 +1370,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz", - "integrity": "sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", + "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/type-utils": "8.33.0", - "@typescript-eslint/utils": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/type-utils": "8.32.1", + "@typescript-eslint/utils": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -1394,7 +1394,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.33.0", + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -1410,16 +1410,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz", - "integrity": "sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz", + "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/typescript-estree": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4" }, "engines": { @@ -1434,34 +1434,15 @@ "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz", - "integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.33.0", - "@typescript-eslint/types": "^8.33.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz", - "integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0" + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1471,32 +1452,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz", - "integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz", - "integrity": "sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", + "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.33.0", - "@typescript-eslint/utils": "8.33.0", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/utils": "8.32.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -1513,9 +1477,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz", - "integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", "dev": true, "license": "MIT", "engines": { @@ -1527,16 +1491,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz", - "integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.33.0", - "@typescript-eslint/tsconfig-utils": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1582,16 +1544,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz", - "integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/typescript-estree": "8.33.0" + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1606,13 +1568,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz", - "integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/types": "8.32.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2794,9 +2756,9 @@ } }, "node_modules/globals": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz", - "integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", + "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", "dev": true, "license": "MIT", "engines": { @@ -4238,15 +4200,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.0.tgz", - "integrity": "sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz", + "integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.33.0", - "@typescript-eslint/parser": "8.33.0", - "@typescript-eslint/utils": "8.33.0" + "@typescript-eslint/eslint-plugin": "8.32.1", + "@typescript-eslint/parser": "8.32.1", + "@typescript-eslint/utils": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/docs/package-lock.json b/docs/package-lock.json index ce1ba4cd9d..602232da07 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -8,8 +8,8 @@ "name": "documentation", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "~3.8.0", - "@docusaurus/preset-classic": "~3.8.0", + "@docusaurus/core": "~3.7.0", + "@docusaurus/preset-classic": "~3.7.0", "@mdi/js": "^7.3.67", "@mdi/react": "^1.6.1", "@mdx-js/react": "^3.0.0", @@ -27,7 +27,7 @@ "url": "^0.11.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "~3.8.0", + "@docusaurus/module-type-aliases": "~3.7.0", "@docusaurus/tsconfig": "^3.7.0", "@docusaurus/types": "^3.7.0", "prettier": "^3.2.4", @@ -3128,9 +3128,9 @@ } }, "node_modules/@docusaurus/babel": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.8.0.tgz", - "integrity": "sha512-9EJwSgS6TgB8IzGk1L8XddJLhZod8fXT4ULYMx6SKqyCBqCFpVCEjR/hNXXhnmtVM2irDuzYoVLGWv7srG/VOA==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.7.0.tgz", + "integrity": "sha512-0H5uoJLm14S/oKV3Keihxvh8RV+vrid+6Gv+2qhuzbqHanawga8tYnsdpjEyt36ucJjqlby2/Md2ObWjA02UXQ==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", @@ -3143,8 +3143,8 @@ "@babel/runtime": "^7.25.9", "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/utils": "3.7.0", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -3154,17 +3154,17 @@ } }, "node_modules/@docusaurus/bundler": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.8.0.tgz", - "integrity": "sha512-Rq4Z/MSeAHjVzBLirLeMcjLIAQy92pF1OI+2rmt18fSlMARfTGLWRE8Vb+ljQPTOSfJxwDYSzsK6i7XloD2rNA==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.7.0.tgz", + "integrity": "sha512-CUUT9VlSGukrCU5ctZucykvgCISivct+cby28wJwCC/fkQFgAHRp/GKv2tx38ZmXb7nacrKzFTcp++f9txUYGg==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.8.0", - "@docusaurus/cssnano-preset": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/babel": "3.7.0", + "@docusaurus/cssnano-preset": "3.7.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils": "3.7.0", "babel-loader": "^9.2.1", "clean-css": "^5.3.2", "copy-webpack-plugin": "^11.0.0", @@ -3178,6 +3178,7 @@ "postcss": "^8.4.26", "postcss-loader": "^7.3.3", "postcss-preset-env": "^10.1.0", + "react-dev-utils": "^12.0.1", "terser-webpack-plugin": "^5.3.9", "tslib": "^2.6.0", "url-loader": "^4.1.1", @@ -3197,18 +3198,18 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.8.0.tgz", - "integrity": "sha512-c7u6zFELmSGPEP9WSubhVDjgnpiHgDqMh1qVdCB7rTflh4Jx0msTYmMiO91Ez0KtHj4sIsDsASnjwfJ2IZp3Vw==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.7.0.tgz", + "integrity": "sha512-b0fUmaL+JbzDIQaamzpAFpTviiaU4cX3Qz8cuo14+HGBCwa0evEK0UYCBFY3n4cLzL8Op1BueeroUD2LYAIHbQ==", "license": "MIT", "dependencies": { - "@docusaurus/babel": "3.8.0", - "@docusaurus/bundler": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/babel": "3.7.0", + "@docusaurus/bundler": "3.7.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/mdx-loader": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-common": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -3216,19 +3217,19 @@ "combine-promises": "^1.1.0", "commander": "^5.1.0", "core-js": "^3.31.1", + "del": "^6.1.1", "detect-port": "^1.5.1", "escape-html": "^1.0.3", "eta": "^2.2.0", "eval": "^0.1.8", - "execa": "5.1.1", "fs-extra": "^11.1.1", "html-tags": "^3.3.1", "html-webpack-plugin": "^5.6.0", "leven": "^3.1.0", "lodash": "^4.17.21", - "open": "^8.4.0", "p-map": "^4.0.0", "prompts": "^2.4.2", + "react-dev-utils": "^12.0.1", "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", "react-loadable-ssr-addon-v5-slorber": "^1.0.1", @@ -3237,7 +3238,7 @@ "react-router-dom": "^5.3.4", "semver": "^7.5.4", "serve-handler": "^6.1.6", - "tinypool": "^1.0.2", + "shelljs": "^0.8.5", "tslib": "^2.6.0", "update-notifier": "^6.0.2", "webpack": "^5.95.0", @@ -3258,9 +3259,9 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.8.0.tgz", - "integrity": "sha512-UJ4hAS2T0R4WNy+phwVff2Q0L5+RXW9cwlH6AEphHR5qw3m/yacfWcSK7ort2pMMbDn8uGrD38BTm4oLkuuNoQ==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.7.0.tgz", + "integrity": "sha512-X9GYgruZBSOozg4w4dzv9uOz8oK/EpPVQXkp0MM6Tsgp/nRIU9hJzJ0Pxg1aRa3xCeEQTOimZHcocQFlLwYajQ==", "license": "MIT", "dependencies": { "cssnano-preset-advanced": "^6.1.2", @@ -3273,9 +3274,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.8.0.tgz", - "integrity": "sha512-7eEMaFIam5Q+v8XwGqF/n0ZoCld4hV4eCCgQkfcN9Mq5inoZa6PHHW9Wu6lmgzoK5Kx3keEeABcO2SxwraoPDQ==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.7.0.tgz", + "integrity": "sha512-z7g62X7bYxCYmeNNuO9jmzxLQG95q9QxINCwpboVcNff3SJiHJbGrarxxOVMVmAh1MsrSfxWkVGv4P41ktnFsA==", "license": "MIT", "dependencies": { "chalk": "^4.1.2", @@ -3286,21 +3287,21 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.8.0.tgz", - "integrity": "sha512-mDPSzssRnpjSdCGuv7z2EIAnPS1MHuZGTaRLwPn4oQwszu4afjWZ/60sfKjTnjBjI8Vl4OgJl2vMmfmiNDX4Ng==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.7.0.tgz", + "integrity": "sha512-OFBG6oMjZzc78/U3WNPSHs2W9ZJ723ewAcvVJaqS0VgyeUfmzUV8f1sv+iUHA0DtwiR5T5FjOxj6nzEE8LY6VA==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", "estree-util-value-to-estree": "^3.0.1", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", - "image-size": "^2.0.2", + "image-size": "^1.0.2", "mdast-util-mdx": "^3.0.0", "mdast-util-to-string": "^4.0.0", "rehype-raw": "^7.0.0", @@ -3325,17 +3326,17 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.8.0.tgz", - "integrity": "sha512-/uMb4Ipt5J/QnD13MpnoC/A4EYAe6DKNWqTWLlGrqsPJwJv73vSwkA25xnYunwfqWk0FlUQfGv/Swdh5eCCg7g==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.7.0.tgz", + "integrity": "sha512-g7WdPqDNaqA60CmBrr0cORTrsOit77hbsTj7xE2l71YhBn79sxdm7WMK7wfhcaafkbpIh7jv5ef5TOpf1Xv9Lg==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.8.0", + "@docusaurus/types": "3.7.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", "@types/react-router-dom": "*", - "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", + "react-helmet-async": "npm:@slorber/react-helmet-async@*", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" }, "peerDependencies": { @@ -3344,24 +3345,24 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.8.0.tgz", - "integrity": "sha512-0SlOTd9R55WEr1GgIXu+hhTT0hzARYx3zIScA5IzpdekZQesI/hKEa5LPHBd415fLkWMjdD59TaW/3qQKpJ0Lg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.7.0.tgz", + "integrity": "sha512-EFLgEz6tGHYWdPU0rK8tSscZwx+AsyuBW/r+tNig2kbccHYGUJmZtYN38GjAa3Fda4NU+6wqUO5kTXQSRBQD3g==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.7.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/mdx-loader": "3.7.0", + "@docusaurus/theme-common": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-common": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "cheerio": "1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", "lodash": "^4.17.21", - "schema-dts": "^1.1.2", + "reading-time": "^1.5.0", "srcset": "^4.0.0", "tslib": "^2.6.0", "unist-util-visit": "^5.0.0", @@ -3378,26 +3379,25 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.8.0.tgz", - "integrity": "sha512-fRDMFLbUN6eVRXcjP8s3Y7HpAt9pzPYh1F/7KKXOCxvJhjjCtbon4VJW0WndEPInVz4t8QUXn5QZkU2tGVCE2g==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.7.0.tgz", + "integrity": "sha512-GXg5V7kC9FZE4FkUZA8oo/NrlRb06UwuICzI6tcbzj0+TVgjq/mpUXXzSgKzMS82YByi4dY2Q808njcBCyy6tQ==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.7.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/mdx-loader": "3.7.0", + "@docusaurus/module-type-aliases": "3.7.0", + "@docusaurus/theme-common": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-common": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "schema-dts": "^1.1.2", "tslib": "^2.6.0", "utility-types": "^3.10.0", "webpack": "^5.88.1" @@ -3411,16 +3411,16 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.8.0.tgz", - "integrity": "sha512-39EDx2y1GA0Pxfion5tQZLNJxL4gq6susd1xzetVBjVIQtwpCdyloOfQBAgX0FylqQxfJrYqL0DIUuq7rd7uBw==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.7.0.tgz", + "integrity": "sha512-YJSU3tjIJf032/Aeao8SZjFOrXJbz/FACMveSMjLyMH4itQyZ2XgUIzt4y+1ISvvk5zrW4DABVT2awTCqBkx0Q==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.7.0", + "@docusaurus/mdx-loader": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -3433,32 +3433,17 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/@docusaurus/plugin-css-cascade-layers": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.8.0.tgz", - "integrity": "sha512-/VBTNymPIxQB8oA3ZQ4GFFRYdH4ZxDRRBECxyjRyv486mfUPXfcdk+im4S5mKWa6EK2JzBz95IH/Wu0qQgJ5yQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - } - }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.8.0.tgz", - "integrity": "sha512-teonJvJsDB9o2OnG6ifbhblg/PXzZvpUKHFgD8dOL1UJ58u0lk8o0ZOkvaYEBa9nDgqzoWrRk9w+e3qaG2mOhQ==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.7.0.tgz", + "integrity": "sha512-Qgg+IjG/z4svtbCNyTocjIwvNTNEwgRjSXXSJkKVG0oWoH0eX/HAPiu+TS1HBwRPQV+tTYPWLrUypYFepfujZA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/core": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils": "3.7.0", "fs-extra": "^11.1.1", - "react-json-view-lite": "^2.3.0", + "react-json-view-lite": "^1.2.0", "tslib": "^2.6.0" }, "engines": { @@ -3470,14 +3455,14 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.8.0.tgz", - "integrity": "sha512-aKKa7Q8+3xRSRESipNvlFgNp3FNPELKhuo48Cg/svQbGNwidSHbZT03JqbW4cBaQnyyVchO1ttk+kJ5VC9Gx0w==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.7.0.tgz", + "integrity": "sha512-otIqiRV/jka6Snjf+AqB360XCeSv7lQC+DKYW+EUZf6XbuE8utz5PeUQ8VuOcD8Bk5zvT1MC4JKcd5zPfDuMWA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "tslib": "^2.6.0" }, "engines": { @@ -3489,14 +3474,14 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.8.0.tgz", - "integrity": "sha512-ugQYMGF4BjbAW/JIBtVcp+9eZEgT9HRdvdcDudl5rywNPBA0lct+lXMG3r17s02rrhInMpjMahN3Yc9Cb3H5/g==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.7.0.tgz", + "integrity": "sha512-M3vrMct1tY65ModbyeDaMoA+fNJTSPe5qmchhAbtqhDD/iALri0g9LrEpIOwNaoLmm6lO88sfBUADQrSRSGSWA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, @@ -3509,14 +3494,14 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.8.0.tgz", - "integrity": "sha512-9juRWxbwZD3SV02Jd9QB6yeN7eu+7T4zB0bvJLcVQwi+am51wAxn2CwbdL0YCCX+9OfiXbADE8D8Q65Hbopu/w==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.7.0.tgz", + "integrity": "sha512-X8U78nb8eiMiPNg3jb9zDIVuuo/rE1LjGDGu+5m5CX4UBZzjMy+klOY2fNya6x8ACyE/L3K2erO1ErheP55W/w==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "tslib": "^2.6.0" }, "engines": { @@ -3528,17 +3513,17 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.8.0.tgz", - "integrity": "sha512-fGpOIyJvNiuAb90nSJ2Gfy/hUOaDu6826e5w5UxPmbpCIc7KlBHNAZ5g4L4ZuHhc4hdfq4mzVBsQSnne+8Ze1g==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.7.0.tgz", + "integrity": "sha512-bTRT9YLZ/8I/wYWKMQke18+PF9MV8Qub34Sku6aw/vlZ/U+kuEuRpQ8bTcNOjaTSfYsWkK4tTwDMHK2p5S86cA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.7.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-common": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -3552,15 +3537,15 @@ } }, "node_modules/@docusaurus/plugin-svgr": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.8.0.tgz", - "integrity": "sha512-kEDyry+4OMz6BWLG/lEqrNsL/w818bywK70N1gytViw4m9iAmoxCUT7Ri9Dgs7xUdzCHJ3OujolEmD88Wy44OA==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.7.0.tgz", + "integrity": "sha512-HByXIZTbc4GV5VAUkZ2DXtXv1Qdlnpk3IpuImwSnEzCDBkUMYcec5282hPjn6skZqB25M1TYCmWS91UbhBGxQg==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "@svgr/core": "8.1.0", "@svgr/webpack": "^8.1.0", "tslib": "^2.6.0", @@ -3575,26 +3560,25 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.8.0.tgz", - "integrity": "sha512-qOu6tQDOWv+rpTlKu+eJATCJVGnABpRCPuqf7LbEaQ1mNY//N/P8cHQwkpAU+aweQfarcZ0XfwCqRHJfjeSV/g==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.7.0.tgz", + "integrity": "sha512-nPHj8AxDLAaQXs+O6+BwILFuhiWbjfQWrdw2tifOClQoNfuXDjfjogee6zfx6NGHWqshR23LrcN115DmkHC91Q==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/plugin-content-blog": "3.8.0", - "@docusaurus/plugin-content-docs": "3.8.0", - "@docusaurus/plugin-content-pages": "3.8.0", - "@docusaurus/plugin-css-cascade-layers": "3.8.0", - "@docusaurus/plugin-debug": "3.8.0", - "@docusaurus/plugin-google-analytics": "3.8.0", - "@docusaurus/plugin-google-gtag": "3.8.0", - "@docusaurus/plugin-google-tag-manager": "3.8.0", - "@docusaurus/plugin-sitemap": "3.8.0", - "@docusaurus/plugin-svgr": "3.8.0", - "@docusaurus/theme-classic": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-search-algolia": "3.8.0", - "@docusaurus/types": "3.8.0" + "@docusaurus/core": "3.7.0", + "@docusaurus/plugin-content-blog": "3.7.0", + "@docusaurus/plugin-content-docs": "3.7.0", + "@docusaurus/plugin-content-pages": "3.7.0", + "@docusaurus/plugin-debug": "3.7.0", + "@docusaurus/plugin-google-analytics": "3.7.0", + "@docusaurus/plugin-google-gtag": "3.7.0", + "@docusaurus/plugin-google-tag-manager": "3.7.0", + "@docusaurus/plugin-sitemap": "3.7.0", + "@docusaurus/plugin-svgr": "3.7.0", + "@docusaurus/theme-classic": "3.7.0", + "@docusaurus/theme-common": "3.7.0", + "@docusaurus/theme-search-algolia": "3.7.0", + "@docusaurus/types": "3.7.0" }, "engines": { "node": ">=18.0" @@ -3605,24 +3589,24 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.8.0.tgz", - "integrity": "sha512-nQWFiD5ZjoT76OaELt2n33P3WVuuCz8Dt5KFRP2fCBo2r9JCLsp2GJjZpnaG24LZ5/arRjv4VqWKgpK0/YLt7g==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.7.0.tgz", + "integrity": "sha512-MnLxG39WcvLCl4eUzHr0gNcpHQfWoGqzADCly54aqCofQX6UozOS9Th4RK3ARbM9m7zIRv3qbhggI53dQtx/hQ==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/plugin-content-blog": "3.8.0", - "@docusaurus/plugin-content-docs": "3.8.0", - "@docusaurus/plugin-content-pages": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-translations": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.7.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/mdx-loader": "3.7.0", + "@docusaurus/module-type-aliases": "3.7.0", + "@docusaurus/plugin-content-blog": "3.7.0", + "@docusaurus/plugin-content-docs": "3.7.0", + "@docusaurus/plugin-content-pages": "3.7.0", + "@docusaurus/theme-common": "3.7.0", + "@docusaurus/theme-translations": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-common": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "copy-text-to-clipboard": "^3.2.0", @@ -3646,15 +3630,15 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.8.0.tgz", - "integrity": "sha512-YqV2vAWpXGLA+A3PMLrOMtqgTHJLDcT+1Caa6RF7N4/IWgrevy5diY8oIHFkXR/eybjcrFFjUPrHif8gSGs3Tw==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.7.0.tgz", + "integrity": "sha512-8eJ5X0y+gWDsURZnBfH0WabdNm8XMCXHv8ENy/3Z/oQKwaB/EHt5lP9VsTDTf36lKEp0V6DjzjFyFIB+CetL0A==", "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", + "@docusaurus/mdx-loader": "3.7.0", + "@docusaurus/module-type-aliases": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-common": "3.7.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -3674,19 +3658,19 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.8.0.tgz", - "integrity": "sha512-GBZ5UOcPgiu6nUw153+0+PNWvFKweSnvKIL6Rp04H9olKb475jfKjAwCCtju5D2xs5qXHvCMvzWOg5o9f6DtuQ==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.7.0.tgz", + "integrity": "sha512-Al/j5OdzwRU1m3falm+sYy9AaB93S1XF1Lgk9Yc6amp80dNxJVplQdQTR4cYdzkGtuQqbzUA8+kaoYYO0RbK6g==", "license": "MIT", "dependencies": { - "@docsearch/react": "^3.9.0", - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/plugin-content-docs": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-translations": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docsearch/react": "^3.8.1", + "@docusaurus/core": "3.7.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/plugin-content-docs": "3.7.0", + "@docusaurus/theme-common": "3.7.0", + "@docusaurus/theme-translations": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-validation": "3.7.0", "algoliasearch": "^5.17.1", "algoliasearch-helper": "^3.22.6", "clsx": "^2.0.0", @@ -3705,9 +3689,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.8.0.tgz", - "integrity": "sha512-1DTy/snHicgkCkryWq54fZvsAglTdjTx4qjOXgqnXJ+DIty1B+aPQrAVUu8LiM+6BiILfmNxYsxhKTj+BS3PZg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.7.0.tgz", + "integrity": "sha512-Ewq3bEraWDmienM6eaNK7fx+/lHMtGDHQyd1O+4+3EsDxxUmrzPkV7Ct3nBWTuE0MsoZr3yNwQVKjllzCMuU3g==", "license": "MIT", "dependencies": { "fs-extra": "^11.1.1", @@ -3718,16 +3702,16 @@ } }, "node_modules/@docusaurus/tsconfig": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.8.0.tgz", - "integrity": "sha512-utLl48nNjSYBoq47RKukZ9fPLEX3nJWThzrujb0ndQQ1jc/gh4RhTRaAqItH9nImnsgGKmLMnyoMBpfGmoop+w==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.7.0.tgz", + "integrity": "sha512-vRsyj3yUZCjscgfgcFYjIsTcAru/4h4YH2/XAE8Rs7wWdnng98PgWKvP5ovVc4rmRpRg2WChVW0uOy2xHDvDBQ==", "dev": true, "license": "MIT" }, "node_modules/@docusaurus/types": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.8.0.tgz", - "integrity": "sha512-RDEClpwNxZq02c+JlaKLWoS13qwWhjcNsi2wG1UpzmEnuti/z1Wx4SGpqbUqRPNSd8QWWePR8Cb7DvG0VN/TtA==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.7.0.tgz", + "integrity": "sha512-kOmZg5RRqJfH31m+6ZpnwVbkqMJrPOG5t0IOl4i/+3ruXyNfWzZ0lVtVrD0u4ONc/0NOsS9sWYaxxWNkH1LdLQ==", "license": "MIT", "dependencies": { "@mdx-js/mdx": "^3.0.0", @@ -3760,16 +3744,15 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.8.0.tgz", - "integrity": "sha512-2wvtG28ALCN/A1WCSLxPASFBFzXCnP0YKCAFIPcvEb6imNu1wg7ni/Svcp71b3Z2FaOFFIv4Hq+j4gD7gA0yfQ==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.7.0.tgz", + "integrity": "sha512-e7zcB6TPnVzyUaHMJyLSArKa2AG3h9+4CfvKXKKWNx6hRs+p0a+u7HHTJBgo6KW2m+vqDnuIHK4X+bhmoghAFA==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-common": "3.8.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/types": "3.7.0", + "@docusaurus/utils-common": "3.7.0", "escape-string-regexp": "^4.0.0", - "execa": "5.1.1", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", "github-slugger": "^1.5.0", @@ -3779,9 +3762,9 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "micromatch": "^4.0.5", - "p-queue": "^6.6.2", "prompts": "^2.4.2", "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", "tslib": "^2.6.0", "url-loader": "^4.1.1", "utility-types": "^3.10.0", @@ -3792,12 +3775,12 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.8.0.tgz", - "integrity": "sha512-3TGF+wVTGgQ3pAc9+5jVchES4uXUAhAt9pwv7uws4mVOxL4alvU3ue/EZ+R4XuGk94pDy7CNXjRXpPjlfZXQfw==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.7.0.tgz", + "integrity": "sha512-IZeyIfCfXy0Mevj6bWNg7DG7B8G+S6o6JVpddikZtWyxJguiQ7JYr0SIZ0qWd8pGNuMyVwriWmbWqMnK7Y5PwA==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.8.0", + "@docusaurus/types": "3.7.0", "tslib": "^2.6.0" }, "engines": { @@ -3805,14 +3788,14 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.8.0.tgz", - "integrity": "sha512-MrnEbkigr54HkdFeg8e4FKc4EF+E9dlVwsY3XQZsNkbv3MKZnbHQ5LsNJDIKDROFe8PBf5C4qCAg5TPBpsjrjg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.7.0.tgz", + "integrity": "sha512-w8eiKk8mRdN+bNfeZqC4nyFoxNyI1/VExMKAzD9tqpJfLLbsa46Wfn5wcKH761g9WkKh36RtFV49iL9lh1DYBA==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", + "@docusaurus/logger": "3.7.0", + "@docusaurus/utils": "3.7.0", + "@docusaurus/utils-common": "3.7.0", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", @@ -4774,6 +4757,12 @@ "@types/node": "*" } }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, "node_modules/@types/parse5": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", @@ -5448,6 +5437,15 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/autocomplete.js": { "version": "0.37.1", "resolved": "https://registry.npmjs.org/autocomplete.js/-/autocomplete.js-0.37.1.tgz", @@ -7371,6 +7369,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "license": "MIT", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -7443,6 +7463,38 @@ "node": ">= 4.0.0" } }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -8633,6 +8685,15 @@ "node": ">=0.10.0" } }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -8773,6 +8834,134 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/form-data": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", @@ -9092,6 +9281,44 @@ "node": ">=10" } }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -10417,10 +10644,13 @@ } }, "node_modules/image-size": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz", - "integrity": "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", + "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", "license": "MIT", + "dependencies": { + "queue": "6.0.2" + }, "bin": { "image-size": "bin/image-size.js" }, @@ -10764,6 +10994,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -10806,6 +11045,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -14402,15 +14650,6 @@ "node": ">=12.20" } }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/p-limit": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", @@ -14456,22 +14695,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-retry": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", @@ -14485,16 +14708,13 @@ "node": ">=8" } }, - "node_modules/p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "license": "MIT", - "dependencies": { - "p-finally": "^1.0.0" - }, "engines": { - "node": ">=8" + "node": ">=6" } }, "node_modules/package-json": { @@ -14792,10 +15012,83 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/postcss": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", - "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -14812,7 +15105,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -16601,6 +16894,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -16792,6 +17094,132 @@ "node": ">=0.10.0" } }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/react-dev-utils/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dev-utils/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -16805,6 +17233,12 @@ "react": "^18.3.1" } }, + "node_modules/react-error-overlay": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.1.0.tgz", + "integrity": "sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==", + "license": "MIT" + }, "node_modules/react-fast-compare": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", @@ -16836,15 +17270,15 @@ "license": "MIT" }, "node_modules/react-json-view-lite": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-2.4.1.tgz", - "integrity": "sha512-fwFYknRIBxjbFm0kBDrzgBy1xa5tDg2LyXXBepC5f1b+MY3BUClMCsvanMPn089JbV1Eg3nZcrp0VCuH43aXnA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.5.0.tgz", + "integrity": "sha512-nWqA1E4jKPklL2jvHWs6s+7Na0qNgw9HCP6xehdQJeg6nPBTFZgGwyko9Q0oj+jQWKTTVRS30u0toM5wiuL3iw==", "license": "MIT", "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "react": "^18.0.0 || ^19.0.0" + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" } }, "node_modules/react-loadable": { @@ -16999,6 +17433,12 @@ "node": ">=8.10.0" } }, + "node_modules/reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==", + "license": "MIT" + }, "node_modules/rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -17074,6 +17514,18 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/redux": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", @@ -17756,12 +18208,6 @@ "loose-envify": "^1.1.0" } }, - "node_modules/schema-dts": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/schema-dts/-/schema-dts-1.1.5.tgz", - "integrity": "sha512-RJr9EaCmsLzBX2NDiO5Z3ux2BVosNZN5jo0gWgsyKvxKIUL5R3swNvoorulAeL9kLB0iTSX7V6aokhla2m7xbg==", - "license": "Apache-2.0" - }, "node_modules/schema-utils": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", @@ -19026,6 +19472,12 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "license": "MIT" + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -19065,15 +19517,6 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", "license": "MIT" }, - "node_modules/tinypool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz", - "integrity": "sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==", - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -19243,7 +19686,6 @@ "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/docs/package.json b/docs/package.json index 2cc81f1b2c..e13e85ecb3 100644 --- a/docs/package.json +++ b/docs/package.json @@ -16,8 +16,8 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "~3.8.0", - "@docusaurus/preset-classic": "~3.8.0", + "@docusaurus/core": "~3.7.0", + "@docusaurus/preset-classic": "~3.7.0", "@mdi/js": "^7.3.67", "@mdi/react": "^1.6.1", "@mdx-js/react": "^3.0.0", @@ -35,7 +35,7 @@ "url": "^0.11.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "~3.8.0", + "@docusaurus/module-type-aliases": "~3.7.0", "@docusaurus/tsconfig": "^3.7.0", "@docusaurus/types": "^3.7.0", "prettier": "^3.2.4", diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 6d837d67ed..343295c60d 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -1709,17 +1709,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz", - "integrity": "sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", + "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/type-utils": "8.33.0", - "@typescript-eslint/utils": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/type-utils": "8.32.1", + "@typescript-eslint/utils": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -1733,7 +1733,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.33.0", + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -1749,16 +1749,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz", - "integrity": "sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz", + "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/typescript-estree": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4" }, "engines": { @@ -1773,34 +1773,15 @@ "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz", - "integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.33.0", - "@typescript-eslint/types": "^8.33.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz", - "integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0" + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1810,32 +1791,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz", - "integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz", - "integrity": "sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", + "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.33.0", - "@typescript-eslint/utils": "8.33.0", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/utils": "8.32.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -1852,9 +1816,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz", - "integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", "dev": true, "license": "MIT", "engines": { @@ -1866,16 +1830,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz", - "integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.33.0", - "@typescript-eslint/tsconfig-utils": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1921,16 +1883,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz", - "integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/typescript-estree": "8.33.0" + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1945,13 +1907,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz", - "integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/types": "8.32.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3872,9 +3834,9 @@ } }, "node_modules/globals": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz", - "integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", + "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", "dev": true, "license": "MIT", "engines": { @@ -6817,15 +6779,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.0.tgz", - "integrity": "sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz", + "integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.33.0", - "@typescript-eslint/parser": "8.33.0", - "@typescript-eslint/utils": "8.33.0" + "@typescript-eslint/eslint-plugin": "8.32.1", + "@typescript-eslint/parser": "8.32.1", + "@typescript-eslint/utils": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/i18n/en.json b/i18n/en.json index a25d62e94c..418c26a2b3 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -463,6 +463,8 @@ "assets_count": "{count, plural, one {# asset} other {# assets}}", "assets_deleted_permanently": "{count} asset(s) deleted permanently", "assets_deleted_permanently_from_server": "{count} asset(s) deleted permanently from the Immich server", + "assets_downloaded_failed": "{count, plural, one {Downloaded # file - {error} file failed} other {Downloaded # files - {error} files failed}}", + "assets_downloaded_successfully": "{count, plural, one {Downloaded # file successfully} other {Downloaded # files successfully}}", "assets_moved_to_trash_count": "Moved {count, plural, one {# asset} other {# assets}} to trash", "assets_permanently_deleted_count": "Permanently deleted {count, plural, one {# asset} other {# assets}}", "assets_removed_count": "Removed {count, plural, one {# asset} other {# assets}}", @@ -694,6 +696,7 @@ "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "dark": "Dark", + "darkTheme": "Toggle dark theme", "date_after": "Date after", "date_and_time": "Date and Time", "date_before": "Date before", @@ -1169,7 +1172,7 @@ "look": "Look", "loop_videos": "Loop videos", "loop_videos_description": "Enable to automatically loop a video in the detail viewer.", - "main_branch_warning": "You’re using a development version; we strongly recommend using a release version!", + "main_branch_warning": "You're using a development version; we strongly recommend using a release version!", "main_menu": "Main menu", "make": "Make", "manage_shared_links": "Manage shared links", @@ -1434,7 +1437,7 @@ "purchase_lifetime_description": "Lifetime purchase", "purchase_option_title": "PURCHASE OPTIONS", "purchase_panel_info_1": "Building Immich takes a lot of time and effort, and we have full-time engineers working on it to make it as good as we possibly can. Our mission is for open-source software and ethical business practices to become a sustainable income source for developers and to create a privacy-respecting ecosystem with real alternatives to exploitative cloud services.", - "purchase_panel_info_2": "As we’re committed not to add paywalls, this purchase will not grant you any additional features in Immich. We rely on users like you to support Immich’s ongoing development.", + "purchase_panel_info_2": "As we're committed not to add paywalls, this purchase will not grant you any additional features in Immich. We rely on users like you to support Immich's ongoing development.", "purchase_panel_title": "Support the project", "purchase_per_server": "Per server", "purchase_per_user": "Per user", @@ -1817,7 +1820,6 @@ "to_parent": "Go to parent", "to_trash": "Trash", "toggle_settings": "Toggle settings", - "toggle_theme": "Toggle dark theme", "total": "Total", "total_usage": "Total usage", "trash": "Trash", @@ -1839,6 +1841,7 @@ "unable_to_setup_pin_code": "Unable to setup PIN code", "unarchive": "Unarchive", "unarchived_count": "{count, plural, other {Unarchived #}}", + "undo": "Undo", "unfavorite": "Unfavorite", "unhide_person": "Unhide person", "unknown": "Unknown", diff --git a/mobile/lib/entities/album.entity.dart b/mobile/lib/entities/album.entity.dart index 8b466da1db..f6d5322752 100644 --- a/mobile/lib/entities/album.entity.dart +++ b/mobile/lib/entities/album.entity.dart @@ -19,6 +19,7 @@ class Album { required this.name, required this.createdAt, required this.modifiedAt, + this.description, this.startDate, this.endDate, this.lastModifiedAssetTimestamp, @@ -34,6 +35,7 @@ class Album { @Index(unique: false, replace: false, type: IndexType.hash) String? localId; String name; + String? description; DateTime createdAt; DateTime modifiedAt; DateTime? startDate; @@ -108,6 +110,7 @@ class Album { remoteId == other.remoteId && localId == other.localId && name == other.name && + description == other.description && createdAt.isAtSameMomentAs(other.createdAt) && modifiedAt.isAtSameMomentAs(other.modifiedAt) && isAtSameMomentAs(startDate, other.startDate) && @@ -135,6 +138,7 @@ class Album { modifiedAt.hashCode ^ startDate.hashCode ^ endDate.hashCode ^ + description.hashCode ^ lastModifiedAssetTimestamp.hashCode ^ shared.hashCode ^ activityEnabled.hashCode ^ @@ -150,6 +154,7 @@ class Album { name: dto.albumName, createdAt: dto.createdAt, modifiedAt: dto.updatedAt, + description: dto.description, lastModifiedAssetTimestamp: dto.lastModifiedAssetTimestamp, shared: dto.shared, startDate: dto.startDate, @@ -184,7 +189,8 @@ class Album { } @override - String toString() => name; + String toString() => + 'remoteId: $remoteId name: $name description: $description'; } extension AssetsHelper on IsarCollection { diff --git a/mobile/lib/entities/album.entity.g.dart b/mobile/lib/entities/album.entity.g.dart index 327dc606ca..546101baca 100644 --- a/mobile/lib/entities/album.entity.g.dart +++ b/mobile/lib/entities/album.entity.g.dart @@ -27,49 +27,54 @@ const AlbumSchema = CollectionSchema( name: r'createdAt', type: IsarType.dateTime, ), - r'endDate': PropertySchema( + r'description': PropertySchema( id: 2, + name: r'description', + type: IsarType.string, + ), + r'endDate': PropertySchema( + id: 3, name: r'endDate', type: IsarType.dateTime, ), r'lastModifiedAssetTimestamp': PropertySchema( - id: 3, + id: 4, name: r'lastModifiedAssetTimestamp', type: IsarType.dateTime, ), r'localId': PropertySchema( - id: 4, + id: 5, name: r'localId', type: IsarType.string, ), r'modifiedAt': PropertySchema( - id: 5, + id: 6, name: r'modifiedAt', type: IsarType.dateTime, ), r'name': PropertySchema( - id: 6, + id: 7, name: r'name', type: IsarType.string, ), r'remoteId': PropertySchema( - id: 7, + id: 8, name: r'remoteId', type: IsarType.string, ), r'shared': PropertySchema( - id: 8, + id: 9, name: r'shared', type: IsarType.bool, ), r'sortOrder': PropertySchema( - id: 9, + id: 10, name: r'sortOrder', type: IsarType.byte, enumMap: _AlbumsortOrderEnumValueMap, ), r'startDate': PropertySchema( - id: 10, + id: 11, name: r'startDate', type: IsarType.dateTime, ) @@ -146,6 +151,12 @@ int _albumEstimateSize( Map> allOffsets, ) { var bytesCount = offsets.last; + { + final value = object.description; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } { final value = object.localId; if (value != null) { @@ -170,15 +181,16 @@ void _albumSerialize( ) { writer.writeBool(offsets[0], object.activityEnabled); writer.writeDateTime(offsets[1], object.createdAt); - writer.writeDateTime(offsets[2], object.endDate); - writer.writeDateTime(offsets[3], object.lastModifiedAssetTimestamp); - writer.writeString(offsets[4], object.localId); - writer.writeDateTime(offsets[5], object.modifiedAt); - writer.writeString(offsets[6], object.name); - writer.writeString(offsets[7], object.remoteId); - writer.writeBool(offsets[8], object.shared); - writer.writeByte(offsets[9], object.sortOrder.index); - writer.writeDateTime(offsets[10], object.startDate); + writer.writeString(offsets[2], object.description); + writer.writeDateTime(offsets[3], object.endDate); + writer.writeDateTime(offsets[4], object.lastModifiedAssetTimestamp); + writer.writeString(offsets[5], object.localId); + writer.writeDateTime(offsets[6], object.modifiedAt); + writer.writeString(offsets[7], object.name); + writer.writeString(offsets[8], object.remoteId); + writer.writeBool(offsets[9], object.shared); + writer.writeByte(offsets[10], object.sortOrder.index); + writer.writeDateTime(offsets[11], object.startDate); } Album _albumDeserialize( @@ -190,16 +202,18 @@ Album _albumDeserialize( final object = Album( activityEnabled: reader.readBool(offsets[0]), createdAt: reader.readDateTime(offsets[1]), - endDate: reader.readDateTimeOrNull(offsets[2]), - lastModifiedAssetTimestamp: reader.readDateTimeOrNull(offsets[3]), - localId: reader.readStringOrNull(offsets[4]), - modifiedAt: reader.readDateTime(offsets[5]), - name: reader.readString(offsets[6]), - remoteId: reader.readStringOrNull(offsets[7]), - shared: reader.readBool(offsets[8]), - sortOrder: _AlbumsortOrderValueEnumMap[reader.readByteOrNull(offsets[9])] ?? - SortOrder.desc, - startDate: reader.readDateTimeOrNull(offsets[10]), + description: reader.readStringOrNull(offsets[2]), + endDate: reader.readDateTimeOrNull(offsets[3]), + lastModifiedAssetTimestamp: reader.readDateTimeOrNull(offsets[4]), + localId: reader.readStringOrNull(offsets[5]), + modifiedAt: reader.readDateTime(offsets[6]), + name: reader.readString(offsets[7]), + remoteId: reader.readStringOrNull(offsets[8]), + shared: reader.readBool(offsets[9]), + sortOrder: + _AlbumsortOrderValueEnumMap[reader.readByteOrNull(offsets[10])] ?? + SortOrder.desc, + startDate: reader.readDateTimeOrNull(offsets[11]), ); object.id = id; return object; @@ -217,23 +231,25 @@ P _albumDeserializeProp

( case 1: return (reader.readDateTime(offset)) as P; case 2: - return (reader.readDateTimeOrNull(offset)) as P; + return (reader.readStringOrNull(offset)) as P; case 3: return (reader.readDateTimeOrNull(offset)) as P; case 4: - return (reader.readStringOrNull(offset)) as P; + return (reader.readDateTimeOrNull(offset)) as P; case 5: - return (reader.readDateTime(offset)) as P; - case 6: - return (reader.readString(offset)) as P; - case 7: return (reader.readStringOrNull(offset)) as P; + case 6: + return (reader.readDateTime(offset)) as P; + case 7: + return (reader.readString(offset)) as P; case 8: - return (reader.readBool(offset)) as P; + return (reader.readStringOrNull(offset)) as P; case 9: + return (reader.readBool(offset)) as P; + case 10: return (_AlbumsortOrderValueEnumMap[reader.readByteOrNull(offset)] ?? SortOrder.desc) as P; - case 10: + case 11: return (reader.readDateTimeOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); @@ -535,6 +551,152 @@ extension AlbumQueryFilter on QueryBuilder { }); } + QueryBuilder descriptionIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'description', + )); + }); + } + + QueryBuilder descriptionIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'description', + )); + }); + } + + QueryBuilder descriptionEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'description', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder descriptionGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'description', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder descriptionLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'description', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder descriptionBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'description', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder descriptionStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'description', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder descriptionEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'description', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder descriptionContains( + String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'description', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder descriptionMatches( + String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'description', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder descriptionIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'description', + value: '', + )); + }); + } + + QueryBuilder descriptionIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'description', + value: '', + )); + }); + } + QueryBuilder endDateIsNull() { return QueryBuilder.apply(this, (query) { return query.addFilterCondition(const FilterCondition.isNull( @@ -1502,6 +1664,18 @@ extension AlbumQuerySortBy on QueryBuilder { }); } + QueryBuilder sortByDescription() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'description', Sort.asc); + }); + } + + QueryBuilder sortByDescriptionDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'description', Sort.desc); + }); + } + QueryBuilder sortByEndDate() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'endDate', Sort.asc); @@ -1637,6 +1811,18 @@ extension AlbumQuerySortThenBy on QueryBuilder { }); } + QueryBuilder thenByDescription() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'description', Sort.asc); + }); + } + + QueryBuilder thenByDescriptionDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'description', Sort.desc); + }); + } + QueryBuilder thenByEndDate() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'endDate', Sort.asc); @@ -1772,6 +1958,13 @@ extension AlbumQueryWhereDistinct on QueryBuilder { }); } + QueryBuilder distinctByDescription( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'description', caseSensitive: caseSensitive); + }); + } + QueryBuilder distinctByEndDate() { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'endDate'); @@ -1849,6 +2042,12 @@ extension AlbumQueryProperty on QueryBuilder { }); } + QueryBuilder descriptionProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'description'); + }); + } + QueryBuilder endDateProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'endDate'); diff --git a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart index 804f66c5bb..7aa8fc6efe 100644 --- a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart @@ -7,6 +7,7 @@ import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift. import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:logging/logging.dart'; +import 'package:openapi/api.dart' as api show AssetVisibility; import 'package:openapi/api.dart' hide AssetVisibility; class DriftSyncStreamRepository extends DriftDatabaseRepository @@ -231,22 +232,22 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository }); } -extension on SyncAssetV1TypeEnum { +extension on AssetTypeEnum { AssetType toAssetType() => switch (this) { - SyncAssetV1TypeEnum.IMAGE => AssetType.image, - SyncAssetV1TypeEnum.VIDEO => AssetType.video, - SyncAssetV1TypeEnum.AUDIO => AssetType.audio, - SyncAssetV1TypeEnum.OTHER => AssetType.other, - _ => throw Exception('Unknown SyncAssetV1TypeEnum value: $this'), + AssetTypeEnum.IMAGE => AssetType.image, + AssetTypeEnum.VIDEO => AssetType.video, + AssetTypeEnum.AUDIO => AssetType.audio, + AssetTypeEnum.OTHER => AssetType.other, + _ => throw Exception('Unknown AssetType value: $this'), }; } -extension on SyncAssetV1VisibilityEnum { +extension on api.AssetVisibility { AssetVisibility toAssetVisibility() => switch (this) { - SyncAssetV1VisibilityEnum.timeline => AssetVisibility.timeline, - SyncAssetV1VisibilityEnum.hidden => AssetVisibility.hidden, - SyncAssetV1VisibilityEnum.archive => AssetVisibility.archive, - SyncAssetV1VisibilityEnum.locked => AssetVisibility.locked, - _ => throw Exception('Unknown SyncAssetV1VisibilityEnum value: $this'), + api.AssetVisibility.timeline => AssetVisibility.timeline, + api.AssetVisibility.hidden => AssetVisibility.hidden, + api.AssetVisibility.archive => AssetVisibility.archive, + api.AssetVisibility.locked => AssetVisibility.locked, + _ => throw Exception('Unknown AssetVisibility value: $this'), }; } diff --git a/mobile/lib/interfaces/download.interface.dart b/mobile/lib/interfaces/download.interface.dart index dc4f0f57f8..beb063d6a2 100644 --- a/mobile/lib/interfaces/download.interface.dart +++ b/mobile/lib/interfaces/download.interface.dart @@ -7,7 +7,8 @@ abstract interface class IDownloadRepository { void Function(TaskProgressUpdate)? onTaskProgress; Future> getLiveVideoTasks(); - Future download(DownloadTask task); + Future> downloadAll(List tasks); + Future cancel(String id); Future deleteAllTrackingRecords(); Future deleteRecordsWithIds(List id); diff --git a/mobile/lib/models/albums/album_viewer_page_state.model.dart b/mobile/lib/models/albums/album_viewer_page_state.model.dart index 1d1cc9f9ec..10a8183ddc 100644 --- a/mobile/lib/models/albums/album_viewer_page_state.model.dart +++ b/mobile/lib/models/albums/album_viewer_page_state.model.dart @@ -3,18 +3,23 @@ import 'dart:convert'; class AlbumViewerPageState { final bool isEditAlbum; final String editTitleText; + final String editDescriptionText; + AlbumViewerPageState({ required this.isEditAlbum, required this.editTitleText, + required this.editDescriptionText, }); AlbumViewerPageState copyWith({ bool? isEditAlbum, String? editTitleText, + String? editDescriptionText, }) { return AlbumViewerPageState( isEditAlbum: isEditAlbum ?? this.isEditAlbum, editTitleText: editTitleText ?? this.editTitleText, + editDescriptionText: editDescriptionText ?? this.editDescriptionText, ); } @@ -23,6 +28,7 @@ class AlbumViewerPageState { result.addAll({'isEditAlbum': isEditAlbum}); result.addAll({'editTitleText': editTitleText}); + result.addAll({'editDescriptionText': editDescriptionText}); return result; } @@ -31,6 +37,7 @@ class AlbumViewerPageState { return AlbumViewerPageState( isEditAlbum: map['isEditAlbum'] ?? false, editTitleText: map['editTitleText'] ?? '', + editDescriptionText: map['editDescriptionText'] ?? '', ); } @@ -41,7 +48,7 @@ class AlbumViewerPageState { @override String toString() => - 'AlbumViewerPageState(isEditAlbum: $isEditAlbum, editTitleText: $editTitleText)'; + 'AlbumViewerPageState(isEditAlbum: $isEditAlbum, editTitleText: $editTitleText, editDescriptionText: $editDescriptionText)'; @override bool operator ==(Object other) { @@ -49,9 +56,13 @@ class AlbumViewerPageState { return other is AlbumViewerPageState && other.isEditAlbum == isEditAlbum && - other.editTitleText == editTitleText; + other.editTitleText == editTitleText && + other.editDescriptionText == editDescriptionText; } @override - int get hashCode => isEditAlbum.hashCode ^ editTitleText.hashCode; + int get hashCode => + isEditAlbum.hashCode ^ + editTitleText.hashCode ^ + editDescriptionText.hashCode; } diff --git a/mobile/lib/models/asset_selection_state.dart b/mobile/lib/models/asset_selection_state.dart index b8a38ecee1..b080dca003 100644 --- a/mobile/lib/models/asset_selection_state.dart +++ b/mobile/lib/models/asset_selection_state.dart @@ -35,7 +35,7 @@ class AssetSelectionState { @override String toString() => - 'SelectionAssetState(hasRemote: $hasRemote, hasMerged: $hasMerged, hasMerged: $hasMerged, selectedCount: $selectedCount)'; + 'SelectionAssetState(hasRemote: $hasRemote, hasLocal: $hasLocal, hasMerged: $hasMerged, selectedCount: $selectedCount)'; @override bool operator ==(covariant AssetSelectionState other) { diff --git a/mobile/lib/pages/album/album_control_button.dart b/mobile/lib/pages/album/album_control_button.dart index 54bfa69da4..b2100946e6 100644 --- a/mobile/lib/pages/album/album_control_button.dart +++ b/mobile/lib/pages/album/album_control_button.dart @@ -26,9 +26,9 @@ class AlbumControlButton extends ConsumerWidget { ); return Padding( - padding: const EdgeInsets.only(left: 16.0, top: 8, bottom: 16), + padding: const EdgeInsets.only(left: 16.0), child: SizedBox( - height: 40, + height: 36, child: ListView( scrollDirection: Axis.horizontal, children: [ diff --git a/mobile/lib/pages/album/album_date_range.dart b/mobile/lib/pages/album/album_date_range.dart index 5f7ef40d4b..591be260f6 100644 --- a/mobile/lib/pages/album/album_date_range.dart +++ b/mobile/lib/pages/album/album_date_range.dart @@ -30,15 +30,12 @@ class AlbumDateRange extends ConsumerWidget { final (startDate, endDate, shared) = data; return Padding( - padding: shared - ? const EdgeInsets.only( - left: 16.0, - bottom: 0.0, - ) - : const EdgeInsets.only(left: 16.0, bottom: 8.0), + padding: const EdgeInsets.only(left: 16.0), child: Text( _getDateRangeText(startDate, endDate), - style: context.textTheme.labelLarge, + style: context.textTheme.labelLarge?.copyWith( + color: context.colorScheme.onSurfaceVariant, + ), ), ); } diff --git a/mobile/lib/pages/album/album_description.dart b/mobile/lib/pages/album/album_description.dart new file mode 100644 index 0000000000..37c5beb2c2 --- /dev/null +++ b/mobile/lib/pages/album/album_description.dart @@ -0,0 +1,45 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/providers/album/current_album.provider.dart'; +import 'package:immich_mobile/widgets/album/album_viewer_editable_description.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; + +class AlbumDescription extends ConsumerWidget { + const AlbumDescription({super.key, required this.descriptionFocusNode}); + + final FocusNode descriptionFocusNode; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final userId = ref.watch(authProvider).userId; + final (isOwner, isRemote, albumDescription) = ref.watch( + currentAlbumProvider.select((album) { + if (album == null) { + return const (false, false, ''); + } + + return (album.ownerId == userId, album.isRemote, album.description); + }), + ); + + if (isOwner && isRemote) { + return Padding( + padding: const EdgeInsets.only(left: 8, right: 8), + child: AlbumViewerEditableDescription( + albumDescription: albumDescription ?? 'add_a_description'.tr(), + descriptionFocusNode: descriptionFocusNode, + ), + ); + } + + return Padding( + padding: const EdgeInsets.only(left: 16, right: 8), + child: Text( + albumDescription ?? 'add_a_description'.tr(), + style: context.textTheme.bodyLarge, + ), + ); + } +} diff --git a/mobile/lib/pages/album/album_shared_user_icons.dart b/mobile/lib/pages/album/album_shared_user_icons.dart index 47ea476028..723bb1e252 100644 --- a/mobile/lib/pages/album/album_shared_user_icons.dart +++ b/mobile/lib/pages/album/album_shared_user_icons.dart @@ -36,7 +36,7 @@ class AlbumSharedUserIcons extends HookConsumerWidget { child: SizedBox( height: 50, child: ListView.builder( - padding: const EdgeInsets.only(left: 16), + padding: const EdgeInsets.only(left: 16, bottom: 8), scrollDirection: Axis.horizontal, itemBuilder: ((context, index) { return Padding( diff --git a/mobile/lib/pages/album/album_title.dart b/mobile/lib/pages/album/album_title.dart index 435e282523..ccea200f3a 100644 --- a/mobile/lib/pages/album/album_title.dart +++ b/mobile/lib/pages/album/album_title.dart @@ -19,7 +19,11 @@ class AlbumTitle extends ConsumerWidget { return const (false, false, ''); } - return (album.ownerId == userId, album.isRemote, album.name); + return ( + album.ownerId == userId, + album.isRemote, + album.name, + ); }), ); @@ -35,7 +39,12 @@ class AlbumTitle extends ConsumerWidget { return Padding( padding: const EdgeInsets.only(left: 16, right: 8), - child: Text(albumName, style: context.textTheme.headlineMedium), + child: Text( + albumName, + style: context.textTheme.headlineLarge?.copyWith( + fontWeight: FontWeight.w700, + ), + ), ); } } diff --git a/mobile/lib/pages/album/album_viewer.dart b/mobile/lib/pages/album/album_viewer.dart index f6c46843db..f22fc30716 100644 --- a/mobile/lib/pages/album/album_viewer.dart +++ b/mobile/lib/pages/album/album_viewer.dart @@ -10,6 +10,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/models/albums/asset_selection_page_result.model.dart'; import 'package:immich_mobile/pages/album/album_control_button.dart'; import 'package:immich_mobile/pages/album/album_date_range.dart'; +import 'package:immich_mobile/pages/album/album_description.dart'; import 'package:immich_mobile/pages/album/album_shared_user_icons.dart'; import 'package:immich_mobile/pages/album/album_title.dart'; import 'package:immich_mobile/providers/album/album.provider.dart'; @@ -36,6 +37,7 @@ class AlbumViewer extends HookConsumerWidget { } final titleFocusNode = useFocusNode(); + final descriptionFocusNode = useFocusNode(); final userId = ref.watch(authProvider).userId; final isMultiselecting = ref.watch(multiselectProvider); final isProcessing = useProcessingOverlay(); @@ -106,23 +108,44 @@ class AlbumViewer extends HookConsumerWidget { MultiselectGrid( key: const ValueKey("albumViewerMultiselectGrid"), renderListProvider: albumTimelineProvider(album.id), - topWidget: Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AlbumTitle( - key: const ValueKey("albumTitle"), - titleFocusNode: titleFocusNode, + topWidget: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + context.primaryColor.withValues(alpha: 0.04), + context.primaryColor.withValues(alpha: 0.02), + Colors.orange.withValues(alpha: 0.02), + Colors.transparent, + ], + stops: const [0.0, 0.3, 0.7, 1.0], ), - const AlbumDateRange(), - const AlbumSharedUserIcons(), - if (album.isRemote) - AlbumControlButton( - key: const ValueKey("albumControlButton"), - onAddPhotosPressed: onAddPhotosPressed, - onAddUsersPressed: onAddUsersPressed, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 32), + const AlbumDateRange(), + AlbumTitle( + key: const ValueKey("albumTitle"), + titleFocusNode: titleFocusNode, ), - ], + AlbumDescription( + key: const ValueKey("albumDescription"), + descriptionFocusNode: descriptionFocusNode, + ), + const AlbumSharedUserIcons(), + if (album.isRemote) + AlbumControlButton( + key: const ValueKey("albumControlButton"), + onAddPhotosPressed: onAddPhotosPressed, + onAddUsersPressed: onAddUsersPressed, + ), + const SizedBox(height: 8), + ], + ), ), onRemoveFromAlbum: onRemoveFromAlbumPressed, editEnabled: album.ownerId == userId, @@ -136,6 +159,7 @@ class AlbumViewer extends HookConsumerWidget { child: AlbumViewerAppbar( key: const ValueKey("albumViewerAppbar"), titleFocusNode: titleFocusNode, + descriptionFocusNode: descriptionFocusNode, userId: userId, onAddPhotos: onAddPhotosPressed, onAddUsers: onAddUsersPressed, diff --git a/mobile/lib/pages/common/create_album.page.dart b/mobile/lib/pages/common/create_album.page.dart index c4845620ff..f5c6321451 100644 --- a/mobile/lib/pages/common/create_album.page.dart +++ b/mobile/lib/pages/common/create_album.page.dart @@ -8,9 +8,11 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/models/albums/asset_selection_page_result.model.dart'; import 'package:immich_mobile/providers/album/album.provider.dart'; import 'package:immich_mobile/providers/album/album_title.provider.dart'; +import 'package:immich_mobile/providers/album/album_viewer.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/widgets/album/album_action_filled_button.dart'; import 'package:immich_mobile/widgets/album/album_title_text_field.dart'; +import 'package:immich_mobile/widgets/album/album_viewer_editable_description.dart'; import 'package:immich_mobile/widgets/album/shared_album_thumbnail_image.dart'; @RoutePage() @@ -28,6 +30,7 @@ class CreateAlbumPage extends HookConsumerWidget { final albumTitleController = useTextEditingController.fromValue(TextEditingValue.empty); final albumTitleTextFieldFocusNode = useFocusNode(); + final albumDescriptionTextFieldFocusNode = useFocusNode(); final isAlbumTitleTextFieldFocus = useState(false); final isAlbumTitleEmpty = useState(true); final selectedAssets = useState>( @@ -36,6 +39,7 @@ class CreateAlbumPage extends HookConsumerWidget { void onBackgroundTapped() { albumTitleTextFieldFocusNode.unfocus(); + albumDescriptionTextFieldFocusNode.unfocus(); isAlbumTitleTextFieldFocus.value = false; if (albumTitleController.text.isEmpty) { @@ -77,6 +81,19 @@ class CreateAlbumPage extends HookConsumerWidget { ); } + buildDescriptionInputField() { + return Padding( + padding: const EdgeInsets.only( + right: 10, + left: 10, + ), + child: AlbumViewerEditableDescription( + albumDescription: '', + descriptionFocusNode: albumDescriptionTextFieldFocusNode, + ), + ); + } + buildTitle() { if (selectedAssets.value.isEmpty) { return SliverToBoxAdapter( @@ -178,18 +195,18 @@ class CreateAlbumPage extends HookConsumerWidget { return const SliverToBoxAdapter(); } - createNonSharedAlbum() async { + Future createAlbum() async { onBackgroundTapped(); var newAlbum = await ref.watch(albumProvider.notifier).createAlbum( - ref.watch(albumTitleProvider), + ref.read(albumTitleProvider), selectedAssets.value, ); if (newAlbum != null) { - ref.watch(albumProvider.notifier).refreshRemoteAlbums(); + ref.read(albumProvider.notifier).refreshRemoteAlbums(); selectedAssets.value = {}; - ref.watch(albumTitleProvider.notifier).clearAlbumTitle(); - + ref.read(albumTitleProvider.notifier).clearAlbumTitle(); + ref.read(albumViewerProvider.notifier).disableEditAlbum(); context.replaceRoute(AlbumViewerRoute(albumId: newAlbum.id)); } } @@ -211,9 +228,8 @@ class CreateAlbumPage extends HookConsumerWidget { ).tr(), actions: [ TextButton( - onPressed: albumTitleController.text.isNotEmpty - ? createNonSharedAlbum - : null, + onPressed: + albumTitleController.text.isNotEmpty ? createAlbum : null, child: Text( 'create'.tr(), style: TextStyle( @@ -237,10 +253,11 @@ class CreateAlbumPage extends HookConsumerWidget { pinned: true, floating: false, bottom: PreferredSize( - preferredSize: const Size.fromHeight(96.0), + preferredSize: const Size.fromHeight(125.0), child: Column( children: [ buildTitleInputField(), + buildDescriptionInputField(), if (selectedAssets.value.isNotEmpty) buildControlButton(), ], ), diff --git a/mobile/lib/pages/common/splash_screen.page.dart b/mobile/lib/pages/common/splash_screen.page.dart index 5ea9351c0e..b640aaa3ed 100644 --- a/mobile/lib/pages/common/splash_screen.page.dart +++ b/mobile/lib/pages/common/splash_screen.page.dart @@ -72,7 +72,9 @@ class SplashScreenPageState extends ConsumerState { return; } - context.replaceRoute(const TabControllerRoute()); + if (context.router.current.name != ShareIntentRoute.name) { + context.replaceRoute(const TabControllerRoute()); + } final hasPermission = await ref.read(galleryPermissionNotifier.notifier).hasPermission; diff --git a/mobile/lib/pages/share_intent/share_intent.page.dart b/mobile/lib/pages/share_intent/share_intent.page.dart index ff137ce0aa..3ff1b0c8ce 100644 --- a/mobile/lib/pages/share_intent/share_intent.page.dart +++ b/mobile/lib/pages/share_intent/share_intent.page.dart @@ -7,6 +7,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/models/upload/share_intent_attachment.model.dart'; import 'package:immich_mobile/pages/common/large_leading_tile.dart'; import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provider.dart'; +import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/utils/url_helper.dart'; @RoutePage() @@ -20,6 +21,11 @@ class ShareIntentPage extends HookConsumerWidget { final currentEndpoint = getServerUrl() ?? '--'; final candidates = ref.watch(shareIntentUploadProvider); final isUploaded = useState(false); + useOnAppLifecycleStateChange((previous, current) { + if (current == AppLifecycleState.resumed) { + isUploaded.value = false; + } + }); void removeAttachment(ShareIntentAttachment attachment) { ref.read(shareIntentUploadProvider.notifier).removeAttachment(attachment); @@ -66,6 +72,14 @@ class ShareIntentPage extends HookConsumerWidget { ), ], ), + leading: IconButton( + onPressed: () { + context.navigateTo( + const TabControllerRoute(), + ); + }, + icon: const Icon(Icons.arrow_back), + ), ), body: ListView.builder( itemCount: attachments.length, diff --git a/mobile/lib/providers/album/album_viewer.provider.dart b/mobile/lib/providers/album/album_viewer.provider.dart index e418657782..cf7344d321 100644 --- a/mobile/lib/providers/album/album_viewer.provider.dart +++ b/mobile/lib/providers/album/album_viewer.provider.dart @@ -5,7 +5,13 @@ import 'package:immich_mobile/entities/album.entity.dart'; class AlbumViewerNotifier extends StateNotifier { AlbumViewerNotifier(this.ref) - : super(AlbumViewerPageState(editTitleText: "", isEditAlbum: false)); + : super( + AlbumViewerPageState( + editTitleText: "", + isEditAlbum: false, + editDescriptionText: "", + ), + ); final Ref ref; @@ -21,12 +27,24 @@ class AlbumViewerNotifier extends StateNotifier { state = state.copyWith(editTitleText: newTitle); } + void setEditDescriptionText(String newDescription) { + state = state.copyWith(editDescriptionText: newDescription); + } + void remoteEditTitleText() { state = state.copyWith(editTitleText: ""); } + void remoteEditDescriptionText() { + state = state.copyWith(editDescriptionText: ""); + } + void resetState() { - state = state.copyWith(editTitleText: "", isEditAlbum: false); + state = state.copyWith( + editTitleText: "", + isEditAlbum: false, + editDescriptionText: "", + ); } Future changeAlbumTitle( @@ -46,6 +64,28 @@ class AlbumViewerNotifier extends StateNotifier { state = state.copyWith(editTitleText: "", isEditAlbum: false); return false; } + + Future changeAlbumDescription( + Album album, + String newAlbumDescription, + ) async { + AlbumService service = ref.watch(albumServiceProvider); + + bool isSuccess = await service.changeDescriptionAlbum( + album, + newAlbumDescription, + ); + + if (isSuccess) { + state = state.copyWith(editDescriptionText: "", isEditAlbum: false); + + return true; + } + + state = state.copyWith(editDescriptionText: "", isEditAlbum: false); + + return false; + } } final albumViewerProvider = diff --git a/mobile/lib/providers/asset_viewer/download.provider.dart b/mobile/lib/providers/asset_viewer/download.provider.dart index d699c7c763..7750d6511a 100644 --- a/mobile/lib/providers/asset_viewer/download.provider.dart +++ b/mobile/lib/providers/asset_viewer/download.provider.dart @@ -140,6 +140,10 @@ class DownloadStateNotifier extends StateNotifier { }); } + Future> downloadAllAsset(List assets) async { + return await _downloadService.downloadAll(assets); + } + void downloadAsset(Asset asset, BuildContext context) async { await _downloadService.download(asset); } diff --git a/mobile/lib/repositories/album_api.repository.dart b/mobile/lib/repositories/album_api.repository.dart index a7bbe452e6..e2ac73bd9b 100644 --- a/mobile/lib/repositories/album_api.repository.dart +++ b/mobile/lib/repositories/album_api.repository.dart @@ -36,6 +36,7 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository { String name, { required Iterable assetIds, Iterable sharedUserIds = const [], + String? description, }) async { final users = sharedUserIds.map( (id) => AlbumUserCreateDto(userId: id, role: AlbumUserRole.editor), @@ -44,6 +45,7 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository { _api.createAlbum( CreateAlbumDto( albumName: name, + description: description, assetIds: assetIds.toList(), albumUsers: users.toList(), ), @@ -161,6 +163,7 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository { lastModifiedAssetTimestamp: dto.lastModifiedAssetTimestamp, shared: dto.shared, startDate: dto.startDate, + description: dto.description, endDate: dto.endDate, activityEnabled: dto.isActivityEnabled, sortOrder: dto.order == AssetOrder.asc ? SortOrder.asc : SortOrder.desc, @@ -174,6 +177,7 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository { album.sharedUsers.addAll(users.map(entity.User.fromDto)); final assets = dto.assets.map(Asset.remote).toList(); album.assets.addAll(assets); + return album; } } diff --git a/mobile/lib/repositories/download.repository.dart b/mobile/lib/repositories/download.repository.dart index 5b42f66b02..f7ba612045 100644 --- a/mobile/lib/repositories/download.repository.dart +++ b/mobile/lib/repositories/download.repository.dart @@ -39,8 +39,8 @@ class DownloadRepository implements IDownloadRepository { } @override - Future download(DownloadTask task) { - return FileDownloader().enqueue(task); + Future> downloadAll(List tasks) { + return FileDownloader().enqueueAll(tasks); } @override diff --git a/mobile/lib/services/album.service.dart b/mobile/lib/services/album.service.dart index 0922f506d5..f1e8721040 100644 --- a/mobile/lib/services/album.service.dart +++ b/mobile/lib/services/album.service.dart @@ -422,6 +422,25 @@ class AlbumService { } } + Future changeDescriptionAlbum( + Album album, + String newAlbumDescription, + ) async { + try { + final updatedAlbum = await _albumApiRepository.update( + album.remoteId!, + description: newAlbumDescription, + ); + + album.description = updatedAlbum.description; + await _albumRepository.update(album); + return true; + } catch (e) { + debugPrint("Error changeDescriptionAlbum ${e.toString()}"); + return false; + } + } + Future getAlbumByName( String name, { bool? remote, diff --git a/mobile/lib/services/download.service.dart b/mobile/lib/services/download.service.dart index 45297853f6..e7ecff175c 100644 --- a/mobile/lib/services/download.service.dart +++ b/mobile/lib/services/download.service.dart @@ -159,9 +159,19 @@ class DownloadService { return await FileDownloader().cancelTaskWithId(id); } + Future> downloadAll(List assets) async { + return await _downloadRepository + .downloadAll(assets.expand(_createDownloadTasks).toList()); + } + Future download(Asset asset) async { + final tasks = _createDownloadTasks(asset); + await _downloadRepository.downloadAll(tasks); + } + + List _createDownloadTasks(Asset asset) { if (asset.isImage && asset.livePhotoVideoId != null && Platform.isIOS) { - await _downloadRepository.download( + return [ _buildDownloadTask( asset.remoteId!, asset.fileName, @@ -171,9 +181,6 @@ class DownloadService { id: asset.remoteId!, ).toJson(), ), - ); - - await _downloadRepository.download( _buildDownloadTask( asset.livePhotoVideoId!, asset.fileName @@ -185,16 +192,20 @@ class DownloadService { id: asset.remoteId!, ).toJson(), ), - ); - } else { - await _downloadRepository.download( - _buildDownloadTask( - asset.remoteId!, - asset.fileName, - group: asset.isImage ? downloadGroupImage : downloadGroupVideo, - ), - ); + ]; } + + if (asset.remoteId == null) { + return []; + } + + return [ + _buildDownloadTask( + asset.remoteId!, + asset.fileName, + group: asset.isImage ? downloadGroupImage : downloadGroupVideo, + ), + ]; } DownloadTask _buildDownloadTask( diff --git a/mobile/lib/services/sync.service.dart b/mobile/lib/services/sync.service.dart index 80950d8c00..e08d7de8b9 100644 --- a/mobile/lib/services/sync.service.dart +++ b/mobile/lib/services/sync.service.dart @@ -451,6 +451,7 @@ class SyncService { final usersToLink = await _userRepository.getByUserIds(userIdsToAdd); album.name = dto.name; + album.description = dto.description; album.shared = dto.shared; album.createdAt = dto.createdAt; album.modifiedAt = dto.modifiedAt; @@ -643,6 +644,7 @@ class SyncService { toUpdate.isEmpty && toDelete.isEmpty && dbAlbum.name == deviceAlbum.name && + dbAlbum.description == deviceAlbum.description && dbAlbum.modifiedAt.isAtSameMomentAs(deviceAlbum.modifiedAt)) { // changes only affeted excluded albums _log.info( @@ -670,6 +672,7 @@ class SyncService { deleteCandidates.addAll(toDelete); existing.addAll(existingInDb); dbAlbum.name = deviceAlbum.name; + dbAlbum.description = deviceAlbum.description; dbAlbum.modifiedAt = deviceAlbum.modifiedAt; if (dbAlbum.thumbnail.value != null && toDelete.contains(dbAlbum.thumbnail.value)) { @@ -943,6 +946,7 @@ class SyncService { Album dbAlbum, ) async { return deviceAlbum.name != dbAlbum.name || + deviceAlbum.description != dbAlbum.description || !deviceAlbum.modifiedAt.isAtSameMomentAs(dbAlbum.modifiedAt) || await _albumMediaRepository.getAssetCount(deviceAlbum.localId!) != (await _eTagRepository.getById(deviceAlbum.eTagKeyAssetCount)) @@ -1101,6 +1105,7 @@ class SyncService { bool _hasRemoteAlbumChanged(Album remoteAlbum, Album dbAlbum) { return remoteAlbum.remoteAssetCount != dbAlbum.assetCount || remoteAlbum.name != dbAlbum.name || + remoteAlbum.description != dbAlbum.description || remoteAlbum.remoteThumbnailAssetId != dbAlbum.thumbnail.value?.remoteId || remoteAlbum.shared != dbAlbum.shared || remoteAlbum.remoteUsers.length != dbAlbum.sharedUsers.length || diff --git a/mobile/lib/widgets/album/album_action_filled_button.dart b/mobile/lib/widgets/album/album_action_filled_button.dart index de73307443..f5064f499c 100644 --- a/mobile/lib/widgets/album/album_action_filled_button.dart +++ b/mobile/lib/widgets/album/album_action_filled_button.dart @@ -16,7 +16,7 @@ class AlbumActionFilledButton extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.only(right: 16.0), + padding: const EdgeInsets.only(right: 8.0), child: FilledButton.icon( style: FilledButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 16), @@ -32,9 +32,7 @@ class AlbumActionFilledButton extends StatelessWidget { ), label: Text( labelText, - style: context.textTheme.labelMedium?.copyWith( - fontWeight: FontWeight.w600, - ), + style: context.textTheme.labelLarge?.copyWith(), ), onPressed: onPressed, ), diff --git a/mobile/lib/widgets/album/album_viewer_appbar.dart b/mobile/lib/widgets/album/album_viewer_appbar.dart index 2aabf7fbbb..9d48045459 100644 --- a/mobile/lib/widgets/album/album_viewer_appbar.dart +++ b/mobile/lib/widgets/album/album_viewer_appbar.dart @@ -18,6 +18,7 @@ class AlbumViewerAppbar extends HookConsumerWidget super.key, required this.userId, required this.titleFocusNode, + required this.descriptionFocusNode, this.onAddPhotos, this.onAddUsers, required this.onActivities, @@ -25,6 +26,7 @@ class AlbumViewerAppbar extends HookConsumerWidget final String userId; final FocusNode titleFocusNode; + final FocusNode descriptionFocusNode; final void Function()? onAddPhotos; final void Function()? onAddUsers; final void Function() onActivities; @@ -48,6 +50,7 @@ class AlbumViewerAppbar extends HookConsumerWidget final albumViewer = ref.watch(albumViewerProvider); final newAlbumTitle = albumViewer.editTitleText; + final newAlbumDescription = albumViewer.editDescriptionText; final isEditAlbum = albumViewer.isEditAlbum; final comments = album.shared @@ -277,20 +280,37 @@ class AlbumViewerAppbar extends HookConsumerWidget if (isEditAlbum) { return IconButton( onPressed: () async { - bool isSuccess = await ref - .watch(albumViewerProvider.notifier) - .changeAlbumTitle(album, newAlbumTitle); - - if (!isSuccess) { - ImmichToast.show( - context: context, - msg: "album_viewer_appbar_share_err_title".tr(), - gravity: ToastGravity.BOTTOM, - toastType: ToastType.error, - ); + if (newAlbumTitle.isNotEmpty) { + bool isSuccess = await ref + .watch(albumViewerProvider.notifier) + .changeAlbumTitle(album, newAlbumTitle); + if (!isSuccess) { + ImmichToast.show( + context: context, + msg: "album_viewer_appbar_share_err_title".tr(), + gravity: ToastGravity.BOTTOM, + toastType: ToastType.error, + ); + } + titleFocusNode.unfocus(); + } else if (newAlbumDescription.isNotEmpty) { + bool isSuccessDescription = await ref + .watch(albumViewerProvider.notifier) + .changeAlbumDescription(album, newAlbumDescription); + if (!isSuccessDescription) { + ImmichToast.show( + context: context, + msg: "album_viewer_appbar_share_err_description".tr(), + gravity: ToastGravity.BOTTOM, + toastType: ToastType.error, + ); + } + descriptionFocusNode.unfocus(); + } else { + titleFocusNode.unfocus(); + descriptionFocusNode.unfocus(); + ref.read(albumViewerProvider.notifier).disableEditAlbum(); } - - titleFocusNode.unfocus(); }, icon: const Icon(Icons.check_rounded), splashRadius: 25, diff --git a/mobile/lib/widgets/album/album_viewer_editable_description.dart b/mobile/lib/widgets/album/album_viewer_editable_description.dart new file mode 100644 index 0000000000..06bfbc0186 --- /dev/null +++ b/mobile/lib/widgets/album/album_viewer_editable_description.dart @@ -0,0 +1,102 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/providers/album/album_viewer.provider.dart'; + +class AlbumViewerEditableDescription extends HookConsumerWidget { + final String albumDescription; + final FocusNode descriptionFocusNode; + const AlbumViewerEditableDescription({ + super.key, + required this.albumDescription, + required this.descriptionFocusNode, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final albumViewerState = ref.watch(albumViewerProvider); + + final descriptionTextEditController = useTextEditingController( + text: albumViewerState.isEditAlbum && + albumViewerState.editDescriptionText.isNotEmpty + ? albumViewerState.editDescriptionText + : albumDescription, + ); + + void onFocusModeChange() { + if (!descriptionFocusNode.hasFocus && + descriptionTextEditController.text.isEmpty) { + ref.watch(albumViewerProvider.notifier).setEditDescriptionText(""); + descriptionTextEditController.text = ""; + } + } + + useEffect( + () { + descriptionFocusNode.addListener(onFocusModeChange); + return () { + descriptionFocusNode.removeListener(onFocusModeChange); + }; + }, + [], + ); + + return Material( + color: Colors.transparent, + child: TextField( + onChanged: (value) { + if (value.isEmpty) { + } else { + ref + .watch(albumViewerProvider.notifier) + .setEditDescriptionText(value); + } + }, + focusNode: descriptionFocusNode, + style: context.textTheme.bodyMedium, + maxLines: 3, + minLines: 1, + controller: descriptionTextEditController, + onTap: () { + context.focusScope.requestFocus(descriptionFocusNode); + + ref + .watch(albumViewerProvider.notifier) + .setEditDescriptionText(albumDescription); + ref.watch(albumViewerProvider.notifier).enableEditAlbum(); + + if (descriptionTextEditController.text == '') { + descriptionTextEditController.clear(); + } + }, + decoration: InputDecoration( + contentPadding: const EdgeInsets.all(8), + suffixIcon: descriptionFocusNode.hasFocus + ? IconButton( + onPressed: () { + descriptionTextEditController.clear(); + }, + icon: Icon( + Icons.cancel_rounded, + color: context.primaryColor, + ), + splashRadius: 10, + ) + : null, + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide(color: Colors.transparent), + ), + focusedBorder: const OutlineInputBorder( + borderSide: BorderSide(color: Colors.transparent), + ), + focusColor: Colors.grey[300], + fillColor: context.scaffoldBackgroundColor, + filled: descriptionFocusNode.hasFocus, + hintText: 'add_a_description'.tr(), + ), + ), + ); + } +} diff --git a/mobile/lib/widgets/album/album_viewer_editable_title.dart b/mobile/lib/widgets/album/album_viewer_editable_title.dart index 0f0e240f01..038c9a13d8 100644 --- a/mobile/lib/widgets/album/album_viewer_editable_title.dart +++ b/mobile/lib/widgets/album/album_viewer_editable_title.dart @@ -52,7 +52,9 @@ class AlbumViewerEditableTitle extends HookConsumerWidget { } }, focusNode: titleFocusNode, - style: context.textTheme.headlineMedium, + style: context.textTheme.headlineLarge?.copyWith( + fontWeight: FontWeight.w700, + ), controller: titleTextEditController, onTap: () { context.focusScope.requestFocus(titleFocusNode); @@ -65,8 +67,10 @@ class AlbumViewerEditableTitle extends HookConsumerWidget { } }, decoration: InputDecoration( - contentPadding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + contentPadding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 0, + ), suffixIcon: titleFocusNode.hasFocus ? IconButton( onPressed: () { diff --git a/mobile/lib/widgets/asset_grid/control_bottom_app_bar.dart b/mobile/lib/widgets/asset_grid/control_bottom_app_bar.dart index 892e7e5b8a..309de3ae28 100644 --- a/mobile/lib/widgets/asset_grid/control_bottom_app_bar.dart +++ b/mobile/lib/widgets/asset_grid/control_bottom_app_bar.dart @@ -39,6 +39,7 @@ class ControlBottomAppBar extends HookConsumerWidget { final void Function()? onEditLocation; final void Function()? onRemoveFromAlbum; final void Function()? onToggleLocked; + final void Function()? onDownload; final bool enabled; final bool unfavorite; @@ -56,6 +57,7 @@ class ControlBottomAppBar extends HookConsumerWidget { required this.onAddToAlbum, required this.onCreateNewAlbum, required this.onUpload, + this.onDownload, this.onStack, this.onEditTime, this.onEditLocation, @@ -158,6 +160,15 @@ class ControlBottomAppBar extends HookConsumerWidget { label: (unfavorite ? "unfavorite" : "favorite").tr(), onPressed: enabled ? onFavorite : null, ), + if (hasRemote && onDownload != null) + ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 90), + child: ControlBoxButton( + iconData: Icons.download, + label: "download".tr(), + onPressed: onDownload, + ), + ), if (hasLocal && hasRemote && onDelete != null && !isInLockedView) ConstrainedBox( constraints: const BoxConstraints(maxWidth: 90), diff --git a/mobile/lib/widgets/asset_grid/multiselect_grid.dart b/mobile/lib/widgets/asset_grid/multiselect_grid.dart index 8cc725ab77..9904447569 100644 --- a/mobile/lib/widgets/asset_grid/multiselect_grid.dart +++ b/mobile/lib/widgets/asset_grid/multiselect_grid.dart @@ -14,6 +14,7 @@ import 'package:immich_mobile/extensions/collection_extensions.dart'; import 'package:immich_mobile/models/asset_selection_state.dart'; import 'package:immich_mobile/providers/album/album.provider.dart'; import 'package:immich_mobile/providers/asset.provider.dart'; +import 'package:immich_mobile/providers/asset_viewer/download.provider.dart'; import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; import 'package:immich_mobile/providers/multiselect.provider.dart'; import 'package:immich_mobile/providers/routes.provider.dart'; @@ -23,6 +24,7 @@ import 'package:immich_mobile/services/album.service.dart'; import 'package:immich_mobile/services/stack.service.dart'; import 'package:immich_mobile/utils/immich_loading_overlay.dart'; import 'package:immich_mobile/utils/selection_handlers.dart'; +import 'package:immich_mobile/utils/translation.dart'; import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart'; import 'package:immich_mobile/widgets/asset_grid/control_bottom_app_bar.dart'; import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart'; @@ -44,6 +46,7 @@ class MultiselectGrid extends HookConsumerWidget { this.editEnabled = false, this.unarchive = false, this.unfavorite = false, + this.downloadEnabled = true, this.emptyIndicator, }); @@ -57,6 +60,7 @@ class MultiselectGrid extends HookConsumerWidget { final bool archiveEnabled; final bool unarchive; final bool deleteEnabled; + final bool downloadEnabled; final bool favoriteEnabled; final bool unfavorite; final bool editEnabled; @@ -239,6 +243,39 @@ class MultiselectGrid extends HookConsumerWidget { } } + void onDownload() async { + processing.value = true; + try { + final toDownload = selection.value.toList(); + + final results = await ref + .read(downloadStateProvider.notifier) + .downloadAllAsset(toDownload); + + final totalCount = toDownload.length; + final successCount = results.where((e) => e).length; + final failedCount = totalCount - successCount; + + final msg = failedCount > 0 + ? t('assets_downloaded_failed', { + 'count': successCount, + 'error': failedCount, + }) + : t('assets_downloaded_successfully', { + 'count': successCount, + }); + + ImmichToast.show( + context: context, + msg: msg, + gravity: ToastGravity.BOTTOM, + ); + } finally { + processing.value = false; + selectionEnabledHook.value = false; + } + } + void onDeleteRemote([bool shouldDeletePermanently = false]) async { processing.value = true; try { @@ -474,6 +511,7 @@ class MultiselectGrid extends HookConsumerWidget { onArchive: archiveEnabled ? onArchiveAsset : null, onDelete: deleteEnabled ? onDelete : null, onDeleteServer: deleteEnabled ? onDeleteRemote : null, + onDownload: downloadEnabled ? onDownload : null, /// local file deletion is allowed irrespective of [deleteEnabled] since it has /// nothing to do with the state of the asset in the Immich server diff --git a/mobile/openapi/lib/api/timeline_api.dart b/mobile/openapi/lib/api/timeline_api.dart index 399e7bde86..33914d5b47 100644 --- a/mobile/openapi/lib/api/timeline_api.dart +++ b/mobile/openapi/lib/api/timeline_api.dart @@ -31,10 +31,6 @@ class TimelineApi { /// /// * [AssetOrder] order: /// - /// * [num] page: - /// - /// * [num] pageSize: - /// /// * [String] personId: /// /// * [String] tagId: @@ -46,7 +42,7 @@ class TimelineApi { /// * [bool] withPartners: /// /// * [bool] withStacked: - Future getTimeBucketWithHttpInfo(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, num? page, num? pageSize, String? personId, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async { + Future getTimeBucketWithHttpInfo(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async { // ignore: prefer_const_declarations final apiPath = r'/timeline/bucket'; @@ -72,12 +68,6 @@ class TimelineApi { if (order != null) { queryParams.addAll(_queryParams('', 'order', order)); } - if (page != null) { - queryParams.addAll(_queryParams('', 'page', page)); - } - if (pageSize != null) { - queryParams.addAll(_queryParams('', 'pageSize', pageSize)); - } if (personId != null) { queryParams.addAll(_queryParams('', 'personId', personId)); } @@ -126,10 +116,6 @@ class TimelineApi { /// /// * [AssetOrder] order: /// - /// * [num] page: - /// - /// * [num] pageSize: - /// /// * [String] personId: /// /// * [String] tagId: @@ -141,8 +127,8 @@ class TimelineApi { /// * [bool] withPartners: /// /// * [bool] withStacked: - Future getTimeBucket(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, num? page, num? pageSize, String? personId, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async { - final response = await getTimeBucketWithHttpInfo(timeBucket, albumId: albumId, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, page: page, pageSize: pageSize, personId: personId, tagId: tagId, userId: userId, visibility: visibility, withPartners: withPartners, withStacked: withStacked, ); + Future getTimeBucket(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async { + final response = await getTimeBucketWithHttpInfo(timeBucket, albumId: albumId, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, personId: personId, tagId: tagId, userId: userId, visibility: visibility, withPartners: withPartners, withStacked: withStacked, ); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } diff --git a/mobile/openapi/lib/model/activity_statistics_response_dto.dart b/mobile/openapi/lib/model/activity_statistics_response_dto.dart index ad0b814a58..27c478230d 100644 --- a/mobile/openapi/lib/model/activity_statistics_response_dto.dart +++ b/mobile/openapi/lib/model/activity_statistics_response_dto.dart @@ -14,25 +14,31 @@ class ActivityStatisticsResponseDto { /// Returns a new [ActivityStatisticsResponseDto] instance. ActivityStatisticsResponseDto({ required this.comments, + required this.likes, }); int comments; + int likes; + @override bool operator ==(Object other) => identical(this, other) || other is ActivityStatisticsResponseDto && - other.comments == comments; + other.comments == comments && + other.likes == likes; @override int get hashCode => // ignore: unnecessary_parenthesis - (comments.hashCode); + (comments.hashCode) + + (likes.hashCode); @override - String toString() => 'ActivityStatisticsResponseDto[comments=$comments]'; + String toString() => 'ActivityStatisticsResponseDto[comments=$comments, likes=$likes]'; Map toJson() { final json = {}; json[r'comments'] = this.comments; + json[r'likes'] = this.likes; return json; } @@ -46,6 +52,7 @@ class ActivityStatisticsResponseDto { return ActivityStatisticsResponseDto( comments: mapValueOfType(json, r'comments')!, + likes: mapValueOfType(json, r'likes')!, ); } return null; @@ -94,6 +101,7 @@ class ActivityStatisticsResponseDto { /// The list of required keys that must be present in a JSON. static const requiredKeys = { 'comments', + 'likes', }; } diff --git a/mobile/openapi/lib/model/sync_album_user_v1.dart b/mobile/openapi/lib/model/sync_album_user_v1.dart index c2b8ed7f48..0b4968b34d 100644 --- a/mobile/openapi/lib/model/sync_album_user_v1.dart +++ b/mobile/openapi/lib/model/sync_album_user_v1.dart @@ -20,7 +20,7 @@ class SyncAlbumUserV1 { String albumId; - SyncAlbumUserV1RoleEnum role; + AlbumUserRole role; String userId; @@ -58,7 +58,7 @@ class SyncAlbumUserV1 { return SyncAlbumUserV1( albumId: mapValueOfType(json, r'albumId')!, - role: SyncAlbumUserV1RoleEnum.fromJson(json[r'role'])!, + role: AlbumUserRole.fromJson(json[r'role'])!, userId: mapValueOfType(json, r'userId')!, ); } @@ -113,77 +113,3 @@ class SyncAlbumUserV1 { }; } - -class SyncAlbumUserV1RoleEnum { - /// Instantiate a new enum with the provided [value]. - const SyncAlbumUserV1RoleEnum._(this.value); - - /// The underlying value of this enum member. - final String value; - - @override - String toString() => value; - - String toJson() => value; - - static const editor = SyncAlbumUserV1RoleEnum._(r'editor'); - static const viewer = SyncAlbumUserV1RoleEnum._(r'viewer'); - - /// List of all possible values in this [enum][SyncAlbumUserV1RoleEnum]. - static const values = [ - editor, - viewer, - ]; - - static SyncAlbumUserV1RoleEnum? fromJson(dynamic value) => SyncAlbumUserV1RoleEnumTypeTransformer().decode(value); - - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; - if (json is List && json.isNotEmpty) { - for (final row in json) { - final value = SyncAlbumUserV1RoleEnum.fromJson(row); - if (value != null) { - result.add(value); - } - } - } - return result.toList(growable: growable); - } -} - -/// Transformation class that can [encode] an instance of [SyncAlbumUserV1RoleEnum] to String, -/// and [decode] dynamic data back to [SyncAlbumUserV1RoleEnum]. -class SyncAlbumUserV1RoleEnumTypeTransformer { - factory SyncAlbumUserV1RoleEnumTypeTransformer() => _instance ??= const SyncAlbumUserV1RoleEnumTypeTransformer._(); - - const SyncAlbumUserV1RoleEnumTypeTransformer._(); - - String encode(SyncAlbumUserV1RoleEnum data) => data.value; - - /// Decodes a [dynamic value][data] to a SyncAlbumUserV1RoleEnum. - /// - /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully, - /// then null is returned. However, if [allowNull] is false and the [dynamic value][data] - /// cannot be decoded successfully, then an [UnimplementedError] is thrown. - /// - /// The [allowNull] is very handy when an API changes and a new enum value is added or removed, - /// and users are still using an old app with the old code. - SyncAlbumUserV1RoleEnum? decode(dynamic data, {bool allowNull = true}) { - if (data != null) { - switch (data) { - case r'editor': return SyncAlbumUserV1RoleEnum.editor; - case r'viewer': return SyncAlbumUserV1RoleEnum.viewer; - default: - if (!allowNull) { - throw ArgumentError('Unknown enum value to decode: $data'); - } - } - } - return null; - } - - /// Singleton [SyncAlbumUserV1RoleEnumTypeTransformer] instance. - static SyncAlbumUserV1RoleEnumTypeTransformer? _instance; -} - - diff --git a/mobile/openapi/lib/model/sync_asset_v1.dart b/mobile/openapi/lib/model/sync_asset_v1.dart index a3aa7365ad..27042325ee 100644 --- a/mobile/openapi/lib/model/sync_asset_v1.dart +++ b/mobile/openapi/lib/model/sync_asset_v1.dart @@ -47,9 +47,9 @@ class SyncAssetV1 { String? thumbhash; - SyncAssetV1TypeEnum type; + AssetTypeEnum type; - SyncAssetV1VisibilityEnum visibility; + AssetVisibility visibility; @override bool operator ==(Object other) => identical(this, other) || other is SyncAssetV1 && @@ -141,8 +141,8 @@ class SyncAssetV1 { originalFileName: mapValueOfType(json, r'originalFileName')!, ownerId: mapValueOfType(json, r'ownerId')!, thumbhash: mapValueOfType(json, r'thumbhash'), - type: SyncAssetV1TypeEnum.fromJson(json[r'type'])!, - visibility: SyncAssetV1VisibilityEnum.fromJson(json[r'visibility'])!, + type: AssetTypeEnum.fromJson(json[r'type'])!, + visibility: AssetVisibility.fromJson(json[r'visibility'])!, ); } return null; @@ -205,163 +205,3 @@ class SyncAssetV1 { }; } - -class SyncAssetV1TypeEnum { - /// Instantiate a new enum with the provided [value]. - const SyncAssetV1TypeEnum._(this.value); - - /// The underlying value of this enum member. - final String value; - - @override - String toString() => value; - - String toJson() => value; - - static const IMAGE = SyncAssetV1TypeEnum._(r'IMAGE'); - static const VIDEO = SyncAssetV1TypeEnum._(r'VIDEO'); - static const AUDIO = SyncAssetV1TypeEnum._(r'AUDIO'); - static const OTHER = SyncAssetV1TypeEnum._(r'OTHER'); - - /// List of all possible values in this [enum][SyncAssetV1TypeEnum]. - static const values = [ - IMAGE, - VIDEO, - AUDIO, - OTHER, - ]; - - static SyncAssetV1TypeEnum? fromJson(dynamic value) => SyncAssetV1TypeEnumTypeTransformer().decode(value); - - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; - if (json is List && json.isNotEmpty) { - for (final row in json) { - final value = SyncAssetV1TypeEnum.fromJson(row); - if (value != null) { - result.add(value); - } - } - } - return result.toList(growable: growable); - } -} - -/// Transformation class that can [encode] an instance of [SyncAssetV1TypeEnum] to String, -/// and [decode] dynamic data back to [SyncAssetV1TypeEnum]. -class SyncAssetV1TypeEnumTypeTransformer { - factory SyncAssetV1TypeEnumTypeTransformer() => _instance ??= const SyncAssetV1TypeEnumTypeTransformer._(); - - const SyncAssetV1TypeEnumTypeTransformer._(); - - String encode(SyncAssetV1TypeEnum data) => data.value; - - /// Decodes a [dynamic value][data] to a SyncAssetV1TypeEnum. - /// - /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully, - /// then null is returned. However, if [allowNull] is false and the [dynamic value][data] - /// cannot be decoded successfully, then an [UnimplementedError] is thrown. - /// - /// The [allowNull] is very handy when an API changes and a new enum value is added or removed, - /// and users are still using an old app with the old code. - SyncAssetV1TypeEnum? decode(dynamic data, {bool allowNull = true}) { - if (data != null) { - switch (data) { - case r'IMAGE': return SyncAssetV1TypeEnum.IMAGE; - case r'VIDEO': return SyncAssetV1TypeEnum.VIDEO; - case r'AUDIO': return SyncAssetV1TypeEnum.AUDIO; - case r'OTHER': return SyncAssetV1TypeEnum.OTHER; - default: - if (!allowNull) { - throw ArgumentError('Unknown enum value to decode: $data'); - } - } - } - return null; - } - - /// Singleton [SyncAssetV1TypeEnumTypeTransformer] instance. - static SyncAssetV1TypeEnumTypeTransformer? _instance; -} - - - -class SyncAssetV1VisibilityEnum { - /// Instantiate a new enum with the provided [value]. - const SyncAssetV1VisibilityEnum._(this.value); - - /// The underlying value of this enum member. - final String value; - - @override - String toString() => value; - - String toJson() => value; - - static const archive = SyncAssetV1VisibilityEnum._(r'archive'); - static const timeline = SyncAssetV1VisibilityEnum._(r'timeline'); - static const hidden = SyncAssetV1VisibilityEnum._(r'hidden'); - static const locked = SyncAssetV1VisibilityEnum._(r'locked'); - - /// List of all possible values in this [enum][SyncAssetV1VisibilityEnum]. - static const values = [ - archive, - timeline, - hidden, - locked, - ]; - - static SyncAssetV1VisibilityEnum? fromJson(dynamic value) => SyncAssetV1VisibilityEnumTypeTransformer().decode(value); - - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; - if (json is List && json.isNotEmpty) { - for (final row in json) { - final value = SyncAssetV1VisibilityEnum.fromJson(row); - if (value != null) { - result.add(value); - } - } - } - return result.toList(growable: growable); - } -} - -/// Transformation class that can [encode] an instance of [SyncAssetV1VisibilityEnum] to String, -/// and [decode] dynamic data back to [SyncAssetV1VisibilityEnum]. -class SyncAssetV1VisibilityEnumTypeTransformer { - factory SyncAssetV1VisibilityEnumTypeTransformer() => _instance ??= const SyncAssetV1VisibilityEnumTypeTransformer._(); - - const SyncAssetV1VisibilityEnumTypeTransformer._(); - - String encode(SyncAssetV1VisibilityEnum data) => data.value; - - /// Decodes a [dynamic value][data] to a SyncAssetV1VisibilityEnum. - /// - /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully, - /// then null is returned. However, if [allowNull] is false and the [dynamic value][data] - /// cannot be decoded successfully, then an [UnimplementedError] is thrown. - /// - /// The [allowNull] is very handy when an API changes and a new enum value is added or removed, - /// and users are still using an old app with the old code. - SyncAssetV1VisibilityEnum? decode(dynamic data, {bool allowNull = true}) { - if (data != null) { - switch (data) { - case r'archive': return SyncAssetV1VisibilityEnum.archive; - case r'timeline': return SyncAssetV1VisibilityEnum.timeline; - case r'hidden': return SyncAssetV1VisibilityEnum.hidden; - case r'locked': return SyncAssetV1VisibilityEnum.locked; - default: - if (!allowNull) { - throw ArgumentError('Unknown enum value to decode: $data'); - } - } - } - return null; - } - - /// Singleton [SyncAssetV1VisibilityEnumTypeTransformer] instance. - static SyncAssetV1VisibilityEnumTypeTransformer? _instance; -} - - diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 286fa47c66..09c0143e80 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -7380,24 +7380,6 @@ "$ref": "#/components/schemas/AssetOrder" } }, - { - "name": "page", - "required": false, - "in": "query", - "schema": { - "minimum": 1, - "type": "number" - } - }, - { - "name": "pageSize", - "required": false, - "in": "query", - "schema": { - "minimum": 1, - "type": "number" - } - }, { "name": "personId", "required": false, @@ -8500,10 +8482,14 @@ "properties": { "comments": { "type": "integer" + }, + "likes": { + "type": "integer" } }, "required": [ - "comments" + "comments", + "likes" ], "type": "object" }, @@ -13006,11 +12992,11 @@ "type": "string" }, "role": { - "enum": [ - "editor", - "viewer" - ], - "type": "string" + "allOf": [ + { + "$ref": "#/components/schemas/AlbumUserRole" + } + ] }, "userId": { "type": "string" @@ -13259,22 +13245,18 @@ "type": "string" }, "type": { - "enum": [ - "IMAGE", - "VIDEO", - "AUDIO", - "OTHER" - ], - "type": "string" + "allOf": [ + { + "$ref": "#/components/schemas/AssetTypeEnum" + } + ] }, "visibility": { - "enum": [ - "archive", - "timeline", - "hidden", - "locked" - ], - "type": "string" + "allOf": [ + { + "$ref": "#/components/schemas/AssetVisibility" + } + ] } }, "required": [ diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index e3e12dc56e..b390bf7477 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -38,6 +38,7 @@ export type ActivityCreateDto = { }; export type ActivityStatisticsResponseDto = { comments: number; + likes: number; }; export type NotificationCreateDto = { data?: object; @@ -3435,14 +3436,12 @@ export function tagAssets({ id, bulkIdsDto }: { body: bulkIdsDto }))); } -export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, page, pageSize, personId, tagId, timeBucket, userId, visibility, withPartners, withStacked }: { +export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, personId, tagId, timeBucket, userId, visibility, withPartners, withStacked }: { albumId?: string; isFavorite?: boolean; isTrashed?: boolean; key?: string; order?: AssetOrder; - page?: number; - pageSize?: number; personId?: string; tagId?: string; timeBucket: string; @@ -3460,8 +3459,6 @@ export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, page isTrashed, key, order, - page, - pageSize, personId, tagId, timeBucket, diff --git a/server/package-lock.json b/server/package-lock.json index 592ce857f9..8df5b7f249 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -2349,12 +2349,12 @@ } }, "node_modules/@nestjs/common": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.2.tgz", - "integrity": "sha512-cHh4OPH44PjaHM93D1jgE1HO/B7XTZVRDxy/cPuGgyMEA4p2zXO+qqcOgTMC5FYcp7dX9jLeCjXAU0ToFAnODw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.1.tgz", + "integrity": "sha512-crzp+1qeZ5EGL0nFTPy9NrVMAaUWewV5AwtQyv6SQ9yQPXwRl9W9hm1pt0nAtUu5QbYMbSuo7lYcF81EjM+nCA==", "license": "MIT", "dependencies": { - "file-type": "21.0.0", + "file-type": "20.5.0", "iterare": "1.2.1", "load-esm": "1.0.2", "tslib": "2.8.1", @@ -2380,9 +2380,9 @@ } }, "node_modules/@nestjs/core": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.2.tgz", - "integrity": "sha512-QRuyxwu0BjNfmmmunsw1ylX7RSyfDQHt+xD+tKncdtgiMOOzAu+LA1gB4WoZnw4frQkk+qZbhEbM61cIjOxD3w==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.1.tgz", + "integrity": "sha512-UFoUAgLKFT+RwHTANJdr0dF7p0qS9QjkaUPjg8aafnjM/qxxxrUVDB49nVvyMlk+Hr1+vvcNaOHbWWQBxoZcHA==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -2454,14 +2454,14 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.2.tgz", - "integrity": "sha512-GlNwOT4htRp8RpZ+TpqGtSHwGKw/abdxxBRse40XE2SWs5ikaoujr9Yd+5sJWDNXB4QTftwb+FplXhyk1Ra+4A==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.1.tgz", + "integrity": "sha512-IUxk380qnUtz0PCRQ5i+o9UHlGMrFzGPIJxDwyt3JZZwx2AngOlcEcm5e+7YeJQEr2QYX2QyC4tUQg0zde+D7A==", "license": "MIT", "dependencies": { "cors": "2.8.5", "express": "5.1.0", - "multer": "2.0.0", + "multer": "1.4.5-lts.2", "path-to-regexp": "8.2.0", "tslib": "2.8.1" }, @@ -2475,9 +2475,9 @@ } }, "node_modules/@nestjs/platform-socket.io": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.1.2.tgz", - "integrity": "sha512-IkeDPRRddY0In6lE+5H/DJodtF5cEx+ga+GWehs4Il5Y3kK7MVR2/WgUABAhyRsbJYOhIhZD7Dai0V2t9ref1Q==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.1.1.tgz", + "integrity": "sha512-Bsc8ouysUFasWiO8RKEvppqYM5LNkHfbyIJQTy3V6+PUdYhblkvmOq8QtjuHpv6DiBI4siUcxACx/90/CdXLkQ==", "license": "MIT", "dependencies": { "socket.io": "4.8.1", @@ -2663,9 +2663,9 @@ } }, "node_modules/@nestjs/testing": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.2.tgz", - "integrity": "sha512-BQxVKUVW6gzEbbHAvmg5RgcP3s++pRgTCmsgaDF/DtcLRUeKi8SjAdqzLm14xbkMeibxOf3fNqM2iwqUKj8ffw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.1.tgz", + "integrity": "sha512-stzm8YrLDGAijHYQw+8Z9dD6lGdvahL0hIjGVZ/0KBxLZht0/rvRjgV31UK+DUqXaF7yhJTw9ryrPaITxI1J6A==", "dev": true, "license": "MIT", "dependencies": { @@ -2691,9 +2691,9 @@ } }, "node_modules/@nestjs/websockets": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.1.2.tgz", - "integrity": "sha512-Ywl7u0C3+qnKIrk0mD3jHWnowO+GScFT1FeP6cNgarA0ujHEfusph9IIbnUJiEiusfnKVpK9fYMGZRSDwnRGPQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.1.1.tgz", + "integrity": "sha512-gxwQoGx5bW5IvparzrX1UOGXz87eqY0fK5Y6yb14z6tSSubQTciNjCDm5osDEkRyRCG6ZB0F+eXF6dRUjwTlBQ==", "license": "MIT", "dependencies": { "iterare": "1.2.1", @@ -5576,9 +5576,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz", - "integrity": "sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==", + "version": "19.1.5", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.5.tgz", + "integrity": "sha512-piErsCVVbpMMT2r7wbawdZsq4xMvIAhQuac2gedQHysu1TZYEigE6pnFfgZT+/jQnrRuF5r+SHzuehFjfRjr4g==", "dev": true, "license": "MIT", "dependencies": { @@ -5735,17 +5735,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz", - "integrity": "sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", + "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/type-utils": "8.33.0", - "@typescript-eslint/utils": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/type-utils": "8.32.1", + "@typescript-eslint/utils": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -5759,7 +5759,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.33.0", + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -5775,16 +5775,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz", - "integrity": "sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz", + "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/typescript-estree": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4" }, "engines": { @@ -5799,34 +5799,15 @@ "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz", - "integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.33.0", - "@typescript-eslint/types": "^8.33.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz", - "integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0" + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5836,32 +5817,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz", - "integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz", - "integrity": "sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", + "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.33.0", - "@typescript-eslint/utils": "8.33.0", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/utils": "8.32.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -5878,9 +5842,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz", - "integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", "dev": true, "license": "MIT", "engines": { @@ -5892,16 +5856,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz", - "integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.33.0", - "@typescript-eslint/tsconfig-utils": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -5947,16 +5909,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz", - "integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/typescript-estree": "8.33.0" + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5971,13 +5933,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz", - "integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/types": "8.32.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -9610,18 +9572,18 @@ } }, "node_modules/file-type": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz", - "integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==", + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.5.0.tgz", + "integrity": "sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg==", "license": "MIT", "dependencies": { - "@tokenizer/inflate": "^0.2.7", - "strtok3": "^10.2.2", + "@tokenizer/inflate": "^0.2.6", + "strtok3": "^10.2.0", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" }, "engines": { - "node": ">=20" + "node": ">=18" }, "funding": { "url": "https://github.com/sindresorhus/file-type?sponsor=1" @@ -10239,9 +10201,9 @@ } }, "node_modules/globals": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz", - "integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", + "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", "dev": true, "license": "MIT", "engines": { @@ -12163,9 +12125,9 @@ } }, "node_modules/multer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.0.tgz", - "integrity": "sha512-bS8rPZurbAuHGAnApbM9d4h1wSoYqrOqkE+6a64KLMK9yWU7gJXBDDVklKQ3TPi9DRb85cRs6yXaC0+cjxRtRg==", + "version": "1.4.5-lts.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz", + "integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==", "license": "MIT", "dependencies": { "append-field": "^1.0.0", @@ -12177,7 +12139,7 @@ "xtend": "^4.0.0" }, "engines": { - "node": ">= 10.16.0" + "node": ">= 6.0.0" } }, "node_modules/multer/node_modules/concat-stream": { @@ -17090,15 +17052,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.0.tgz", - "integrity": "sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz", + "integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.33.0", - "@typescript-eslint/parser": "8.33.0", - "@typescript-eslint/utils": "8.33.0" + "@typescript-eslint/eslint-plugin": "8.32.1", + "@typescript-eslint/parser": "8.32.1", + "@typescript-eslint/utils": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -17417,9 +17379,9 @@ } }, "node_modules/validator": { - "version": "13.15.15", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", - "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.0.tgz", + "integrity": "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==", "license": "MIT", "engines": { "node": ">= 0.10" diff --git a/server/src/dtos/activity.dto.ts b/server/src/dtos/activity.dto.ts index a97116cf35..d11fe8da7e 100644 --- a/server/src/dtos/activity.dto.ts +++ b/server/src/dtos/activity.dto.ts @@ -29,6 +29,9 @@ export class ActivityResponseDto { export class ActivityStatisticsResponseDto { @ApiProperty({ type: 'integer' }) comments!: number; + + @ApiProperty({ type: 'integer' }) + likes!: number; } export class ActivityDto { diff --git a/server/src/dtos/sync.dto.ts b/server/src/dtos/sync.dto.ts index 3e50762c8a..3088392c68 100644 --- a/server/src/dtos/sync.dto.ts +++ b/server/src/dtos/sync.dto.ts @@ -65,9 +65,11 @@ export class SyncAssetV1 { fileCreatedAt!: Date | null; fileModifiedAt!: Date | null; localDateTime!: Date | null; + @ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType }) type!: AssetType; deletedAt!: Date | null; isFavorite!: boolean; + @ApiProperty({ enumName: 'AssetVisibility', enum: AssetVisibility }) visibility!: AssetVisibility; } @@ -125,6 +127,7 @@ export class SyncAlbumUserDeleteV1 { export class SyncAlbumUserV1 { albumId!: string; userId!: string; + @ApiProperty({ enumName: 'AlbumUserRole', enum: AlbumUserRole }) role!: AlbumUserRole; } diff --git a/server/src/dtos/time-bucket.dto.ts b/server/src/dtos/time-bucket.dto.ts index f68ce93075..3f4157babb 100644 --- a/server/src/dtos/time-bucket.dto.ts +++ b/server/src/dtos/time-bucket.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsEnum, IsInt, IsString, Min } from 'class-validator'; +import { IsEnum, IsString } from 'class-validator'; import { AssetOrder, AssetVisibility } from 'src/enum'; import { Optional, ValidateAssetVisibility, ValidateBoolean, ValidateUUID } from 'src/validation'; @@ -41,16 +41,6 @@ export class TimeBucketDto { export class TimeBucketAssetDto extends TimeBucketDto { @IsString() timeBucket!: string; - - @IsInt() - @Min(1) - @Optional() - page?: number; - - @IsInt() - @Min(1) - @Optional() - pageSize?: number; } export class TimelineStackResponseDto { diff --git a/server/src/queries/activity.repository.sql b/server/src/queries/activity.repository.sql index 3db4ee6f5b..c8b0c4315a 100644 --- a/server/src/queries/activity.repository.sql +++ b/server/src/queries/activity.repository.sql @@ -62,15 +62,21 @@ where -- ActivityRepository.getStatistics select - count(*) as "count" + count(*) filter ( + where + "activity"."isLiked" = $1 + ) as "comments", + count(*) filter ( + where + "activity"."isLiked" = $2 + ) as "likes" from "activity" inner join "users" on "users"."id" = "activity"."userId" and "users"."deletedAt" is null left join "assets" on "assets"."id" = "activity"."assetId" where - "activity"."assetId" = $1 - and "activity"."albumId" = $2 - and "activity"."isLiked" = $3 + "activity"."assetId" = $3 + and "activity"."albumId" = $4 and "assets"."deletedAt" is null and "assets"."visibility" != 'locked' diff --git a/server/src/repositories/activity.repository.ts b/server/src/repositories/activity.repository.ts index f8bbfdf8a6..aa30250868 100644 --- a/server/src/repositories/activity.repository.ts +++ b/server/src/repositories/activity.repository.ts @@ -67,19 +67,27 @@ export class ActivityRepository { } @GenerateSql({ params: [{ albumId: DummyValue.UUID, assetId: DummyValue.UUID }] }) - async getStatistics({ albumId, assetId }: { albumId: string; assetId?: string }): Promise { - const { count } = await this.db + async getStatistics({ + albumId, + assetId, + }: { + albumId: string; + assetId?: string; + }): Promise<{ comments: number; likes: number }> { + const result = await this.db .selectFrom('activity') - .select((eb) => eb.fn.countAll().as('count')) + .select((eb) => [ + eb.fn.countAll().filterWhere('activity.isLiked', '=', false).as('comments'), + eb.fn.countAll().filterWhere('activity.isLiked', '=', true).as('likes'), + ]) .innerJoin('users', (join) => join.onRef('users.id', '=', 'activity.userId').on('users.deletedAt', 'is', null)) .leftJoin('assets', 'assets.id', 'activity.assetId') .$if(!!assetId, (qb) => qb.where('activity.assetId', '=', assetId!)) .where('activity.albumId', '=', albumId) - .where('activity.isLiked', '=', false) .where('assets.deletedAt', 'is', null) .where('assets.visibility', '!=', sql.lit(AssetVisibility.LOCKED)) .executeTakeFirstOrThrow(); - return count; + return result; } } diff --git a/server/src/services/activity.service.spec.ts b/server/src/services/activity.service.spec.ts index 82bd8bba89..aea547e6db 100644 --- a/server/src/services/activity.service.spec.ts +++ b/server/src/services/activity.service.spec.ts @@ -54,13 +54,13 @@ describe(ActivityService.name, () => { }); describe('getStatistics', () => { - it('should get the comment count', async () => { + it('should get the comment and like count', async () => { const [albumId, assetId] = newUuids(); - mocks.activity.getStatistics.mockResolvedValue(1); + mocks.activity.getStatistics.mockResolvedValue({ comments: 1, likes: 3 }); mocks.access.album.checkOwnerAccess.mockResolvedValue(new Set([albumId])); - await expect(sut.getStatistics(factory.auth(), { assetId, albumId })).resolves.toEqual({ comments: 1 }); + await expect(sut.getStatistics(factory.auth(), { assetId, albumId })).resolves.toEqual({ comments: 1, likes: 3 }); }); }); diff --git a/server/src/services/activity.service.ts b/server/src/services/activity.service.ts index 6e3c3d7083..8256a34f02 100644 --- a/server/src/services/activity.service.ts +++ b/server/src/services/activity.service.ts @@ -31,7 +31,7 @@ export class ActivityService extends BaseService { async getStatistics(auth: AuthDto, dto: ActivityDto): Promise { await this.requireAccess({ auth, permission: Permission.ALBUM_READ, ids: [dto.albumId] }); - return { comments: await this.activityRepository.getStatistics({ albumId: dto.albumId, assetId: dto.assetId }) }; + return await this.activityRepository.getStatistics({ albumId: dto.albumId, assetId: dto.assetId }); } async create(auth: AuthDto, dto: ActivityCreateDto): Promise> { diff --git a/web/package-lock.json b/web/package-lock.json index 10e4c0dc39..ef3b105660 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -2229,9 +2229,9 @@ } }, "node_modules/@tailwindcss/node": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.8.tgz", - "integrity": "sha512-OWwBsbC9BFAJelmnNcrKuf+bka2ZxCE2A4Ft53Tkg4uoiE67r/PMEYwCsourC26E+kmxfwE0hVzMdxqeW+xu7Q==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.7.tgz", + "integrity": "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==", "dev": true, "license": "MIT", "dependencies": { @@ -2241,13 +2241,13 @@ "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.8" + "tailwindcss": "4.1.7" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.8.tgz", - "integrity": "sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.7.tgz", + "integrity": "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -2259,24 +2259,24 @@ "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.8", - "@tailwindcss/oxide-darwin-arm64": "4.1.8", - "@tailwindcss/oxide-darwin-x64": "4.1.8", - "@tailwindcss/oxide-freebsd-x64": "4.1.8", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.8", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.8", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.8", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.8", - "@tailwindcss/oxide-linux-x64-musl": "4.1.8", - "@tailwindcss/oxide-wasm32-wasi": "4.1.8", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.8", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.8" + "@tailwindcss/oxide-android-arm64": "4.1.7", + "@tailwindcss/oxide-darwin-arm64": "4.1.7", + "@tailwindcss/oxide-darwin-x64": "4.1.7", + "@tailwindcss/oxide-freebsd-x64": "4.1.7", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.7", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.7", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.7", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.7", + "@tailwindcss/oxide-linux-x64-musl": "4.1.7", + "@tailwindcss/oxide-wasm32-wasi": "4.1.7", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.7", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.7" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.8.tgz", - "integrity": "sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.7.tgz", + "integrity": "sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==", "cpu": [ "arm64" ], @@ -2291,9 +2291,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.8.tgz", - "integrity": "sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.7.tgz", + "integrity": "sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==", "cpu": [ "arm64" ], @@ -2308,9 +2308,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.8.tgz", - "integrity": "sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.7.tgz", + "integrity": "sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==", "cpu": [ "x64" ], @@ -2325,9 +2325,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.8.tgz", - "integrity": "sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.7.tgz", + "integrity": "sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==", "cpu": [ "x64" ], @@ -2342,9 +2342,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.8.tgz", - "integrity": "sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.7.tgz", + "integrity": "sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==", "cpu": [ "arm" ], @@ -2359,9 +2359,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.8.tgz", - "integrity": "sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.7.tgz", + "integrity": "sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==", "cpu": [ "arm64" ], @@ -2376,9 +2376,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.8.tgz", - "integrity": "sha512-O6b8QesPbJCRshsNApsOIpzKt3ztG35gfX9tEf4arD7mwNinsoCKxkj8TgEE0YRjmjtO3r9FlJnT/ENd9EVefQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.7.tgz", + "integrity": "sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==", "cpu": [ "arm64" ], @@ -2393,9 +2393,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.8.tgz", - "integrity": "sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.7.tgz", + "integrity": "sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==", "cpu": [ "x64" ], @@ -2410,9 +2410,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.8.tgz", - "integrity": "sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.7.tgz", + "integrity": "sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==", "cpu": [ "x64" ], @@ -2427,9 +2427,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.8.tgz", - "integrity": "sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.7.tgz", + "integrity": "sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -2448,7 +2448,7 @@ "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", - "@napi-rs/wasm-runtime": "^0.2.10", + "@napi-rs/wasm-runtime": "^0.2.9", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, @@ -2456,10 +2456,70 @@ "node": ">=14.0.0" } }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.4.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.4.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.9", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.0", + "@emnapi/runtime": "^1.4.0", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.0", + "dev": true, + "inBundle": true, + "license": "0BSD", + "optional": true + }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.8.tgz", - "integrity": "sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.7.tgz", + "integrity": "sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==", "cpu": [ "arm64" ], @@ -2474,9 +2534,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.8.tgz", - "integrity": "sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.7.tgz", + "integrity": "sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==", "cpu": [ "x64" ], @@ -2568,15 +2628,15 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.8.tgz", - "integrity": "sha512-CQ+I8yxNV5/6uGaJjiuymgw0kEQiNKRinYbZXPdx1fk5WgiyReG0VaUx/Xq6aVNSUNJFzxm6o8FNKS5aMaim5A==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.7.tgz", + "integrity": "sha512-tYa2fO3zDe41I7WqijyVbRd8oWT0aEID1Eokz5hMT6wShLIHj3yvwj9XbfuloHP9glZ6H+aG2AN/+ZrxJ1Y5RQ==", "dev": true, "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.1.8", - "@tailwindcss/oxide": "4.1.8", - "tailwindcss": "4.1.8" + "@tailwindcss/node": "4.1.7", + "@tailwindcss/oxide": "4.1.7", + "tailwindcss": "4.1.7" }, "peerDependencies": { "vite": "^5.2.0 || ^6" @@ -2888,17 +2948,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz", - "integrity": "sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", + "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/type-utils": "8.33.0", - "@typescript-eslint/utils": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/type-utils": "8.32.1", + "@typescript-eslint/utils": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -2912,7 +2972,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.33.0", + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -2928,16 +2988,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz", - "integrity": "sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz", + "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/typescript-estree": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4" }, "engines": { @@ -2952,34 +3012,15 @@ "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz", - "integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.33.0", - "@typescript-eslint/types": "^8.33.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz", - "integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0" + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2989,32 +3030,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz", - "integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz", - "integrity": "sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", + "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.33.0", - "@typescript-eslint/utils": "8.33.0", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/utils": "8.32.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -3031,9 +3055,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz", - "integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", "dev": true, "license": "MIT", "engines": { @@ -3045,16 +3069,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz", - "integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.33.0", - "@typescript-eslint/tsconfig-utils": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/visitor-keys": "8.33.0", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3100,16 +3122,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz", - "integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.33.0", - "@typescript-eslint/types": "8.33.0", - "@typescript-eslint/typescript-estree": "8.33.0" + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3124,13 +3146,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz", - "integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/types": "8.32.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -4957,9 +4979,9 @@ } }, "node_modules/fabric": { - "version": "6.6.6", - "resolved": "https://registry.npmjs.org/fabric/-/fabric-6.6.6.tgz", - "integrity": "sha512-cL0m/RanEIiP67/TAj8kAQcEYlXofeB1SXCB1w7a0ktyUQHdRpnm2/VHlqsD/PfSLlGqftHzmxAS4LvKzSlrEw==", + "version": "6.6.5", + "resolved": "https://registry.npmjs.org/fabric/-/fabric-6.6.5.tgz", + "integrity": "sha512-BFxyLDeLMMgtteqQwKAyRM+oSkf82lDFzsiC7AMob7k7ag7naFuHOtWtcll4v+M9Cpn5aqRBfz1shnsO0vZhbg==", "license": "MIT", "engines": { "node": ">=16.20.0" @@ -5429,9 +5451,9 @@ } }, "node_modules/globals": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz", - "integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", + "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", "dev": true, "license": "MIT", "engines": { @@ -8612,9 +8634,9 @@ } }, "node_modules/svelte": { - "version": "5.33.6", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.33.6.tgz", - "integrity": "sha512-bxg2QY03JlrilCZmDlshY95Argj0rnX43UQFWZN4fct8PZTNBBmvfow2A6yOW1+YweDjhC2qdZF66ASI0Y21Tw==", + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.33.1.tgz", + "integrity": "sha512-7znzaaQALL62NBzkdKV04tmYIVla8qjrW+k6GdgFZcKcj8XOb8iEjmfRPo40iaWZlKv3+uiuc0h4iaGgwoORtA==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", @@ -8863,9 +8885,9 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz", - "integrity": "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz", + "integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==", "license": "MIT" }, "node_modules/tapable": { @@ -9189,15 +9211,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.33.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.0.tgz", - "integrity": "sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz", + "integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.33.0", - "@typescript-eslint/parser": "8.33.0", - "@typescript-eslint/utils": "8.33.0" + "@typescript-eslint/eslint-plugin": "8.32.1", + "@typescript-eslint/parser": "8.32.1", + "@typescript-eslint/utils": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/web/src/lib/components/asset-viewer/activity-status.svelte b/web/src/lib/components/asset-viewer/activity-status.svelte index 494c6fcbf7..f240d9a6e9 100644 --- a/web/src/lib/components/asset-viewer/activity-status.svelte +++ b/web/src/lib/components/asset-viewer/activity-status.svelte @@ -7,25 +7,29 @@ interface Props { isLiked: ActivityResponseDto | null; numberOfComments: number | undefined; + numberOfLikes: number | undefined; disabled: boolean; onOpenActivityTab: () => void; onFavorite: () => void; } - let { isLiked, numberOfComments, disabled, onOpenActivityTab, onFavorite }: Props = $props(); + let { isLiked, numberOfComments, numberOfLikes, disabled, onOpenActivityTab, onFavorite }: Props = $props(); -

+
diff --git a/web/src/lib/components/asset-viewer/activity-viewer.svelte b/web/src/lib/components/asset-viewer/activity-viewer.svelte index 3c0775ad34..c4aa7098d5 100644 --- a/web/src/lib/components/asset-viewer/activity-viewer.svelte +++ b/web/src/lib/components/asset-viewer/activity-viewer.svelte @@ -118,12 +118,9 @@ }; -
-
-
+
+
+
@@ -569,6 +570,7 @@ asset={toTimelineAsset(stackedAsset)} onClick={() => { asset = stackedAsset; + previewStackedAsset = undefined; }} onMouseEvent={({ isMouseOver }) => handleStackedAssetMouseEvent(isMouseOver, stackedAsset)} readonly diff --git a/web/src/lib/components/asset-viewer/detail-panel-tags.svelte b/web/src/lib/components/asset-viewer/detail-panel-tags.svelte index aeef6bd06e..39afc1e506 100644 --- a/web/src/lib/components/asset-viewer/detail-panel-tags.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel-tags.svelte @@ -70,7 +70,9 @@ title="Add tag" onclick={handleAddTag} > - Add + {$t('add')} diff --git a/web/src/lib/components/photos-page/actions/delete-assets.svelte b/web/src/lib/components/photos-page/actions/delete-assets.svelte index b16e046523..e3b592b5cb 100644 --- a/web/src/lib/components/photos-page/actions/delete-assets.svelte +++ b/web/src/lib/components/photos-page/actions/delete-assets.svelte @@ -1,6 +1,6 @@ {#if !themeManager.theme.system} - themeManager.setTheme(theme == 'dark' ? Theme.DARK : Theme.LIGHT)} - /> + {#await langs + .find((item) => item.code === get(lang)) + ?.loader() ?? defaultLang.loader() then { default: translations }} + themeManager.setTheme(theme == 'dark' ? Theme.DARK : Theme.LIGHT)} + /> + {/await} {/if} diff --git a/web/src/lib/components/user-settings-page/app-settings.svelte b/web/src/lib/components/user-settings-page/app-settings.svelte index adb37d5d93..d248038a24 100644 --- a/web/src/lib/components/user-settings-page/app-settings.svelte +++ b/web/src/lib/components/user-settings-page/app-settings.svelte @@ -39,7 +39,7 @@ }; const handleToggleLocaleBrowser = () => { - $locale = $locale ? undefined : fallbackLocale.code; + $locale = $locale === 'default' ? fallbackLocale.code : 'default'; }; const handleLocaleChange = (newLocale: string | undefined) => { @@ -89,13 +89,13 @@

{selectedDate}

- {#if $locale !== undefined} + {#if $locale !== 'default'}
($alwaysLoadOriginalFile = !$alwaysLoadOriginalFile)} />
@@ -121,16 +120,10 @@ title={$t('video_hover_setting')} subtitle={$t('video_hover_setting_description')} bind:checked={$playVideoThumbnailOnHover} - onToggle={() => ($playVideoThumbnailOnHover = !$playVideoThumbnailOnHover)} />
- ($loopVideo = !$loopVideo)} - /> +
diff --git a/web/src/lib/constants.ts b/web/src/lib/constants.ts index fdb18b3978..ae53b4e7f3 100644 --- a/web/src/lib/constants.ts +++ b/web/src/lib/constants.ts @@ -273,9 +273,17 @@ export const locales = [ { code: 'zu-ZA', name: 'Zulu (South Africa)' }, ]; -export const defaultLang = { name: 'English', code: 'en', loader: () => import('$i18n/en.json') }; +interface Lang { + name: string; + code: string; + loader: () => Promise<{ default: object }>; + rtl?: boolean; + weblateCode?: string; +} -export const langs = [ +export const defaultLang: Lang = { name: 'English', code: 'en', loader: () => import('$i18n/en.json') }; + +export const langs: Lang[] = [ { name: 'Afrikaans', code: 'af', loader: () => import('$i18n/af.json') }, { name: 'Arabic', code: 'ar', loader: () => import('$i18n/ar.json'), rtl: true }, { name: 'Azerbaijani', code: 'az', loader: () => import('$i18n/az.json'), rtl: true }, @@ -359,7 +367,7 @@ export const langs = [ weblateCode: 'zh_SIMPLIFIED', loader: () => import('$i18n/zh_SIMPLIFIED.json'), }, - { name: 'Development (keys only)', code: 'dev', loader: () => Promise.resolve({}) }, + { name: 'Development (keys only)', code: 'dev', loader: () => Promise.resolve({ default: {} }) }, ]; export enum ImmichProduct { diff --git a/web/src/lib/managers/activity-manager.svelte.ts b/web/src/lib/managers/activity-manager.svelte.ts index a527778bb1..c566f4f508 100644 --- a/web/src/lib/managers/activity-manager.svelte.ts +++ b/web/src/lib/managers/activity-manager.svelte.ts @@ -17,6 +17,7 @@ class ActivityManager { #assetId = $state(); #activities = $state([]); #commentCount = $state(0); + #likeCount = $state(0); #isLiked = $state(null); get activities() { @@ -27,6 +28,10 @@ class ActivityManager { return this.#commentCount; } + get likeCount() { + return this.#likeCount; + } + get isLiked() { return this.#isLiked; } @@ -48,6 +53,10 @@ class ActivityManager { this.#commentCount++; } + if (activity.type === ReactionType.Like) { + this.#likeCount++; + } + handlePromiseError(this.refreshActivities(this.#albumId, this.#assetId)); return activity; } @@ -61,6 +70,10 @@ class ActivityManager { this.#commentCount--; } + if (activity.type === ReactionType.Like) { + this.#likeCount--; + } + this.#activities = index ? this.#activities.splice(index, 1) : this.#activities.filter(({ id }) => id !== activity.id); @@ -98,8 +111,9 @@ class ActivityManager { }); this.#isLiked = liked ?? null; - const { comments } = await getActivityStatistics({ albumId, assetId }); + const { comments, likes } = await getActivityStatistics({ albumId, assetId }); this.#commentCount = comments; + this.#likeCount = likes; } reset() { @@ -107,6 +121,7 @@ class ActivityManager { this.#assetId = undefined; this.#activities = []; this.#commentCount = 0; + this.#likeCount = 0; } } diff --git a/web/src/lib/stores/preferences.store.ts b/web/src/lib/stores/preferences.store.ts index e7f38eb6d0..f0689e5d6e 100644 --- a/web/src/lib/stores/preferences.store.ts +++ b/web/src/lib/stores/preferences.store.ts @@ -9,9 +9,9 @@ export interface ThemeSetting { } // Locale to use for formatting dates, numbers, etc. -export const locale = persisted('locale', undefined, { +export const locale = persisted('locale', 'default', { serializer: { - parse: (text) => (text == '' ? 'en-US' : text), + parse: (text) => text || 'default', stringify: (object) => object ?? '', }, }); diff --git a/web/src/lib/utils/actions.ts b/web/src/lib/utils/actions.ts index 08a22de3f9..166ca94f74 100644 --- a/web/src/lib/utils/actions.ts +++ b/web/src/lib/utils/actions.ts @@ -1,12 +1,13 @@ import { notificationController, NotificationType } from '$lib/components/shared-components/notification/notification'; import type { AssetStore, TimelineAsset } from '$lib/stores/assets-store.svelte'; import type { StackResponse } from '$lib/utils/asset-utils'; -import { AssetVisibility, deleteAssets as deleteBulk } from '@immich/sdk'; +import { AssetVisibility, deleteAssets as deleteBulk, restoreAssets } from '@immich/sdk'; import { t } from 'svelte-i18n'; import { get } from 'svelte/store'; import { handleError } from './handle-error'; export type OnDelete = (assetIds: string[]) => void; +export type OnUndoDelete = (assets: TimelineAsset[]) => void; export type OnRestore = (ids: string[]) => void; export type OnLink = (assets: { still: TimelineAsset; motion: TimelineAsset }) => void; export type OnUnlink = (assets: { still: TimelineAsset; motion: TimelineAsset }) => void; @@ -17,9 +18,15 @@ export type OnStack = (result: StackResponse) => void; export type OnUnstack = (assets: TimelineAsset[]) => void; export type OnSetVisibility = (ids: string[]) => void; -export const deleteAssets = async (force: boolean, onAssetDelete: OnDelete, ids: string[]) => { +export const deleteAssets = async ( + force: boolean, + onAssetDelete: OnDelete, + assets: TimelineAsset[], + onUndoDelete: OnUndoDelete | undefined = undefined, +) => { const $t = get(t); try { + const ids = assets.map((a) => a.id); await deleteBulk({ assetBulkDeleteDto: { ids, force } }); onAssetDelete(ids); @@ -28,12 +35,28 @@ export const deleteAssets = async (force: boolean, onAssetDelete: OnDelete, ids: ? $t('assets_permanently_deleted_count', { values: { count: ids.length } }) : $t('assets_trashed_count', { values: { count: ids.length } }), type: NotificationType.Info, + ...(onUndoDelete && + !force && { + button: { text: $t('undo'), onClick: () => undoDeleteAssets(onUndoDelete, assets) }, + timeout: 5000, + }), }); } catch (error) { handleError(error, $t('errors.unable_to_delete_assets')); } }; +const undoDeleteAssets = async (onUndoDelete: OnUndoDelete, assets: TimelineAsset[]) => { + const $t = get(t); + try { + const ids = assets.map((a) => a.id); + await restoreAssets({ bulkIdsDto: { ids } }); + onUndoDelete?.(assets); + } catch (error) { + handleError(error, $t('errors.unable_to_restore_assets')); + } +}; + /** * Update the asset stack state in the asset store based on the provided stack response. * This function updates the stack information so that the icon is shown for the primary asset diff --git a/web/src/lib/utils/timeline-util.spec.ts b/web/src/lib/utils/timeline-util.spec.ts index f842b948e0..c77aefc0b4 100644 --- a/web/src/lib/utils/timeline-util.spec.ts +++ b/web/src/lib/utils/timeline-util.spec.ts @@ -1,3 +1,4 @@ +import { locale } from '$lib/stores/preferences.store'; import { parseUtcDate } from '$lib/utils/date-time'; import { formatGroupTitle } from '$lib/utils/timeline-util'; import { DateTime } from 'luxon'; @@ -16,48 +17,63 @@ describe('formatGroupTitle', () => { it('formats today', () => { const date = parseUtcDate('2024-07-27T01:00:00Z'); - expect(formatGroupTitle(date.setLocale('en'))).toBe('today'); - expect(formatGroupTitle(date.setLocale('es'))).toBe('hoy'); + locale.set('en'); + expect(formatGroupTitle(date)).toBe('today'); + locale.set('es'); + expect(formatGroupTitle(date)).toBe('hoy'); }); it('formats yesterday', () => { const date = parseUtcDate('2024-07-26T23:59:59Z'); - expect(formatGroupTitle(date.setLocale('en'))).toBe('yesterday'); - expect(formatGroupTitle(date.setLocale('fr'))).toBe('hier'); + locale.set('en'); + expect(formatGroupTitle(date)).toBe('yesterday'); + locale.set('fr'); + expect(formatGroupTitle(date)).toBe('hier'); }); it('formats last week', () => { const date = parseUtcDate('2024-07-21T00:00:00Z'); - expect(formatGroupTitle(date.setLocale('en'))).toBe('Sunday'); - expect(formatGroupTitle(date.setLocale('ar-SA'))).toBe('الأحد'); + locale.set('en'); + expect(formatGroupTitle(date)).toBe('Sunday'); + locale.set('ar-SA'); + expect(formatGroupTitle(date)).toBe('الأحد'); }); it('formats date 7 days ago', () => { const date = parseUtcDate('2024-07-20T00:00:00Z'); - expect(formatGroupTitle(date.setLocale('en'))).toBe('Sat, Jul 20'); - expect(formatGroupTitle(date.setLocale('de'))).toBe('Sa., 20. Juli'); + locale.set('en'); + expect(formatGroupTitle(date)).toBe('Sat, Jul 20'); + locale.set('de'); + expect(formatGroupTitle(date)).toBe('Sa., 20. Juli'); }); it('formats date this year', () => { const date = parseUtcDate('2020-01-01T00:00:00Z'); - expect(formatGroupTitle(date.setLocale('en'))).toBe('Wed, Jan 1, 2020'); - expect(formatGroupTitle(date.setLocale('ja'))).toBe('2020年1月1日(水)'); + locale.set('en'); + expect(formatGroupTitle(date)).toBe('Wed, Jan 1, 2020'); + locale.set('ja'); + expect(formatGroupTitle(date)).toBe('2020年1月1日(水)'); }); it('formats future date', () => { const tomorrow = parseUtcDate('2024-07-28T00:00:00Z'); - expect(formatGroupTitle(tomorrow.setLocale('en'))).toBe('Sun, Jul 28'); + locale.set('en'); + expect(formatGroupTitle(tomorrow)).toBe('Sun, Jul 28'); const nextMonth = parseUtcDate('2024-08-28T00:00:00Z'); - expect(formatGroupTitle(nextMonth.setLocale('en'))).toBe('Wed, Aug 28'); + locale.set('en'); + expect(formatGroupTitle(nextMonth)).toBe('Wed, Aug 28'); const nextYear = parseUtcDate('2025-01-10T12:00:00Z'); - expect(formatGroupTitle(nextYear.setLocale('en'))).toBe('Fri, Jan 10, 2025'); + locale.set('en'); + expect(formatGroupTitle(nextYear)).toBe('Fri, Jan 10, 2025'); }); it('returns "Invalid DateTime" when date is invalid', () => { const date = DateTime.invalid('test'); - expect(formatGroupTitle(date.setLocale('en'))).toBe('Invalid DateTime'); - expect(formatGroupTitle(date.setLocale('es'))).toBe('Invalid DateTime'); + locale.set('en'); + expect(formatGroupTitle(date)).toBe('Invalid DateTime'); + locale.set('es'); + expect(formatGroupTitle(date)).toBe('Invalid DateTime'); }); }); diff --git a/web/src/lib/utils/timeline-util.ts b/web/src/lib/utils/timeline-util.ts index d8252271a2..7538e0e02c 100644 --- a/web/src/lib/utils/timeline-util.ts +++ b/web/src/lib/utils/timeline-util.ts @@ -62,12 +62,12 @@ export function formatGroupTitle(_date: DateTime): string { // Today if (today.hasSame(date, 'day')) { - return date.toRelativeCalendar(); + return date.toRelativeCalendar({ locale: get(locale) }); } // Yesterday if (today.minus({ days: 1 }).hasSame(date, 'day')) { - return date.toRelativeCalendar(); + return date.toRelativeCalendar({ locale: get(locale) }); } // Last week diff --git a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte index bf870f8b0c..6e52b858ba 100644 --- a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -87,6 +87,7 @@ import { t } from 'svelte-i18n'; import { fly } from 'svelte/transition'; import type { PageData } from './$types'; + import { type TimelineAsset } from '$lib/stores/assets-store.svelte'; interface Props { data: PageData; @@ -317,6 +318,11 @@ await refreshAlbum(); }; + const handleUndoRemoveAssets = async (assets: TimelineAsset[]) => { + assetStore.addAssets(assets); + await refreshAlbum(); + }; + const handleUpdateThumbnail = async (assetId: string) => { if (viewMode !== AlbumPageViewMode.SELECT_THUMBNAIL) { return; @@ -570,6 +576,7 @@ disabled={!album.isActivityEnabled} isLiked={activityManager.isLiked} numberOfComments={activityManager.commentCount} + numberOfLikes={undefined} onFavorite={handleFavorite} onOpenActivityTab={handleOpenAndCloseActivityTab} /> @@ -623,7 +630,7 @@ {/if} {#if assetInteraction.isAllUserOwned} - + {/if} diff --git a/web/src/routes/(user)/archive/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/archive/[[photos=photos]]/[[assetId=id]]/+page.svelte index b1cafa9d98..39096ac38b 100644 --- a/web/src/routes/(user)/archive/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/archive/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -13,6 +13,7 @@ import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte'; import { AssetAction } from '$lib/constants'; + import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte'; import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { AssetStore } from '$lib/stores/assets-store.svelte'; import { AssetVisibility } from '@immich/sdk'; @@ -20,7 +21,6 @@ import { onDestroy } from 'svelte'; import { t } from 'svelte-i18n'; import type { PageData } from './$types'; - import SetVisibilityAction from '$lib/components/photos-page/actions/set-visibility-action.svelte'; interface Props { data: PageData; diff --git a/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte index c08b080637..119eaed943 100644 --- a/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -92,7 +92,11 @@ {/if} - assetStore.removeAssets(assetIds)} /> + assetStore.removeAssets(assetIds)} + onUndoDelete={(assets) => assetStore.addAssets(assets)} + /> {/if} diff --git a/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte index a907040490..8b02e01d84 100644 --- a/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -122,6 +122,7 @@ {viewport} showAssetName={true} pageHeaderOffset={54} + onReload={triggerAssetUpdate} />
{/if} @@ -170,7 +171,7 @@ {#if $preferences.tags.enabled && assetInteraction.isAllUserOwned} {/if} - +
diff --git a/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte index c0ffbe0b95..6a28786bf9 100644 --- a/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -351,6 +351,11 @@ await updateAssetCount(); }; + const handleUndoDeleteAssets = async (assets: TimelineAsset[]) => { + assetStore.addAssets(assets); + await updateAssetCount(); + }; + let person = $derived(data.person); let thumbnailData = $derived(getPeopleThumbnailUrl(person)); @@ -532,7 +537,11 @@ {/if} - handleDeleteAssets(assetIds)} /> + handleDeleteAssets(assetIds)} + onUndoDelete={(assets) => handleUndoDeleteAssets(assets)} + /> {:else} diff --git a/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte index 82816b36b4..4a9adaa898 100644 --- a/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte @@ -150,7 +150,11 @@ {#if $preferences.tags.enabled} {/if} - assetStore.removeAssets(assetIds)} /> + assetStore.removeAssets(assetIds)} + onUndoDelete={(assets) => assetStore.addAssets(assets)} + />
diff --git a/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte index e1aa6f9d27..6e19917022 100644 --- a/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -301,7 +301,7 @@ {#if $preferences.tags.enabled && assetInteraction.isAllUserOwned} {/if} - +
@@ -382,6 +382,7 @@ showArchiveIcon={true} {viewport} pageHeaderOffset={54} + onReload={onSearchQueryUpdate} /> {:else if !isLoading}
@@ -444,7 +445,7 @@ {#if $preferences.tags.enabled && assetInteraction.isAllUserOwned} {/if} - +