Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0810ae80e
|
||
|
|
d688e5181f
|
||
|
|
1d7f888563
|
||
|
|
482708038e
|
||
|
|
ce3830ba2e
|
||
|
|
0acf23b2f6
|
||
|
|
31adc14156
|
||
|
|
bd9209359e
|
||
|
|
803cfb8742
|
||
|
|
f3fdf76817
|
||
|
|
2777e6dac0
|
||
|
|
a551d5fb52
|
||
|
|
08915ad2ae
|
||
|
|
1dd75f8ccf
|
||
|
|
3dc24ab3d7
|
||
|
|
a3e9067ba0
|
||
|
|
a0a763ae57
|
||
|
|
c56a903d55
|
||
|
|
c07828f244
|
||
|
|
cf4f1c15ea
|
||
|
|
76797c6120
|
||
|
|
36ed3e0095
|
||
|
|
e0ba25da77
|
||
|
|
e89b0fac8a
|
||
|
|
fa256dd004
|
||
|
|
b5c6598722
|
||
|
|
db111aaa2e
|
||
|
|
c1ac567204
|
||
|
|
1e11525c8e
|
||
|
|
b46c52e042
|
||
|
|
848511769e
|
||
|
|
376078d7f4
|
||
|
|
cb630a9d57
|
||
|
|
6ec7e8df82
|
||
|
|
1e93ef4d07
|
||
|
|
af4d634ed9
|
||
|
|
caf8d7fc7e
|
||
|
|
319d736274
|
||
|
|
426d507ec2
|
||
|
|
e5d9226233
|
||
|
|
bc1ca2a2b1
|
||
|
|
2e1cd07b99
|
||
|
|
370fa2b85d
|
||
|
|
7dedd4f91d
|
No files matched your search
@@ -1,3 +0,0 @@
|
|||||||
# Berry Dash Launcher
|
|
||||||
|
|
||||||
The version launcher for Berry Dash users
|
|
||||||
@@ -11,29 +11,29 @@
|
|||||||
"@fortawesome/react-fontawesome": "3.1.1",
|
"@fortawesome/react-fontawesome": "3.1.1",
|
||||||
"@tauri-apps/api": "2.9.1",
|
"@tauri-apps/api": "2.9.1",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
||||||
"@tauri-apps/plugin-dialog": "2.4.2",
|
"@tauri-apps/plugin-dialog": "2.6.0",
|
||||||
"@tauri-apps/plugin-fs": "2.4.4",
|
"@tauri-apps/plugin-fs": "2.4.5",
|
||||||
"@tauri-apps/plugin-notification": "2.3.3",
|
"@tauri-apps/plugin-notification": "2.3.3",
|
||||||
"@tauri-apps/plugin-opener": "2.5.2",
|
"@tauri-apps/plugin-opener": "2.5.3",
|
||||||
"@tauri-apps/plugin-os": "2.3.2",
|
"@tauri-apps/plugin-os": "2.3.2",
|
||||||
"axios": "1.13.2",
|
"@tauri-apps/plugin-window-state": "2.4.1",
|
||||||
"date-fns": "4.1.0",
|
"axios": "1.13.4",
|
||||||
"next": "16.1.0",
|
"next": "16.1.6",
|
||||||
"pretty-bytes": "7.1.0",
|
"pretty-bytes": "7.1.0",
|
||||||
"react": "19.2.3",
|
"react": "19.2.4",
|
||||||
"react-dom": "19.2.3",
|
"react-dom": "19.2.4",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "3.3.3",
|
"@eslint/eslintrc": "3.3.3",
|
||||||
"@tailwindcss/postcss": "4.1.18",
|
"@tailwindcss/postcss": "4.1.18",
|
||||||
"@tauri-apps/cli": "2.9.6",
|
"@tauri-apps/cli": "2.9.6",
|
||||||
"@types/crypto-js": "4.2.2",
|
"@types/crypto-js": "4.2.2",
|
||||||
"@types/node": "25.0.3",
|
"@types/node": "25.0.10",
|
||||||
"@types/react": "19.2.7",
|
"@types/react": "19.2.10",
|
||||||
"@types/react-dom": "19.2.3",
|
"@types/react-dom": "19.2.3",
|
||||||
"crypto-js": "4.2.0",
|
"crypto-js": "4.2.0",
|
||||||
"eslint": "9.39.2",
|
"eslint": "9.39.2",
|
||||||
"eslint-config-next": "16.1.0",
|
"eslint-config-next": "16.1.6",
|
||||||
"tailwindcss": "4.1.18",
|
"tailwindcss": "4.1.18",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
},
|
},
|
||||||
@@ -42,21 +42,21 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||||
|
|
||||||
"@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
|
"@babel/code-frame": ["@babel/code-frame@7.28.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q=="],
|
||||||
|
|
||||||
"@babel/compat-data": ["@babel/compat-data@7.28.5", "", {}, "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA=="],
|
"@babel/compat-data": ["@babel/compat-data@7.28.6", "", {}, "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg=="],
|
||||||
|
|
||||||
"@babel/core": ["@babel/core@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw=="],
|
"@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="],
|
||||||
|
|
||||||
"@babel/generator": ["@babel/generator@7.28.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="],
|
"@babel/generator": ["@babel/generator@7.28.6", "", { "dependencies": { "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw=="],
|
||||||
|
|
||||||
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
|
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="],
|
||||||
|
|
||||||
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
|
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
|
||||||
|
|
||||||
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
|
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="],
|
||||||
|
|
||||||
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
|
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="],
|
||||||
|
|
||||||
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
|
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
|
||||||
|
|
||||||
@@ -64,23 +64,23 @@
|
|||||||
|
|
||||||
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
|
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
|
||||||
|
|
||||||
"@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="],
|
"@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="],
|
||||||
|
|
||||||
"@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="],
|
"@babel/parser": ["@babel/parser@7.28.6", "", { "dependencies": { "@babel/types": "^7.28.6" }, "bin": "./bin/babel-parser.js" }, "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ=="],
|
||||||
|
|
||||||
"@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
|
"@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="],
|
||||||
|
|
||||||
"@babel/traverse": ["@babel/traverse@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/types": "^7.28.5", "debug": "^4.3.1" } }, "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ=="],
|
"@babel/traverse": ["@babel/traverse@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/types": "^7.28.6", "debug": "^4.3.1" } }, "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg=="],
|
||||||
|
|
||||||
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
|
"@babel/types": ["@babel/types@7.28.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg=="],
|
||||||
|
|
||||||
"@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="],
|
"@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
|
||||||
|
|
||||||
"@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="],
|
"@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
||||||
|
|
||||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||||
|
|
||||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="],
|
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
|
||||||
|
|
||||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
||||||
|
|
||||||
@@ -178,25 +178,25 @@
|
|||||||
|
|
||||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
|
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
|
||||||
|
|
||||||
"@next/env": ["@next/env@16.1.0", "", {}, "sha512-Dd23XQeFHmhf3KBW76leYVkejHlCdB7erakC2At2apL1N08Bm+dLYNP+nNHh0tzUXfPQcNcXiQyacw0PG4Fcpw=="],
|
"@next/env": ["@next/env@16.1.6", "", {}, "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ=="],
|
||||||
|
|
||||||
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.1.0", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-sooC/k0LCF4/jLXYHpgfzJot04lZQqsttn8XJpTguP8N3GhqXN3wSkh68no2OcZzS/qeGwKDFTqhZ8WofdXmmQ=="],
|
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.1.6", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ=="],
|
||||||
|
|
||||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-onHq8dl8KjDb8taANQdzs3XmIqQWV3fYdslkGENuvVInFQzZnuBYYOG2HGHqqtvgmEU7xWzhgndXXxnhk4Z3fQ=="],
|
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw=="],
|
||||||
|
|
||||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.1.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Am6VJTp8KhLuAH13tPrAoVIXzuComlZlMwGr++o2KDjWiKPe3VwpxYhgV6I4gKls2EnsIMggL4y7GdXyDdJcFA=="],
|
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.1.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ=="],
|
||||||
|
|
||||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.1.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-fVicfaJT6QfghNyg8JErZ+EMNQ812IS0lmKfbmC01LF1nFBcKfcs4Q75Yy8IqnsCqH/hZwGhqzj3IGVfWV6vpA=="],
|
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw=="],
|
||||||
|
|
||||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.1.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-TojQnDRoX7wJWXEEwdfuJtakMDW64Q7NrxQPviUnfYJvAx5/5wcGE+1vZzQ9F17m+SdpFeeXuOr6v3jbyusYMQ=="],
|
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ=="],
|
||||||
|
|
||||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.1.0", "", { "os": "linux", "cpu": "x64" }, "sha512-quhNFVySW4QwXiZkZ34SbfzNBm27vLrxZ2HwTfFFO1BBP0OY1+pI0nbyewKeq1FriqU+LZrob/cm26lwsiAi8Q=="],
|
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ=="],
|
||||||
|
|
||||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.1.0", "", { "os": "linux", "cpu": "x64" }, "sha512-6JW0z2FZUK5iOVhUIWqE4RblAhUj1EwhZ/MwteGb//SpFTOHydnhbp3868gxalwea+mbOLWO6xgxj9wA9wNvNw=="],
|
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg=="],
|
||||||
|
|
||||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.1.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-+DK/akkAvvXn5RdYN84IOmLkSy87SCmpofJPdB8vbLmf01BzntPBSYXnMvnEEv/Vcf3HYJwt24QZ/s6sWAwOMQ=="],
|
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.1.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw=="],
|
||||||
|
|
||||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.1.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Tr0j94MphimCCks+1rtYPzQFK+faJuhHWCegU9S9gDlgyOk8Y3kPmO64UcjyzZAlligeBtYZ/2bEyrKq0d2wqQ=="],
|
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.1.6", "", { "os": "win32", "cpu": "x64" }, "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A=="],
|
||||||
|
|
||||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||||
|
|
||||||
@@ -268,16 +268,18 @@
|
|||||||
|
|
||||||
"@tauri-apps/plugin-clipboard-manager": ["@tauri-apps/plugin-clipboard-manager@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-CUlb5Hqi2oZbcZf4VUyUH53XWPPdtpw43EUpCza5HWZJwxEoDowFzNUDt1tRUXA8Uq+XPn17Ysfptip33sG4eQ=="],
|
"@tauri-apps/plugin-clipboard-manager": ["@tauri-apps/plugin-clipboard-manager@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-CUlb5Hqi2oZbcZf4VUyUH53XWPPdtpw43EUpCza5HWZJwxEoDowFzNUDt1tRUXA8Uq+XPn17Ysfptip33sG4eQ=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.4.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-lNIn5CZuw8WZOn8zHzmFmDSzg5zfohWoa3mdULP0YFh/VogVdMVWZPcWSHlydsiJhRQYaTNSYKN7RmZKE2lCYQ=="],
|
"@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.6.0", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-fs": ["@tauri-apps/plugin-fs@2.4.4", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-MTorXxIRmOnOPT1jZ3w96vjSuScER38ryXY88vl5F0uiKdnvTKKTtaEjTEo8uPbl4e3gnUtfsDVwC7h77GQLvQ=="],
|
"@tauri-apps/plugin-fs": ["@tauri-apps/plugin-fs@2.4.5", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-dVxWWGE6VrOxC7/jlhyE+ON/Cc2REJlM35R3PJX3UvFw2XwYhLGQVAIyrehenDdKjotipjYEVc4YjOl3qq90fA=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-notification": ["@tauri-apps/plugin-notification@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg=="],
|
"@tauri-apps/plugin-notification": ["@tauri-apps/plugin-notification@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.5.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ei/yRRoCklWHImwpCcDK3VhNXx+QXM9793aQ64YxpqVF0BDuuIlXhZgiAkc15wnPVav+IbkYhmDJIv5R326Mew=="],
|
"@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.5.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-n+nXWeuSeF9wcEsSPmRnBEGrRgOy6jjkSU+UVCOV8YUGKb2erhDOxis7IqRXiRVHhY8XMKks00BJ0OAdkpf6+A=="],
|
"@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-n+nXWeuSeF9wcEsSPmRnBEGrRgOy6jjkSU+UVCOV8YUGKb2erhDOxis7IqRXiRVHhY8XMKks00BJ0OAdkpf6+A=="],
|
||||||
|
|
||||||
|
"@tauri-apps/plugin-window-state": ["@tauri-apps/plugin-window-state@2.4.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-OuvdrzyY8Q5Dbzpj+GcrnV1iCeoZbcFdzMjanZMMcAEUNy/6PH5pxZPXpaZLOR7whlzXiuzx0L9EKZbH7zpdRw=="],
|
||||||
|
|
||||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
|
|
||||||
"@types/crypto-js": ["@types/crypto-js@4.2.2", "", {}, "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ=="],
|
"@types/crypto-js": ["@types/crypto-js@4.2.2", "", {}, "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ=="],
|
||||||
@@ -288,31 +290,31 @@
|
|||||||
|
|
||||||
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
|
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
"@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.2.7", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg=="],
|
"@types/react": ["@types/react@19.2.10", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw=="],
|
||||||
|
|
||||||
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.50.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.50.0", "@typescript-eslint/type-utils": "8.50.0", "@typescript-eslint/utils": "8.50.0", "@typescript-eslint/visitor-keys": "8.50.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.50.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg=="],
|
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.54.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.54.0", "@typescript-eslint/type-utils": "8.54.0", "@typescript-eslint/utils": "8.54.0", "@typescript-eslint/visitor-keys": "8.54.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.54.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.50.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.50.0", "@typescript-eslint/types": "8.50.0", "@typescript-eslint/typescript-estree": "8.50.0", "@typescript-eslint/visitor-keys": "8.50.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q=="],
|
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.54.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.54.0", "@typescript-eslint/types": "8.54.0", "@typescript-eslint/typescript-estree": "8.54.0", "@typescript-eslint/visitor-keys": "8.54.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA=="],
|
||||||
|
|
||||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.50.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.50.0", "@typescript-eslint/types": "^8.50.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ=="],
|
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.54.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.54.0", "@typescript-eslint/types": "^8.54.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g=="],
|
||||||
|
|
||||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.50.0", "", { "dependencies": { "@typescript-eslint/types": "8.50.0", "@typescript-eslint/visitor-keys": "8.50.0" } }, "sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A=="],
|
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.54.0", "", { "dependencies": { "@typescript-eslint/types": "8.54.0", "@typescript-eslint/visitor-keys": "8.54.0" } }, "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg=="],
|
||||||
|
|
||||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.50.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w=="],
|
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.54.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw=="],
|
||||||
|
|
||||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.50.0", "", { "dependencies": { "@typescript-eslint/types": "8.50.0", "@typescript-eslint/typescript-estree": "8.50.0", "@typescript-eslint/utils": "8.50.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw=="],
|
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.54.0", "", { "dependencies": { "@typescript-eslint/types": "8.54.0", "@typescript-eslint/typescript-estree": "8.54.0", "@typescript-eslint/utils": "8.54.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA=="],
|
||||||
|
|
||||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.50.0", "", {}, "sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w=="],
|
"@typescript-eslint/types": ["@typescript-eslint/types@8.54.0", "", {}, "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.50.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.50.0", "@typescript-eslint/tsconfig-utils": "8.50.0", "@typescript-eslint/types": "8.50.0", "@typescript-eslint/visitor-keys": "8.50.0", "debug": "^4.3.4", "minimatch": "^9.0.4", "semver": "^7.6.0", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ=="],
|
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.54.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.54.0", "@typescript-eslint/tsconfig-utils": "8.54.0", "@typescript-eslint/types": "8.54.0", "@typescript-eslint/visitor-keys": "8.54.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA=="],
|
||||||
|
|
||||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.50.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.50.0", "@typescript-eslint/types": "8.50.0", "@typescript-eslint/typescript-estree": "8.50.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg=="],
|
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.54.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.54.0", "@typescript-eslint/types": "8.54.0", "@typescript-eslint/typescript-estree": "8.54.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA=="],
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.50.0", "", { "dependencies": { "@typescript-eslint/types": "8.50.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q=="],
|
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.54.0", "", { "dependencies": { "@typescript-eslint/types": "8.54.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA=="],
|
||||||
|
|
||||||
"@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="],
|
"@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="],
|
||||||
|
|
||||||
@@ -388,15 +390,15 @@
|
|||||||
|
|
||||||
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
||||||
|
|
||||||
"axe-core": ["axe-core@4.11.0", "", {}, "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ=="],
|
"axe-core": ["axe-core@4.11.1", "", {}, "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A=="],
|
||||||
|
|
||||||
"axios": ["axios@1.13.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA=="],
|
"axios": ["axios@1.13.4", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg=="],
|
||||||
|
|
||||||
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
||||||
|
|
||||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||||
|
|
||||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.11", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ=="],
|
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.18", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA=="],
|
||||||
|
|
||||||
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
||||||
|
|
||||||
@@ -412,7 +414,7 @@
|
|||||||
|
|
||||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||||
|
|
||||||
"caniuse-lite": ["caniuse-lite@1.0.30001761", "", {}, "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g=="],
|
"caniuse-lite": ["caniuse-lite@1.0.30001766", "", {}, "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA=="],
|
||||||
|
|
||||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||||
|
|
||||||
@@ -442,8 +444,6 @@
|
|||||||
|
|
||||||
"data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
|
"data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
|
||||||
|
|
||||||
"date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="],
|
|
||||||
|
|
||||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||||
@@ -460,7 +460,7 @@
|
|||||||
|
|
||||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||||
|
|
||||||
"electron-to-chromium": ["electron-to-chromium@1.5.267", "", {}, "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw=="],
|
"electron-to-chromium": ["electron-to-chromium@1.5.279", "", {}, "sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg=="],
|
||||||
|
|
||||||
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||||
|
|
||||||
@@ -488,7 +488,7 @@
|
|||||||
|
|
||||||
"eslint": ["eslint@9.39.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.2", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw=="],
|
"eslint": ["eslint@9.39.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.2", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw=="],
|
||||||
|
|
||||||
"eslint-config-next": ["eslint-config-next@16.1.0", "", { "dependencies": { "@next/eslint-plugin-next": "16.1.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^7.0.0", "globals": "16.4.0", "typescript-eslint": "^8.46.0" }, "peerDependencies": { "eslint": ">=9.0.0", "typescript": ">=3.3.1" }, "optionalPeers": ["typescript"] }, "sha512-RlPb8E2uO/Ix/w3kizxz6+6ogw99WqtNzTG0ArRZ5NEkIYcsfRb8U0j7aTG7NjRvcrsak5QtUSuxGNN2UcA58g=="],
|
"eslint-config-next": ["eslint-config-next@16.1.6", "", { "dependencies": { "@next/eslint-plugin-next": "16.1.6", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^7.0.0", "globals": "16.4.0", "typescript-eslint": "^8.46.0" }, "peerDependencies": { "eslint": ">=9.0.0", "typescript": ">=3.3.1" }, "optionalPeers": ["typescript"] }, "sha512-vKq40io2B0XtkkNDYyleATwblNt8xuh3FWp8SpSz3pt7P01OkBFlKsJZ2mWt5WsCySlDQLckb1zMY9yE9Qy0LA=="],
|
||||||
|
|
||||||
"eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="],
|
"eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="],
|
||||||
|
|
||||||
@@ -510,7 +510,7 @@
|
|||||||
|
|
||||||
"espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
|
"espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
|
||||||
|
|
||||||
"esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
|
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
|
||||||
|
|
||||||
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
||||||
|
|
||||||
@@ -526,7 +526,7 @@
|
|||||||
|
|
||||||
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
|
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
|
||||||
|
|
||||||
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
|
"fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
|
||||||
|
|
||||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||||
|
|
||||||
@@ -740,7 +740,7 @@
|
|||||||
|
|
||||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||||
|
|
||||||
"next": ["next@16.1.0", "", { "dependencies": { "@next/env": "16.1.0", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.1.0", "@next/swc-darwin-x64": "16.1.0", "@next/swc-linux-arm64-gnu": "16.1.0", "@next/swc-linux-arm64-musl": "16.1.0", "@next/swc-linux-x64-gnu": "16.1.0", "@next/swc-linux-x64-musl": "16.1.0", "@next/swc-win32-arm64-msvc": "16.1.0", "@next/swc-win32-x64-msvc": "16.1.0", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-Y+KbmDbefYtHDDQKLNrmzE/YYzG2msqo2VXhzh5yrJ54tx/6TmGdkR5+kP9ma7i7LwZpZMfoY3m/AoPPPKxtVw=="],
|
"next": ["next@16.1.6", "", { "dependencies": { "@next/env": "16.1.6", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.1.6", "@next/swc-darwin-x64": "16.1.6", "@next/swc-linux-arm64-gnu": "16.1.6", "@next/swc-linux-arm64-musl": "16.1.6", "@next/swc-linux-x64-gnu": "16.1.6", "@next/swc-linux-x64-musl": "16.1.6", "@next/swc-win32-arm64-msvc": "16.1.6", "@next/swc-win32-x64-msvc": "16.1.6", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw=="],
|
||||||
|
|
||||||
"node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
|
"node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
|
||||||
|
|
||||||
@@ -796,9 +796,9 @@
|
|||||||
|
|
||||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||||
|
|
||||||
"react": ["react@19.2.3", "", {}, "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA=="],
|
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
||||||
|
|
||||||
"react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="],
|
"react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
|
||||||
|
|
||||||
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
@@ -882,7 +882,7 @@
|
|||||||
|
|
||||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||||
|
|
||||||
"ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
|
"ts-api-utils": ["ts-api-utils@2.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="],
|
||||||
|
|
||||||
"tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
|
"tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
|
||||||
|
|
||||||
@@ -900,7 +900,7 @@
|
|||||||
|
|
||||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
"typescript-eslint": ["typescript-eslint@8.50.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.50.0", "@typescript-eslint/parser": "8.50.0", "@typescript-eslint/typescript-estree": "8.50.0", "@typescript-eslint/utils": "8.50.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A=="],
|
"typescript-eslint": ["typescript-eslint@8.54.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.54.0", "@typescript-eslint/parser": "8.54.0", "@typescript-eslint/typescript-estree": "8.54.0", "@typescript-eslint/utils": "8.54.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ=="],
|
||||||
|
|
||||||
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
|
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
|
||||||
|
|
||||||
@@ -920,7 +920,7 @@
|
|||||||
|
|
||||||
"which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
|
"which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
|
||||||
|
|
||||||
"which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="],
|
"which-typed-array": ["which-typed-array@1.1.20", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg=="],
|
||||||
|
|
||||||
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
||||||
|
|
||||||
@@ -928,7 +928,7 @@
|
|||||||
|
|
||||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||||
|
|
||||||
"zod": ["zod@4.2.1", "", {}, "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw=="],
|
"zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
|
||||||
|
|
||||||
"zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="],
|
"zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="],
|
||||||
|
|
||||||
@@ -936,13 +936,13 @@
|
|||||||
|
|
||||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.0", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
|
|
||||||
|
|||||||
+15
-15
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "lncvrt-games-launcher",
|
"name": "lncvrt-games-launcher",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.3.0",
|
"version": "1.5.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
@@ -17,30 +17,30 @@
|
|||||||
"@fortawesome/react-fontawesome": "3.1.1",
|
"@fortawesome/react-fontawesome": "3.1.1",
|
||||||
"@tauri-apps/api": "2.9.1",
|
"@tauri-apps/api": "2.9.1",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
||||||
"@tauri-apps/plugin-dialog": "2.4.2",
|
"@tauri-apps/plugin-dialog": "2.6.0",
|
||||||
"@tauri-apps/plugin-fs": "2.4.4",
|
"@tauri-apps/plugin-fs": "2.4.5",
|
||||||
"@tauri-apps/plugin-notification": "2.3.3",
|
"@tauri-apps/plugin-notification": "2.3.3",
|
||||||
"@tauri-apps/plugin-opener": "2.5.2",
|
"@tauri-apps/plugin-opener": "2.5.3",
|
||||||
"@tauri-apps/plugin-os": "2.3.2",
|
"@tauri-apps/plugin-os": "2.3.2",
|
||||||
"axios": "1.13.2",
|
"@tauri-apps/plugin-window-state": "2.4.1",
|
||||||
"date-fns": "4.1.0",
|
"axios": "1.13.4",
|
||||||
"next": "16.1.0",
|
"next": "16.1.6",
|
||||||
"pretty-bytes": "7.1.0",
|
"pretty-bytes": "7.1.0",
|
||||||
"react": "19.2.3",
|
"react": "19.2.4",
|
||||||
"react-dom": "19.2.3"
|
"react-dom": "19.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@eslint/eslintrc": "3.3.3",
|
||||||
"@tailwindcss/postcss": "4.1.18",
|
"@tailwindcss/postcss": "4.1.18",
|
||||||
"@tauri-apps/cli": "2.9.6",
|
"@tauri-apps/cli": "2.9.6",
|
||||||
"@types/crypto-js": "4.2.2",
|
"@types/crypto-js": "4.2.2",
|
||||||
"@types/react": "19.2.7",
|
"@types/node": "25.0.10",
|
||||||
|
"@types/react": "19.2.10",
|
||||||
"@types/react-dom": "19.2.3",
|
"@types/react-dom": "19.2.3",
|
||||||
"crypto-js": "4.2.0",
|
"crypto-js": "4.2.0",
|
||||||
"@types/node": "25.0.3",
|
|
||||||
"tailwindcss": "4.1.18",
|
|
||||||
"typescript": "5.9.3",
|
|
||||||
"eslint": "9.39.2",
|
"eslint": "9.39.2",
|
||||||
"eslint-config-next": "16.1.0",
|
"eslint-config-next": "16.1.6",
|
||||||
"@eslint/eslintrc": "3.3.3"
|
"tailwindcss": "4.1.18",
|
||||||
|
"typescript": "5.9.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+12
-11
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lncvrt-games-launcher"
|
name = "lncvrt-games-launcher"
|
||||||
version = "1.3.0"
|
version = "1.5.1"
|
||||||
authors = ["Lncvrt"]
|
authors = ["Lncvrt"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
@@ -13,20 +13,20 @@ tauri-build = { version = "2.5.3", features = [] }
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tauri = { version = "2.9.5", features = ["macos-private-api"] }
|
tauri = { version = "2.9.5", features = ["macos-private-api"] }
|
||||||
tauri-plugin-opener = "2.5.2"
|
tauri-plugin-opener = "2.5.3"
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
serde_json = "1.0.145"
|
serde_json = "1.0.149"
|
||||||
tauri-plugin-os = "2.3.2"
|
tauri-plugin-os = "2.3.2"
|
||||||
reqwest = { version = "0.12.26", default-features = false, features = ["stream", "rustls-tls"] }
|
reqwest = { version = "0.13.1", default-features = false, features = ["stream", "rustls"] }
|
||||||
tokio = "1.48.0"
|
tokio = "1.49.0"
|
||||||
futures-util = { version = "0.3.31", features = ["io"] }
|
futures-util = { version = "0.3.31", features = ["io"] }
|
||||||
tauri-plugin-decorum = "1.1.1"
|
tauri-plugin-decorum = "1.1.1"
|
||||||
tauri-plugin-fs = "2.4.4"
|
tauri-plugin-fs = "2.4.5"
|
||||||
zip = "7.0.0"
|
zip = "7.2.0"
|
||||||
libc = "0.2.178"
|
libc = "0.2.180"
|
||||||
tauri-plugin-dialog = "2.4.2"
|
tauri-plugin-dialog = "2.6.0"
|
||||||
tauri-plugin-notification = "2.3.3"
|
tauri-plugin-notification = "2.3.3"
|
||||||
sysinfo = "0.37.2"
|
sysinfo = "0.38.0"
|
||||||
sha2 = "0.10.9"
|
sha2 = "0.10.9"
|
||||||
tauri-plugin-clipboard-manager = "2.3.2"
|
tauri-plugin-clipboard-manager = "2.3.2"
|
||||||
|
|
||||||
@@ -34,6 +34,7 @@ tauri-plugin-clipboard-manager = "2.3.2"
|
|||||||
shlex = "1.3.0"
|
shlex = "1.3.0"
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
tauri-plugin-single-instance = "2.3.6"
|
tauri-plugin-single-instance = "2.3.7"
|
||||||
|
tauri-plugin-window-state = "2.4.1"
|
||||||
|
|
||||||
|
|
||||||
@@ -21,11 +21,17 @@
|
|||||||
"core:window:allow-toggle-maximize",
|
"core:window:allow-toggle-maximize",
|
||||||
"decorum:allow-show-snap-overlay",
|
"decorum:allow-show-snap-overlay",
|
||||||
"fs:default",
|
"fs:default",
|
||||||
"fs:allow-applocaldata-read",
|
|
||||||
"fs:allow-applocaldata-write",
|
|
||||||
"dialog:default",
|
"dialog:default",
|
||||||
"notification:default",
|
"notification:default",
|
||||||
"clipboard-manager:default",
|
"clipboard-manager:default",
|
||||||
"clipboard-manager:allow-write-text"
|
"clipboard-manager:allow-write-text",
|
||||||
|
"fs:allow-applocaldata-read",
|
||||||
|
"fs:allow-applocaldata-write",
|
||||||
|
{
|
||||||
|
"identifier": "fs:scope",
|
||||||
|
"allow": [
|
||||||
|
{ "path": "$APPLOCALDATA/game/**" }
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"identifier": "desktop-capability",
|
||||||
|
"platforms": [
|
||||||
|
"macOS",
|
||||||
|
"windows",
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
"window-state:default"
|
||||||
|
]
|
||||||
|
}
|
||||||
+97
-76
@@ -15,22 +15,25 @@ use tauri::{AppHandle, Emitter, Manager};
|
|||||||
use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
|
use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
|
||||||
use tauri_plugin_opener::OpenerExt;
|
use tauri_plugin_opener::OpenerExt;
|
||||||
use tauri_plugin_os::platform;
|
use tauri_plugin_os::platform;
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
use tokio::{io::AsyncWriteExt, time::timeout};
|
use tokio::{io::AsyncWriteExt, time::timeout};
|
||||||
use zip::ZipArchive;
|
use zip::ZipArchive;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
use std::os::unix::fs::PermissionsExt;
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use tauri_plugin_decorum::WebviewWindowExt;
|
use tauri_plugin_decorum::WebviewWindowExt;
|
||||||
|
|
||||||
fn is_running_by_path(path: &PathBuf) -> bool {
|
#[allow(unused)]
|
||||||
|
fn is_running_by_path(path: &Path) -> bool {
|
||||||
let sys = System::new_all();
|
let sys = System::new_all();
|
||||||
|
let target = path.canonicalize().ok();
|
||||||
|
if target.is_none() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let target = target.unwrap();
|
||||||
sys.processes().values().any(|proc| {
|
sys.processes().values().any(|proc| {
|
||||||
if let Some(exe) = proc.exe() {
|
proc.exe()
|
||||||
exe == path
|
.and_then(|exe| exe.canonicalize().ok())
|
||||||
} else {
|
.map_or(false, |exe| exe == target)
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,9 +185,26 @@ async fn download(
|
|||||||
|
|
||||||
app.emit("download-hash-checking", format!("{}", &name))
|
app.emit("download-hash-checking", format!("{}", &name))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut hasher = Sha512::new();
|
|
||||||
hasher.update(&tokio::fs::read(download_part_path.clone()).await.unwrap());
|
let download_hash = {
|
||||||
let download_hash = format!("{:x}", hasher.finalize());
|
let mut file = tokio::fs::File::open(download_part_path.clone())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let mut hasher = Sha512::new();
|
||||||
|
{
|
||||||
|
let mut buffer = [0; 8192];
|
||||||
|
loop {
|
||||||
|
let bytes_read = file.read(&mut buffer).await.unwrap();
|
||||||
|
if bytes_read == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hasher.update(&buffer[..bytes_read]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drop(file);
|
||||||
|
format!("{:x}", hasher.finalize())
|
||||||
|
};
|
||||||
|
|
||||||
if hash != download_hash {
|
if hash != download_hash {
|
||||||
tokio::fs::remove_file(download_part_path.clone())
|
tokio::fs::remove_file(download_part_path.clone())
|
||||||
.await
|
.await
|
||||||
@@ -205,102 +225,103 @@ async fn download(
|
|||||||
return "-1".to_string();
|
return "-1".to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
{
|
{
|
||||||
let executable_path = game_path.join(&name).join(&executable);
|
use std::{fs, os::unix::fs::PermissionsExt};
|
||||||
|
|
||||||
|
let executable_path = if cfg!(target_os = "linux") {
|
||||||
|
game_path.join(&name).join(&executable)
|
||||||
|
} else {
|
||||||
|
game_path
|
||||||
|
.join(&name)
|
||||||
|
.join(&executable)
|
||||||
|
.join("Contents")
|
||||||
|
.join("MacOS")
|
||||||
|
.join(
|
||||||
|
&executable
|
||||||
|
.chars()
|
||||||
|
.take(executable.chars().count() - 4)
|
||||||
|
.collect::<String>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let mut perms = fs::metadata(&executable_path).unwrap().permissions();
|
let mut perms = fs::metadata(&executable_path).unwrap().permissions();
|
||||||
perms.set_mode(0o755);
|
perms.set_mode(0o755);
|
||||||
fs::set_permissions(executable_path, perms).unwrap();
|
fs::set_permissions(&executable_path, perms).unwrap();
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
{
|
|
||||||
use std::fs;
|
|
||||||
use std::os::unix::fs::PermissionsExt;
|
|
||||||
|
|
||||||
let macos_app_path = game_path
|
|
||||||
.join(&name)
|
|
||||||
.join(&executable)
|
|
||||||
.join("Contents")
|
|
||||||
.join("MacOS")
|
|
||||||
.join(
|
|
||||||
&executable
|
|
||||||
.chars()
|
|
||||||
.take(executable.chars().count() - 4)
|
|
||||||
.collect::<String>(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut perms = fs::metadata(&macos_app_path).unwrap().permissions();
|
|
||||||
perms.set_mode(0o755);
|
|
||||||
fs::set_permissions(&macos_app_path, perms).unwrap();
|
|
||||||
}
|
|
||||||
return "1".to_string();
|
return "1".to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn launch_game(app: AppHandle, name: String, executable: String) {
|
fn launch_game(
|
||||||
|
app: AppHandle,
|
||||||
|
name: String,
|
||||||
|
executable: String,
|
||||||
|
display_name: String,
|
||||||
|
use_wine: bool,
|
||||||
|
wine_command: String,
|
||||||
|
) {
|
||||||
let game_folder = app
|
let game_folder = app
|
||||||
.path()
|
.path()
|
||||||
.app_local_data_dir()
|
.app_local_data_dir()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.join("game")
|
.join("game")
|
||||||
.join(&name);
|
.join(&name);
|
||||||
let game_path = game_folder.join(&executable);
|
if !game_folder.exists() {
|
||||||
if !game_path.exists() {
|
|
||||||
app.dialog()
|
|
||||||
.message(
|
|
||||||
format!(
|
|
||||||
"Executable \"{}\" not found.\n\nTry reinstalling the game or make a support request in the Community link on the sidebar.",
|
|
||||||
game_path.display().to_string()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.kind(MessageDialogKind::Error)
|
|
||||||
.title("Game not found")
|
|
||||||
.show(|_| {});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if is_running_by_path(&game_path) {
|
|
||||||
app.dialog()
|
let exe_path = game_folder.join(&executable);
|
||||||
.message(format!("The version {} is already running.", name))
|
|
||||||
.kind(MessageDialogKind::Error)
|
//if already running on macos, it'll auto take the user to that proccess
|
||||||
.title("Game already running")
|
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||||
.show(|_| {});
|
{
|
||||||
return;
|
if !use_wine && is_running_by_path(&exe_path) {
|
||||||
|
app.dialog()
|
||||||
|
.message(format!(
|
||||||
|
"{} is already running, if this doesn't seem true, try to kill the proccess.",
|
||||||
|
display_name
|
||||||
|
))
|
||||||
|
.kind(MessageDialogKind::Error)
|
||||||
|
.title("Game already running")
|
||||||
|
.show(|_| {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
if use_wine {
|
||||||
|
let quoted_path = format!("\"{}\"", exe_path.to_string_lossy());
|
||||||
|
let cmd = wine_command.replace("%path%", "ed_path);
|
||||||
|
|
||||||
|
Command::new("bash")
|
||||||
|
.arg("-c")
|
||||||
|
.arg(cmd)
|
||||||
|
.current_dir(&game_folder)
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if platform() == "macos" {
|
if platform() == "macos" {
|
||||||
Command::new("open")
|
Command::new("open")
|
||||||
.arg(&game_path)
|
.arg(&executable)
|
||||||
.current_dir(&game_folder)
|
.current_dir(&game_folder)
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
Command::new(&game_path)
|
Command::new(&exe_path)
|
||||||
.current_dir(&game_folder)
|
.current_dir(&game_folder)
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
async fn uninstall_version(app: AppHandle, name: String) {
|
|
||||||
let game_path = app
|
|
||||||
.path()
|
|
||||||
.app_local_data_dir()
|
|
||||||
.unwrap()
|
|
||||||
.join("game")
|
|
||||||
.join(&name);
|
|
||||||
if game_path.exists() {
|
|
||||||
if let Err(_) = tokio::fs::remove_dir_all(&game_path).await {
|
|
||||||
app.emit("version-failed", &name).unwrap();
|
|
||||||
} else {
|
|
||||||
app.emit("version-uninstalled", &name).unwrap();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
app.emit("version-uninstalled", &name).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn open_folder(app: AppHandle, name: String) {
|
async fn open_folder(app: AppHandle, name: String) {
|
||||||
let game_path = app
|
let game_path = app
|
||||||
@@ -329,6 +350,7 @@ async fn open_folder(app: AppHandle, name: String) {
|
|||||||
pub fn run() {
|
pub fn run() {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
|
.plugin(tauri_plugin_window_state::Builder::new().build())
|
||||||
.plugin(tauri_plugin_clipboard_manager::init())
|
.plugin(tauri_plugin_clipboard_manager::init())
|
||||||
.plugin(tauri_plugin_notification::init())
|
.plugin(tauri_plugin_notification::init())
|
||||||
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
||||||
@@ -345,7 +367,6 @@ pub fn run() {
|
|||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
download,
|
download,
|
||||||
launch_game,
|
launch_game,
|
||||||
uninstall_version,
|
|
||||||
open_folder,
|
open_folder,
|
||||||
folder_size
|
folder_size
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.3.0",
|
"version": "1.5.1",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev",
|
"beforeDevCommand": "next dev",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.3.0",
|
"version": "1.5.1",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev",
|
"beforeDevCommand": "next dev",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.3.0",
|
"version": "1.5.1",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev",
|
"beforeDevCommand": "next dev",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.3.0",
|
"version": "1.5.1",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev",
|
"beforeDevCommand": "next dev",
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ type GlobalCtxType = {
|
|||||||
setManagingVersion: (v: string | null) => void
|
setManagingVersion: (v: string | null) => void
|
||||||
setSelectedGame: (v: number | null) => void
|
setSelectedGame: (v: number | null) => void
|
||||||
getVersionInfo: (id: string | undefined) => GameVersion | undefined
|
getVersionInfo: (id: string | undefined) => GameVersion | undefined
|
||||||
getVersionGame: (id: number | undefined) => Game | undefined
|
getGameInfo: (id: number | undefined) => Game | undefined
|
||||||
getListOfGames: () => Game[]
|
getListOfGames: () => Game[]
|
||||||
getVersionsAmountData: (gameId: number) => {
|
getVersionsAmountData: (gameId: number) => {
|
||||||
installed: number
|
installed: number
|
||||||
|
|||||||
+25
-9
@@ -64,20 +64,36 @@ body {
|
|||||||
--col8: rgb(140, 128, 152);
|
--col8: rgb(140, 128, 152);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mint-theme {
|
||||||
|
--col0: rgb(8, 32, 16);
|
||||||
|
--col1: rgb(16, 48, 32);
|
||||||
|
--col2: rgb(32, 56, 40);
|
||||||
|
--col3: rgb(48, 72, 48);
|
||||||
|
--col4: rgb(64, 88, 66);
|
||||||
|
--col5: rgb(80, 104, 65);
|
||||||
|
--col6: rgb(96, 120, 80);
|
||||||
|
--col7: rgb(112, 136, 85);
|
||||||
|
--col8: rgb(128, 152, 95);
|
||||||
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
@apply rounded-md cursor-pointer text-[16px] py-1.5 px-3 transition-colors border;
|
@apply rounded-md cursor-pointer text-[16px] py-1 px-2 transition-colors border;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btntheme1 {
|
.btntheme1 {
|
||||||
@apply bg-(--col2) border-(--col4) hover:bg-(--col4) hover:border-(--col6);
|
@apply bg-(--col2) border-(--col4) hover:bg-(--col4) hover:border-(--col6) disabled:text-gray-300 disabled:bg-(--col1) disabled:border-(--col5) disabled:hover:text-gray-100 disabled:hover:bg-(--col2) disabled:hover:border-(--col6);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btntheme2 {
|
.btntheme2,
|
||||||
@apply bg-(--col3) border-(--col5) hover:bg-(--col5) hover:border-(--col7);
|
.downloads-entry .entry-info-item,
|
||||||
|
.downloads-entry .button {
|
||||||
|
@apply bg-(--col3) border-(--col5) hover:bg-(--col5) hover:border-(--col7) disabled:text-gray-300 disabled:bg-(--col2) disabled:border-(--col6) disabled:hover:text-gray-100 disabled:hover:bg-(--col3) disabled:hover:border-(--col7);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btntheme3 {
|
.btntheme3,
|
||||||
@apply bg-(--col4) border-(--col6) hover:bg-(--col6) hover:border-(--col8);
|
.downloads-entry:hover .entry-info-item,
|
||||||
|
.downloads-entry:hover .button {
|
||||||
|
@apply bg-(--col4) border-(--col6) hover:bg-(--col6) hover:border-(--col8) disabled:text-gray-300 disabled:bg-(--col2) disabled:border-(--col7) disabled:hover:text-gray-100 disabled:hover:bg-(--col4) disabled:hover:border-(--col8);
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
@@ -135,7 +151,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.close-button {
|
.close-button {
|
||||||
@apply flex justify-center items-center absolute bg-(--col3) hover:bg-(--col4) text-2xl cursor-pointer text-gray-300 hover:text-white h-12 w-12 p-3 rounded-xl left-2 top-2 transition-colors border border-(--col4) hover:border-(--col5);
|
@apply flex justify-center items-center absolute text-2xl text-gray-200 hover:text-white cursor-pointer h-12 w-12 p-3 rounded-lg left-2 top-2 transition-colors border;
|
||||||
}
|
}
|
||||||
|
|
||||||
*:focus {
|
*:focus {
|
||||||
@@ -143,9 +159,9 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.input-field {
|
.input-field {
|
||||||
@apply border-2 border-(--col4) rounded-md bg-(--col2) p-2 px-4 focus:border-blue-600 transition-colors;
|
@apply border-2 border-(--col4) rounded-md bg-(--col2) py-1 px-2 focus:bg-(--col3) focus:border-(--col6) transition-colors w-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-info-item {
|
.entry-info-item {
|
||||||
@apply flex flex-row items-center gap-1 border text-gray-300 py-1 px-2 rounded-lg w-fit text-[16px] transition-colors cursor-pointer;
|
@apply flex flex-row items-center gap-1 border text-gray-300 py-1 px-2 rounded-md w-fit text-[16px] transition-colors cursor-pointer;
|
||||||
}
|
}
|
||||||
@@ -9,5 +9,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.downloads-entry {
|
.downloads-entry {
|
||||||
@apply flex justify-between items-center m-2 p-4 rounded-lg text-gray-200 text-lg transition-colors bg-(--col2) hover:bg-(--col3) border border-(--col4) hover:border-(--col5);
|
@apply flex justify-between items-center m-2 p-2 rounded-lg text-gray-200 text-lg transition-colors bg-(--col2) hover:bg-(--col3) border border-(--col4) hover:border-(--col5);
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,15 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|||||||
import { faCheck } from '@fortawesome/free-solid-svg-icons'
|
import { faCheck } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { SettingProps } from '../types/SettingProps'
|
import { SettingProps } from '../types/SettingProps'
|
||||||
|
|
||||||
export function Setting ({ label, value, onChange, className }: SettingProps) {
|
export function Setting ({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
className,
|
||||||
|
title
|
||||||
|
}: SettingProps) {
|
||||||
return (
|
return (
|
||||||
<div className={`flex items-center gap-2 mb-2 ${className}`}>
|
<div className={`flex items-center gap-2 mb-2 ${className}`} title={title}>
|
||||||
<label className='text-white text-lg'>{label}</label>
|
<label className='text-white text-lg'>{label}</label>
|
||||||
<div className='setting-checkbox-wrapper'>
|
<div className='setting-checkbox-wrapper'>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
@apply flex items-center pl-1 h-14 w-60;
|
@apply flex items-center pl-2 h-10 w-60 pt-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-links {
|
.nav-links {
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ import Image from 'next/image'
|
|||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { usePathname, useSearchParams } from 'next/navigation'
|
import { usePathname, useSearchParams } from 'next/navigation'
|
||||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||||
|
import { Lexend } from 'next/font/google'
|
||||||
|
|
||||||
|
const lexend = Lexend({
|
||||||
|
subsets: ['latin']
|
||||||
|
})
|
||||||
|
|
||||||
export default function Sidebar () {
|
export default function Sidebar () {
|
||||||
const {
|
const {
|
||||||
@@ -63,64 +68,62 @@ export default function Sidebar () {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Image draggable={false} src={Icon} width={48} height={48} alt='' />
|
<Image draggable={false} src={Icon} width={36} height={36} alt='' />
|
||||||
<p className='ml-1 text-[17px] whitespace-nowrap'>
|
<p className={`ml-1 text-[16px] whitespace-nowrap ${lexend.className}`}>
|
||||||
Lncvrt Games Launcher
|
Lncvrt Games Launcher
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='overflow-auto'>
|
<nav className='nav-links overflow-auto pt-2'>
|
||||||
<nav className='nav-links'>
|
<Link
|
||||||
<Link
|
draggable={false}
|
||||||
draggable={false}
|
href='/'
|
||||||
href='/'
|
className={`link relative flex items-center ${
|
||||||
className={`link relative flex items-center ${
|
pathname === '/' || pathname === '/game' ? 'active' : ''
|
||||||
pathname === '/' || pathname === '/game' ? 'active' : ''
|
}`}
|
||||||
}`}
|
>
|
||||||
>
|
<FontAwesomeIcon icon={faHexagonNodes} className='mr-2' /> Games
|
||||||
<FontAwesomeIcon icon={faHexagonNodes} className='mr-2' /> Games
|
</Link>
|
||||||
</Link>
|
{getListOfGames()
|
||||||
{getListOfGames()
|
.sort((a, b) => {
|
||||||
.sort((a, b) => {
|
return a.id - b.id
|
||||||
return a.id - b.id
|
})
|
||||||
})
|
.map(i => (
|
||||||
.map(i => (
|
<Link
|
||||||
<Link
|
key={i.id}
|
||||||
key={i.id}
|
draggable={false}
|
||||||
draggable={false}
|
href={'/game?id=' + i.id}
|
||||||
href={'/game?id=' + i.id}
|
className={`link ${
|
||||||
className={`link ${
|
pathname === '/game' && Number(params.get('id') || 0) == i.id
|
||||||
pathname === '/game' && Number(params.get('id') || 0) == i.id
|
? 'active'
|
||||||
? 'active'
|
: ''
|
||||||
: ''
|
} ml-auto w-50 ${
|
||||||
} ml-auto w-50 ${
|
normalConfig?.settings.alwaysShowGamesInSidebar ||
|
||||||
normalConfig?.settings.alwaysShowGamesInSidebar ||
|
pathname === '/' ||
|
||||||
pathname === '/' ||
|
pathname === '/game'
|
||||||
pathname === '/game'
|
? ''
|
||||||
? ''
|
: 'hidden'
|
||||||
: 'hidden'
|
}`}
|
||||||
}`}
|
>
|
||||||
>
|
<div className='flex items-center'>
|
||||||
<div className='flex items-center'>
|
<FontAwesomeIcon icon={faGamepad} className='mr-1' />
|
||||||
<FontAwesomeIcon icon={faGamepad} className='mr-1' />
|
<span className='truncate max-w-full'>{i.name}</span>
|
||||||
<span className='truncate max-w-full'>{i.name}</span>
|
</div>
|
||||||
</div>
|
</Link>
|
||||||
</Link>
|
))}
|
||||||
))}
|
<Link
|
||||||
<Link
|
draggable={false}
|
||||||
draggable={false}
|
href='/settings'
|
||||||
href='/settings'
|
className={`link ${pathname === '/settings' ? 'active' : ''}`}
|
||||||
className={`link ${pathname === '/settings' ? 'active' : ''}`}
|
>
|
||||||
>
|
<FontAwesomeIcon icon={faCog} className='mr-1' /> Settings
|
||||||
<FontAwesomeIcon icon={faCog} className='mr-1' /> Settings
|
</Link>
|
||||||
</Link>
|
<button
|
||||||
<button
|
onClick={() => openUrl('https://games.lncvrt.xyz/discord')}
|
||||||
onClick={() => openUrl('https://games.lncvrt.xyz/discord')}
|
className='link mr-auto'
|
||||||
className='link mr-auto'
|
>
|
||||||
>
|
<FontAwesomeIcon icon={faDiscord} className='mr-1' /> Community
|
||||||
<FontAwesomeIcon icon={faDiscord} className='mr-1' /> Community
|
</button>
|
||||||
</button>
|
</nav>
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
className='sidebar-downloads'
|
className='sidebar-downloads'
|
||||||
hidden={downloadProgress.length == 0}
|
hidden={downloadProgress.length == 0}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useGlobal } from '../GlobalProvider'
|
||||||
|
|
||||||
|
export default function VersionChangelog () {
|
||||||
|
const {
|
||||||
|
getGameInfo,
|
||||||
|
getVersionInfo,
|
||||||
|
managingVersion,
|
||||||
|
downloadedVersionsConfig
|
||||||
|
} = useGlobal()
|
||||||
|
if (!managingVersion || !downloadedVersionsConfig) return <></>
|
||||||
|
|
||||||
|
const versionInfo = getVersionInfo(managingVersion)
|
||||||
|
const gameInfo = getGameInfo(versionInfo?.game)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p className='text-xl text-center'>
|
||||||
|
Viewing changelog for {versionInfo?.displayName}
|
||||||
|
</p>
|
||||||
|
<div className='popup-content text-center p-2'>
|
||||||
|
<span
|
||||||
|
className='whitespace-pre-wrap'
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: versionInfo?.changelog ? atob(versionInfo.changelog) : ''
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
faArrowUpRightFromSquare,
|
||||||
faCheck,
|
faCheck,
|
||||||
faCode,
|
faCode,
|
||||||
faHardDrive,
|
faHardDrive,
|
||||||
@@ -8,7 +9,6 @@ import {
|
|||||||
faWarning
|
faWarning
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import { format } from 'date-fns'
|
|
||||||
import { useGlobal } from '../GlobalProvider'
|
import { useGlobal } from '../GlobalProvider'
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
@@ -16,16 +16,17 @@ import prettyBytes from 'pretty-bytes'
|
|||||||
|
|
||||||
export default function VersionInfo () {
|
export default function VersionInfo () {
|
||||||
const {
|
const {
|
||||||
getVersionGame,
|
getGameInfo,
|
||||||
getVersionInfo,
|
getVersionInfo,
|
||||||
managingVersion,
|
managingVersion,
|
||||||
downloadedVersionsConfig,
|
downloadedVersionsConfig,
|
||||||
viewingInfoFromDownloads
|
viewingInfoFromDownloads,
|
||||||
|
setPopupMode
|
||||||
} = useGlobal()
|
} = useGlobal()
|
||||||
if (!managingVersion || !downloadedVersionsConfig) return <></>
|
if (!managingVersion || !downloadedVersionsConfig) return <></>
|
||||||
|
|
||||||
const versionInfo = getVersionInfo(managingVersion)
|
const versionInfo = getVersionInfo(managingVersion)
|
||||||
const gameInfo = getVersionGame(versionInfo?.game)
|
const gameInfo = getGameInfo(versionInfo?.game)
|
||||||
const [versionSize, setVersionSize] = useState<number | null>(null)
|
const [versionSize, setVersionSize] = useState<number | null>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -39,9 +40,7 @@ export default function VersionInfo () {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p className='text-xl text-center'>
|
<p className='text-xl text-center'>
|
||||||
Viewing info for{' '}
|
Viewing info for {versionInfo?.displayName}
|
||||||
{getVersionGame(getVersionInfo(managingVersion)?.game)?.name} v
|
|
||||||
{getVersionInfo(managingVersion)?.versionName}
|
|
||||||
</p>
|
</p>
|
||||||
<div className='popup-content flex flex-col items-center justify-center gap-2 h-full'>
|
<div className='popup-content flex flex-col items-center justify-center gap-2 h-full'>
|
||||||
<div
|
<div
|
||||||
@@ -50,11 +49,8 @@ export default function VersionInfo () {
|
|||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Installed{' '}
|
Installed{' '}
|
||||||
{format(
|
{new Intl.DateTimeFormat(undefined).format(
|
||||||
new Date(
|
downloadedVersionsConfig.list[managingVersion] ?? 0
|
||||||
downloadedVersionsConfig.timestamps[managingVersion] ?? 0
|
|
||||||
),
|
|
||||||
'MM/dd/yyyy'
|
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -64,11 +60,8 @@ export default function VersionInfo () {
|
|||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Released{' '}
|
Released{' '}
|
||||||
{format(
|
{new Intl.DateTimeFormat(undefined).format(
|
||||||
new Date(
|
versionInfo?.releaseDate ? versionInfo.releaseDate * 1000 : 0
|
||||||
versionInfo?.releaseDate ? versionInfo.releaseDate * 1000 : 0
|
|
||||||
),
|
|
||||||
'MM/dd/yyyy'
|
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,7 +76,10 @@ export default function VersionInfo () {
|
|||||||
/>
|
/>
|
||||||
<p>{gameInfo?.verified ? 'Verified' : 'Unverified'}</p>
|
<p>{gameInfo?.verified ? 'Verified' : 'Unverified'}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='entry-info-item btntheme2' hidden={gameInfo?.official}>
|
<div
|
||||||
|
className='entry-info-item btntheme2'
|
||||||
|
hidden={gameInfo?.developer == null}
|
||||||
|
>
|
||||||
<FontAwesomeIcon icon={faCode} color='lightgray' />
|
<FontAwesomeIcon icon={faCode} color='lightgray' />
|
||||||
<p>Developer: {gameInfo?.developer}</p>
|
<p>Developer: {gameInfo?.developer}</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -114,6 +110,14 @@ export default function VersionInfo () {
|
|||||||
: 'Loading...'}
|
: 'Loading...'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
className='entry-info-item btntheme2'
|
||||||
|
onClick={() => setPopupMode(4)}
|
||||||
|
hidden={!versionInfo?.changelog}
|
||||||
|
>
|
||||||
|
<p>View Changelog</p>
|
||||||
|
<FontAwesomeIcon icon={faArrowUpRightFromSquare} color='lightgray' />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
+217
-90
@@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import '../Installs.css'
|
import '../Installs.css'
|
||||||
import { format } from 'date-fns'
|
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { useGlobal } from '../GlobalProvider'
|
import { useGlobal } from '../GlobalProvider'
|
||||||
import { useSearchParams } from 'next/navigation'
|
import { useSearchParams } from 'next/navigation'
|
||||||
import { platform } from '@tauri-apps/plugin-os'
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
|
import { faWarning } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
|
||||||
export default function Installs () {
|
export default function Installs () {
|
||||||
const {
|
const {
|
||||||
downloadProgress,
|
|
||||||
showPopup,
|
showPopup,
|
||||||
setShowPopup,
|
setShowPopup,
|
||||||
setPopupMode,
|
setPopupMode,
|
||||||
@@ -20,12 +20,18 @@ export default function Installs () {
|
|||||||
normalConfig,
|
normalConfig,
|
||||||
setManagingVersion,
|
setManagingVersion,
|
||||||
getVersionInfo,
|
getVersionInfo,
|
||||||
getVersionGame,
|
getGameInfo,
|
||||||
setSelectedGame
|
setSelectedGame,
|
||||||
|
serverVersionList
|
||||||
} = useGlobal()
|
} = useGlobal()
|
||||||
|
|
||||||
const params = useSearchParams()
|
const params = useSearchParams()
|
||||||
const [hoveredIds, setHoveredIds] = useState<string[]>([])
|
const [category, setCategory] = useState<number>(-1)
|
||||||
|
|
||||||
|
const id = Number(params.get('id') || 0)
|
||||||
|
if (!id) return <p>Invalid game</p>
|
||||||
|
const game = serverVersionList?.games.find(g => g.id === id)
|
||||||
|
if (!game) return <p>Invalid game</p>
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!showPopup) return
|
if (!showPopup) return
|
||||||
@@ -36,18 +42,30 @@ export default function Installs () {
|
|||||||
<div className='mx-4 mt-4'>
|
<div className='mx-4 mt-4'>
|
||||||
<div className='flex justify-between items-center mb-4'>
|
<div className='flex justify-between items-center mb-4'>
|
||||||
<p className='text-3xl'>Installs</p>
|
<p className='text-3xl'>Installs</p>
|
||||||
<button
|
<div className='flex gap-2'>
|
||||||
className='button btntheme1 text-3xl'
|
<button
|
||||||
onClick={() => {
|
className='button btntheme1'
|
||||||
setSelectedGame(Number(params.get('id') || 0))
|
onClick={() => {
|
||||||
setPopupMode(0)
|
setCategory(-1)
|
||||||
setShowPopup(true)
|
}}
|
||||||
setFadeOut(false)
|
title='Click to go up a level.'
|
||||||
}}
|
hidden={category == -1}
|
||||||
disabled={downloadProgress.length != 0}
|
>
|
||||||
>
|
Back
|
||||||
Download versions
|
</button>
|
||||||
</button>
|
<button
|
||||||
|
className='button btntheme1'
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedGame(id)
|
||||||
|
setPopupMode(0)
|
||||||
|
setShowPopup(true)
|
||||||
|
setFadeOut(false)
|
||||||
|
}}
|
||||||
|
title='Click to download more versions of this game.'
|
||||||
|
>
|
||||||
|
Download versions
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='downloads-container'>
|
<div className='downloads-container'>
|
||||||
<div
|
<div
|
||||||
@@ -57,13 +75,75 @@ export default function Installs () {
|
|||||||
: 'h-[calc(100vh-84px)]'
|
: 'h-[calc(100vh-84px)]'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{downloadedVersionsConfig &&
|
{category == -1 &&
|
||||||
downloadedVersionsConfig.list.filter(v => {
|
Object.entries(game.categoryNames).map(([key, value]) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={crypto.randomUUID()}
|
||||||
|
className={`downloads-entry ${
|
||||||
|
normalConfig?.settings.useLegacyInteractButtons
|
||||||
|
? ''
|
||||||
|
: 'cursor-pointer'
|
||||||
|
}`}
|
||||||
|
title={
|
||||||
|
normalConfig?.settings.useLegacyInteractButtons
|
||||||
|
? ''
|
||||||
|
: 'Click to view category'
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
if (normalConfig?.settings.useLegacyInteractButtons) return
|
||||||
|
setCategory(Number(key))
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='h-18 w-screen relative'>
|
||||||
|
<p className='text-2xl'>{value}</p>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className='entry-info-item flex absolute left-0 bottom-0'
|
||||||
|
title='The amount of versions installed of this game in installed/installable format.'
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
{(() => {
|
||||||
|
const count =
|
||||||
|
Object.keys(
|
||||||
|
downloadedVersionsConfig?.list ?? []
|
||||||
|
).filter(v => {
|
||||||
|
const info = getVersionInfo(v)
|
||||||
|
if (!info) return false
|
||||||
|
if (
|
||||||
|
platform() === 'linux' &&
|
||||||
|
info.wine &&
|
||||||
|
!normalConfig?.settings.useWineOnUnixWhenNeeded
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
return (
|
||||||
|
info.game === id && info.category == Number(key)
|
||||||
|
)
|
||||||
|
}).length ?? 0
|
||||||
|
return `${count} install${count === 1 ? '' : 's'}`
|
||||||
|
})()}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className='button absolute right-0 bottom-0'
|
||||||
|
hidden={!normalConfig?.settings.useLegacyInteractButtons}
|
||||||
|
title='Click to view category'
|
||||||
|
onClick={() => setCategory(Number(key))}
|
||||||
|
>
|
||||||
|
Installs
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
{Object.keys(downloadedVersionsConfig?.list ?? []).filter(v => {
|
||||||
const info = getVersionInfo(v)
|
const info = getVersionInfo(v)
|
||||||
if (!info) return false
|
if (!info) return false
|
||||||
return info.game === Number(params.get('id') || 0)
|
return info.game === id
|
||||||
}).length != 0 ? (
|
}).length != 0 ? (
|
||||||
downloadedVersionsConfig.list
|
Object.keys(downloadedVersionsConfig?.list ?? [])
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
const infoA = getVersionInfo(a)
|
const infoA = getVersionInfo(a)
|
||||||
const infoB = getVersionInfo(b)
|
const infoB = getVersionInfo(b)
|
||||||
@@ -73,7 +153,18 @@ export default function Installs () {
|
|||||||
.filter(v => {
|
.filter(v => {
|
||||||
const info = getVersionInfo(v)
|
const info = getVersionInfo(v)
|
||||||
if (!info) return false
|
if (!info) return false
|
||||||
return info.game === Number(params.get('id') || 0)
|
if (
|
||||||
|
platform() === 'linux' &&
|
||||||
|
info.wine &&
|
||||||
|
!normalConfig?.settings.useWineOnUnixWhenNeeded
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
return (
|
||||||
|
info.game === id &&
|
||||||
|
(category == -1
|
||||||
|
? info.category == -1
|
||||||
|
: info.category == category)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.map((entry, i) => (
|
.map((entry, i) => (
|
||||||
<div
|
<div
|
||||||
@@ -83,86 +174,122 @@ export default function Installs () {
|
|||||||
? ''
|
? ''
|
||||||
: 'cursor-pointer'
|
: 'cursor-pointer'
|
||||||
}`}
|
}`}
|
||||||
title='Click to launch game'
|
title={
|
||||||
|
normalConfig?.settings.useLegacyInteractButtons
|
||||||
|
? ''
|
||||||
|
: 'Click to launch game. Right-click to manage this version install'
|
||||||
|
}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (normalConfig?.settings.useLegacyInteractButtons) return
|
if (normalConfig?.settings.useLegacyInteractButtons) return
|
||||||
const verInfo = getVersionInfo(entry)
|
const verInfo = getVersionInfo(entry)
|
||||||
if (verInfo == undefined) return
|
if (verInfo == undefined) return
|
||||||
|
const gameInfo = getGameInfo(verInfo.game)
|
||||||
|
if (gameInfo == undefined) return
|
||||||
invoke('launch_game', {
|
invoke('launch_game', {
|
||||||
name: verInfo.id,
|
name: verInfo.id,
|
||||||
executable: verInfo.executable
|
executable: verInfo.executable,
|
||||||
|
displayName: verInfo.displayName,
|
||||||
|
useWine: !!(
|
||||||
|
platform() === 'linux' &&
|
||||||
|
verInfo.wine &&
|
||||||
|
normalConfig?.settings.useWineOnUnixWhenNeeded
|
||||||
|
),
|
||||||
|
wineCommand: normalConfig?.settings.wineOnUnixCommand
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
onMouseEnter={() => setHoveredIds(prev => [...prev, entry])}
|
onContextMenu={e => {
|
||||||
onMouseLeave={() =>
|
e.preventDefault()
|
||||||
setHoveredIds(prev => prev.filter(i => i !== i))
|
if (normalConfig?.settings.useLegacyInteractButtons) return
|
||||||
}
|
|
||||||
|
setManagingVersion(entry)
|
||||||
|
setPopupMode(2)
|
||||||
|
setShowPopup(true)
|
||||||
|
setFadeOut(false)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className='flex flex-col'>
|
<div className='h-18 w-screen relative'>
|
||||||
<p className='text-2xl'>
|
<p className='text-2xl'>
|
||||||
{getVersionGame(getVersionInfo(entry)?.game)?.name} v
|
{getVersionInfo(entry)?.displayName}
|
||||||
{getVersionInfo(entry)?.versionName}
|
|
||||||
</p>
|
</p>
|
||||||
<div
|
|
||||||
className={`entry-info-item ${
|
<div className='flex gap-2 absolute left-0 bottom-0'>
|
||||||
hoveredIds.includes(entry) ? 'btntheme3' : 'btntheme2'
|
<div
|
||||||
}`}
|
className='entry-info-item'
|
||||||
>
|
title='The date the game was installed.'
|
||||||
<p>
|
onClick={e => e.stopPropagation()}
|
||||||
Installed{' '}
|
>
|
||||||
{format(
|
<p>
|
||||||
new Date(downloadedVersionsConfig.timestamps[entry]),
|
Installed{' '}
|
||||||
'MM/dd/yyyy'
|
{new Intl.DateTimeFormat(undefined).format(
|
||||||
)}
|
downloadedVersionsConfig?.list[entry]
|
||||||
</p>
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className='entry-info-item'
|
||||||
|
title='This version is using wine. It cannot be guarenteed to work fully and might not work at all.'
|
||||||
|
hidden={
|
||||||
|
!(
|
||||||
|
platform() === 'linux' &&
|
||||||
|
getVersionInfo(entry)?.wine
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
|
||||||
|
<p>Uses wine</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex gap-2 absolute right-0 bottom-0'>
|
||||||
|
<button
|
||||||
|
className='button'
|
||||||
|
onClick={e => {
|
||||||
|
e.stopPropagation()
|
||||||
|
setManagingVersion(entry)
|
||||||
|
setPopupMode(3)
|
||||||
|
setShowPopup(true)
|
||||||
|
setFadeOut(false)
|
||||||
|
}}
|
||||||
|
title='Click to view version info'
|
||||||
|
>
|
||||||
|
View Info
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className='button'
|
||||||
|
hidden={
|
||||||
|
!normalConfig?.settings.useLegacyInteractButtons
|
||||||
|
}
|
||||||
|
onClick={e => {
|
||||||
|
e.stopPropagation()
|
||||||
|
setManagingVersion(entry)
|
||||||
|
setPopupMode(2)
|
||||||
|
setShowPopup(true)
|
||||||
|
setFadeOut(false)
|
||||||
|
}}
|
||||||
|
title='Click to manage this version install'
|
||||||
|
>
|
||||||
|
Manage
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className='button'
|
||||||
|
onClick={e => {
|
||||||
|
e.stopPropagation()
|
||||||
|
const verInfo = getVersionInfo(entry)
|
||||||
|
if (verInfo == undefined) return
|
||||||
|
invoke('launch_game', {
|
||||||
|
name: verInfo.id,
|
||||||
|
executable: verInfo.executable
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
hidden={
|
||||||
|
!normalConfig?.settings.useLegacyInteractButtons
|
||||||
|
}
|
||||||
|
title='Click to launch game'
|
||||||
|
>
|
||||||
|
Launch
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div className='flex flex-row items-center gap-2'>
|
|
||||||
<button
|
|
||||||
className={`button ${
|
|
||||||
hoveredIds.includes(entry) ? 'btntheme3' : 'btntheme2'
|
|
||||||
}`}
|
|
||||||
onClick={e => {
|
|
||||||
e.stopPropagation()
|
|
||||||
setManagingVersion(entry)
|
|
||||||
setPopupMode(3)
|
|
||||||
setShowPopup(true)
|
|
||||||
setFadeOut(false)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
View Info
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={`button ${
|
|
||||||
hoveredIds.includes(entry) ? 'btntheme3' : 'btntheme2'
|
|
||||||
}`}
|
|
||||||
onClick={e => {
|
|
||||||
e.stopPropagation()
|
|
||||||
setManagingVersion(entry)
|
|
||||||
setPopupMode(2)
|
|
||||||
setShowPopup(true)
|
|
||||||
setFadeOut(false)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Manage
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={`button ${
|
|
||||||
hoveredIds.includes(entry) ? 'btntheme3' : 'btntheme2'
|
|
||||||
}`}
|
|
||||||
onClick={e => {
|
|
||||||
e.stopPropagation()
|
|
||||||
const verInfo = getVersionInfo(entry)
|
|
||||||
if (verInfo == undefined) return
|
|
||||||
invoke('launch_game', {
|
|
||||||
name: verInfo.id,
|
|
||||||
executable: verInfo.executable
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
hidden={!normalConfig?.settings.useLegacyInteractButtons}
|
|
||||||
>
|
|
||||||
Launch
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
|
|||||||
+297
-252
@@ -44,6 +44,8 @@ import {
|
|||||||
isPermissionGranted,
|
isPermissionGranted,
|
||||||
requestPermission
|
requestPermission
|
||||||
} from '@tauri-apps/plugin-notification'
|
} from '@tauri-apps/plugin-notification'
|
||||||
|
import VersionChangelog from './componets/VersionChangelog'
|
||||||
|
import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs'
|
||||||
|
|
||||||
const roboto = Roboto({
|
const roboto = Roboto({
|
||||||
subsets: ['latin']
|
subsets: ['latin']
|
||||||
@@ -79,34 +81,127 @@ export default function RootLayout ({
|
|||||||
useState<boolean>(false)
|
useState<boolean>(false)
|
||||||
const [selectedGame, setSelectedGame] = useState<number | null>(null)
|
const [selectedGame, setSelectedGame] = useState<number | null>(null)
|
||||||
|
|
||||||
function handleOverlayClick (e: React.MouseEvent<HTMLDivElement>) {
|
const pathname = usePathname()
|
||||||
if (e.target === e.currentTarget) {
|
|
||||||
if (viewingInfoFromDownloads) {
|
function getSpecialVersionsList (game?: number): GameVersion[] {
|
||||||
setPopupMode(0)
|
if (!normalConfig || !serverVersionList) return []
|
||||||
setViewingInfoFromDownloads(false)
|
|
||||||
setManagingVersion(null)
|
return serverVersionList.versions
|
||||||
setSelectedGame(null)
|
.filter(
|
||||||
}
|
v => !Object.keys(downloadedVersionsConfig?.list ?? []).includes(v.id)
|
||||||
|
)
|
||||||
|
.filter(v => {
|
||||||
|
if (
|
||||||
|
platform() === 'linux' &&
|
||||||
|
v.wine &&
|
||||||
|
!normalConfig.settings.useWineOnUnixWhenNeeded
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (game && v.game != game) return false
|
||||||
|
if (downloadProgress.length != 0) {
|
||||||
|
return !downloadProgress.some(d => d.version === v.id)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (b.game !== a.game) return a.game - b.game
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVersionInfo (id: string | undefined): GameVersion | undefined {
|
||||||
|
if (!id) return undefined
|
||||||
|
return serverVersionList?.versions.find(v => v.id === id)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGameInfo (game: number | undefined): Game | undefined {
|
||||||
|
if (!game) return undefined
|
||||||
|
return serverVersionList?.games.find(g => g.id === game)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getListOfGames (): Game[] {
|
||||||
|
if (!downloadedVersionsConfig?.list) return []
|
||||||
|
|
||||||
|
const gamesMap = new Map<number, Game>()
|
||||||
|
|
||||||
|
Object.keys(downloadedVersionsConfig.list).forEach(i => {
|
||||||
|
const version = getVersionInfo(i)
|
||||||
|
if (!version) return
|
||||||
|
const game = getGameInfo(version.game)
|
||||||
|
if (!game) return
|
||||||
|
gamesMap.set(game.id, game)
|
||||||
|
})
|
||||||
|
|
||||||
|
return Array.from(gamesMap.values())
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVersionsAmountData (gameId: number): {
|
||||||
|
installed: number
|
||||||
|
total: number
|
||||||
|
} | null {
|
||||||
|
if (!downloadedVersionsConfig || !serverVersionList) return null
|
||||||
|
|
||||||
|
const allowWine =
|
||||||
|
platform() !== 'linux' || normalConfig?.settings.useWineOnUnixWhenNeeded
|
||||||
|
|
||||||
|
const installed = Object.keys(downloadedVersionsConfig.list).filter(v => {
|
||||||
|
const info = getVersionInfo(v)
|
||||||
|
if (!info) return false
|
||||||
|
if (info.wine && !allowWine) return false
|
||||||
|
return getGameInfo(info.game)?.id === gameId
|
||||||
|
}).length
|
||||||
|
|
||||||
|
const total = serverVersionList.versions.filter(v => {
|
||||||
|
if (!v) return false
|
||||||
|
if (v.wine && !allowWine) return false
|
||||||
|
return getGameInfo(v.game)?.id === gameId
|
||||||
|
}).length
|
||||||
|
|
||||||
|
return { installed, total }
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatEtaSmart (seconds: number) {
|
||||||
|
if (seconds < 60) return `${Math.floor(seconds)}s`
|
||||||
|
if (seconds < 3600)
|
||||||
|
return `${Math.floor(seconds / 60)}m ${Math.floor(seconds % 60)}s`
|
||||||
|
if (seconds < 86400) {
|
||||||
|
const h = Math.floor(seconds / 3600)
|
||||||
|
const m = Math.floor((seconds % 3600) / 60)
|
||||||
|
return `${h}h ${m}m`
|
||||||
|
}
|
||||||
|
const d = Math.floor(seconds / 86400)
|
||||||
|
const h = Math.floor((seconds % 86400) / 3600)
|
||||||
|
return `${d}d ${h}h`
|
||||||
|
}
|
||||||
|
|
||||||
|
function closePopup () {
|
||||||
|
if (popupMode == 0 && selectedGame && pathname === '/') {
|
||||||
|
setSelectedGame(null)
|
||||||
|
setSelectedVersionList([])
|
||||||
|
} else if (viewingInfoFromDownloads) {
|
||||||
|
setViewingInfoFromDownloads(false)
|
||||||
|
setPopupMode(0)
|
||||||
|
} else if (popupMode == 4) {
|
||||||
|
setPopupMode(3)
|
||||||
|
} else {
|
||||||
setFadeOut(true)
|
setFadeOut(true)
|
||||||
setTimeout(() => setShowPopup(false), 200)
|
setTimeout(() => setShowPopup(false), 200)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const pathname = usePathname()
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let unlistenProgress: (() => void) | null = null
|
let unlistenProgress: (() => void) | null = null
|
||||||
let unlistenUninstalled: (() => void) | null = null
|
|
||||||
|
|
||||||
listen<string>('download-progress', event => {
|
listen<string>('download-progress', event => {
|
||||||
const [versionName, progStr, totalSizeStr, speedStr, etaSecsStr] =
|
const [displayName, progStr, totalSizeStr, speedStr, etaSecsStr] =
|
||||||
event.payload.split(':')
|
event.payload.split(':')
|
||||||
const prog = Number(progStr)
|
const prog = Number(progStr)
|
||||||
const progBytes = Number(totalSizeStr)
|
const progBytes = Number(totalSizeStr)
|
||||||
const speed = Number(speedStr)
|
const speed = Number(speedStr)
|
||||||
const etaSecs = Number(etaSecsStr)
|
const etaSecs = Number(etaSecsStr)
|
||||||
setDownloadProgress(prev => {
|
setDownloadProgress(prev => {
|
||||||
const i = prev.findIndex(d => d.version === versionName)
|
const i = prev.findIndex(d => d.version === displayName)
|
||||||
if (i === -1) return prev
|
if (i === -1) return prev
|
||||||
const copy = [...prev]
|
const copy = [...prev]
|
||||||
copy[i] = {
|
copy[i] = {
|
||||||
@@ -121,9 +216,9 @@ export default function RootLayout ({
|
|||||||
}).then(f => (unlistenProgress = f))
|
}).then(f => (unlistenProgress = f))
|
||||||
|
|
||||||
listen<string>('download-hash-checking', event => {
|
listen<string>('download-hash-checking', event => {
|
||||||
const versionName = event.payload
|
const displayName = event.payload
|
||||||
setDownloadProgress(prev => {
|
setDownloadProgress(prev => {
|
||||||
const i = prev.findIndex(d => d.version === versionName)
|
const i = prev.findIndex(d => d.version === displayName)
|
||||||
if (i === -1) return prev
|
if (i === -1) return prev
|
||||||
const copy = [...prev]
|
const copy = [...prev]
|
||||||
copy[i] = { ...copy[i], hash_checking: true }
|
copy[i] = { ...copy[i], hash_checking: true }
|
||||||
@@ -132,9 +227,9 @@ export default function RootLayout ({
|
|||||||
}).then(f => (unlistenProgress = f))
|
}).then(f => (unlistenProgress = f))
|
||||||
|
|
||||||
listen<string>('download-finishing', event => {
|
listen<string>('download-finishing', event => {
|
||||||
const versionName = event.payload
|
const displayName = event.payload
|
||||||
setDownloadProgress(prev => {
|
setDownloadProgress(prev => {
|
||||||
const i = prev.findIndex(d => d.version === versionName)
|
const i = prev.findIndex(d => d.version === displayName)
|
||||||
if (i === -1) return prev
|
if (i === -1) return prev
|
||||||
const copy = [...prev]
|
const copy = [...prev]
|
||||||
copy[i] = { ...copy[i], hash_checking: false, finishing: true }
|
copy[i] = { ...copy[i], hash_checking: false, finishing: true }
|
||||||
@@ -142,30 +237,8 @@ export default function RootLayout ({
|
|||||||
})
|
})
|
||||||
}).then(f => (unlistenProgress = f))
|
}).then(f => (unlistenProgress = f))
|
||||||
|
|
||||||
listen<string>('version-uninstalled', event => {
|
|
||||||
const versionName = event.payload
|
|
||||||
setDownloadedVersionsConfig(prev => {
|
|
||||||
if (!prev) return prev
|
|
||||||
const updatedList = prev.list.filter(v => v !== versionName)
|
|
||||||
const updatedTimestamps = Object.fromEntries(
|
|
||||||
Object.entries(prev.timestamps).filter(([k]) => k !== versionName)
|
|
||||||
)
|
|
||||||
const updatedConfig = {
|
|
||||||
...prev,
|
|
||||||
list: updatedList,
|
|
||||||
timestamps: updatedTimestamps
|
|
||||||
}
|
|
||||||
writeVersionsConfig(updatedConfig)
|
|
||||||
setManagingVersion(null)
|
|
||||||
setFadeOut(true)
|
|
||||||
setTimeout(() => setShowPopup(false), 200)
|
|
||||||
return updatedConfig
|
|
||||||
})
|
|
||||||
}).then(f => (unlistenUninstalled = f))
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unlistenProgress?.()
|
unlistenProgress?.()
|
||||||
unlistenUninstalled?.()
|
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@@ -203,6 +276,7 @@ export default function RootLayout ({
|
|||||||
const versionsConfig = await readVersionsConfig()
|
const versionsConfig = await readVersionsConfig()
|
||||||
setDownloadedVersionsConfig(versionsConfig)
|
setDownloadedVersionsConfig(versionsConfig)
|
||||||
setNormalConfig(normalConfig)
|
setNormalConfig(normalConfig)
|
||||||
|
setLoadingText('Finishing...')
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
||||||
if (!(await isPermissionGranted())) {
|
if (!(await isPermissionGranted())) {
|
||||||
@@ -218,47 +292,6 @@ export default function RootLayout ({
|
|||||||
return () => document.removeEventListener('contextmenu', handler)
|
return () => document.removeEventListener('contextmenu', handler)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
function getSpecialVersionsList (game?: number): GameVersion[] {
|
|
||||||
if (!normalConfig || !serverVersionList) return []
|
|
||||||
|
|
||||||
return serverVersionList.versions
|
|
||||||
.filter(v => !downloadedVersionsConfig?.list.includes(v.id))
|
|
||||||
.filter(v => {
|
|
||||||
if (game && v.game != game) return false
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
.sort((a, b) => {
|
|
||||||
if (b.game !== a.game) return a.game - b.game
|
|
||||||
return 0
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVersionInfo (id: string | undefined): GameVersion | undefined {
|
|
||||||
if (!id) return undefined
|
|
||||||
return serverVersionList?.versions.find(v => v.id === id)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVersionGame (game: number | undefined): Game | undefined {
|
|
||||||
if (!game) return undefined
|
|
||||||
return serverVersionList?.games.find(g => g.id === game)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getListOfGames (): Game[] {
|
|
||||||
if (!downloadedVersionsConfig?.list) return []
|
|
||||||
|
|
||||||
const gamesMap = new Map<number, Game>()
|
|
||||||
|
|
||||||
downloadedVersionsConfig.list.forEach(i => {
|
|
||||||
const version = getVersionInfo(i)
|
|
||||||
if (!version) return
|
|
||||||
const game = getVersionGame(version.game)
|
|
||||||
if (!game) return
|
|
||||||
gamesMap.set(game.id, game)
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.from(gamesMap.values())
|
|
||||||
}
|
|
||||||
|
|
||||||
async function downloadVersions (): Promise<void> {
|
async function downloadVersions (): Promise<void> {
|
||||||
const list = selectedVersionList
|
const list = selectedVersionList
|
||||||
setSelectedVersionList([])
|
setSelectedVersionList([])
|
||||||
@@ -278,7 +311,7 @@ export default function RootLayout ({
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const gameInfo = getVersionGame(info.game)
|
const gameInfo = getGameInfo(info.game)
|
||||||
if (!gameInfo) {
|
if (!gameInfo) {
|
||||||
setDownloadProgress(prev =>
|
setDownloadProgress(prev =>
|
||||||
prev.filter(d => d.version !== download.version)
|
prev.filter(d => d.version !== download.version)
|
||||||
@@ -308,8 +341,7 @@ export default function RootLayout ({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const date = Date.now()
|
const date = Date.now()
|
||||||
data.list = [...data.list, download.version]
|
data.list = { ...data.list, [download.version]: date }
|
||||||
data.timestamps = { ...data.timestamps, [download.version]: date }
|
|
||||||
setDownloadedVersionsConfig(data)
|
setDownloadedVersionsConfig(data)
|
||||||
writeVersionsConfig(data)
|
writeVersionsConfig(data)
|
||||||
} else {
|
} else {
|
||||||
@@ -323,7 +355,7 @@ export default function RootLayout ({
|
|||||||
if (normalConfig?.settings.allowNotifications)
|
if (normalConfig?.settings.allowNotifications)
|
||||||
await notifyUser(
|
await notifyUser(
|
||||||
'Download Failed',
|
'Download Failed',
|
||||||
`The download for version ${gameInfo.name} v${info.versionName} has failed.`
|
`The download for version ${info.displayName} has failed.`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,37 +364,6 @@ export default function RootLayout ({
|
|||||||
await notifyUser('Downloads Finished', 'All downloads have finished.')
|
await notifyUser('Downloads Finished', 'All downloads have finished.')
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVersionsAmountData (gameId: number): {
|
|
||||||
installed: number
|
|
||||||
total: number
|
|
||||||
} | null {
|
|
||||||
if (!downloadedVersionsConfig || !serverVersionList) return null
|
|
||||||
|
|
||||||
const installed = downloadedVersionsConfig.list.filter(
|
|
||||||
v => getVersionGame(getVersionInfo(v)?.game)?.id === gameId
|
|
||||||
).length
|
|
||||||
|
|
||||||
const total = serverVersionList.versions.filter(
|
|
||||||
v => getVersionGame(v?.game)?.id === gameId
|
|
||||||
).length
|
|
||||||
|
|
||||||
return { installed, total }
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatEtaSmart (seconds: number) {
|
|
||||||
if (seconds < 60) return `${Math.floor(seconds)}s`
|
|
||||||
if (seconds < 3600)
|
|
||||||
return `${Math.floor(seconds / 60)}m ${Math.floor(seconds % 60)}s`
|
|
||||||
if (seconds < 86400) {
|
|
||||||
const h = Math.floor(seconds / 3600)
|
|
||||||
const m = Math.floor((seconds % 3600) / 60)
|
|
||||||
return `${h}h ${m}m`
|
|
||||||
}
|
|
||||||
const d = Math.floor(seconds / 86400)
|
|
||||||
const h = Math.floor((seconds % 86400) / 3600)
|
|
||||||
return `${d}d ${h}h`
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<html lang='en' className={roboto.className}>
|
<html lang='en' className={roboto.className}>
|
||||||
@@ -376,6 +377,8 @@ export default function RootLayout ({
|
|||||||
? 'blue-theme'
|
? 'blue-theme'
|
||||||
: normalConfig?.settings.theme === 4
|
: normalConfig?.settings.theme === 4
|
||||||
? 'purple-theme'
|
? 'purple-theme'
|
||||||
|
: normalConfig?.settings.theme === 5
|
||||||
|
? 'mint-theme'
|
||||||
: 'dark-theme'
|
: 'dark-theme'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -421,7 +424,7 @@ export default function RootLayout ({
|
|||||||
managingVersion,
|
managingVersion,
|
||||||
setManagingVersion,
|
setManagingVersion,
|
||||||
getVersionInfo,
|
getVersionInfo,
|
||||||
getVersionGame,
|
getGameInfo,
|
||||||
getListOfGames,
|
getListOfGames,
|
||||||
setSelectedGame,
|
setSelectedGame,
|
||||||
getVersionsAmountData,
|
getVersionsAmountData,
|
||||||
@@ -432,18 +435,7 @@ export default function RootLayout ({
|
|||||||
<div
|
<div
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onKeyDown={e => {
|
onKeyDown={e => {
|
||||||
if (showPopup && e.key === 'Escape') {
|
if (showPopup && e.key === 'Escape') closePopup()
|
||||||
if (popupMode == 0 && selectedGame) {
|
|
||||||
setSelectedGame(null)
|
|
||||||
setSelectedVersionList([])
|
|
||||||
} else if (viewingInfoFromDownloads) {
|
|
||||||
setViewingInfoFromDownloads(false)
|
|
||||||
setPopupMode(0)
|
|
||||||
} else {
|
|
||||||
setFadeOut(true)
|
|
||||||
setTimeout(() => setShowPopup(false), 200)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
@@ -459,34 +451,31 @@ export default function RootLayout ({
|
|||||||
{showPopup && (
|
{showPopup && (
|
||||||
<div
|
<div
|
||||||
className={`popup-overlay ${fadeOut ? 'fade-out' : ''}`}
|
className={`popup-overlay ${fadeOut ? 'fade-out' : ''}`}
|
||||||
onClick={handleOverlayClick}
|
onClick={(e: React.MouseEvent<HTMLDivElement>) => {
|
||||||
|
if (e.target === e.currentTarget) {
|
||||||
|
if (viewingInfoFromDownloads) {
|
||||||
|
setPopupMode(0)
|
||||||
|
setViewingInfoFromDownloads(false)
|
||||||
|
setManagingVersion(null)
|
||||||
|
setSelectedGame(null)
|
||||||
|
}
|
||||||
|
setFadeOut(true)
|
||||||
|
setTimeout(() => setShowPopup(false), 200)
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className='popup-box'>
|
<div className='popup-box'>
|
||||||
<button
|
<button
|
||||||
className='close-button'
|
className='close-button btntheme1'
|
||||||
onClick={() => {
|
onClick={() => closePopup()}
|
||||||
if (
|
|
||||||
popupMode == 0 &&
|
|
||||||
selectedGame &&
|
|
||||||
pathname === '/'
|
|
||||||
) {
|
|
||||||
setSelectedGame(null)
|
|
||||||
setSelectedVersionList([])
|
|
||||||
} else if (viewingInfoFromDownloads) {
|
|
||||||
setViewingInfoFromDownloads(false)
|
|
||||||
setPopupMode(0)
|
|
||||||
} else {
|
|
||||||
setFadeOut(true)
|
|
||||||
setTimeout(() => setShowPopup(false), 200)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={
|
icon={
|
||||||
(popupMode == 0 &&
|
(popupMode == 0 &&
|
||||||
selectedGame &&
|
selectedGame &&
|
||||||
pathname === '/') ||
|
pathname === '/') ||
|
||||||
viewingInfoFromDownloads
|
viewingInfoFromDownloads ||
|
||||||
|
popupMode == 4
|
||||||
? faChevronLeft
|
? faChevronLeft
|
||||||
: faXmark
|
: faXmark
|
||||||
}
|
}
|
||||||
@@ -505,16 +494,15 @@ export default function RootLayout ({
|
|||||||
<p
|
<p
|
||||||
className={`text-2xl truncate ${
|
className={`text-2xl truncate ${
|
||||||
selectedVersionList.includes(v.id)
|
selectedVersionList.includes(v.id)
|
||||||
? 'max-w-82.5'
|
? 'max-w-84.5'
|
||||||
: 'max-w-90'
|
: 'max-w-91.5'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{getVersionGame(v.game)?.name} v
|
{v.displayName}
|
||||||
{v.versionName}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
className='button btntheme3 right-22 bottom-1.5'
|
className='button btntheme3 right-20.75 bottom-1.75'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedVersionList(prev =>
|
setSelectedVersionList(prev =>
|
||||||
prev.includes(v.id)
|
prev.includes(v.id)
|
||||||
@@ -522,6 +510,11 @@ export default function RootLayout ({
|
|||||||
: [...prev, v.id]
|
: [...prev, v.id]
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
title={
|
||||||
|
selectedVersionList.includes(v.id)
|
||||||
|
? 'This version will be downloaded. Click to remove from the list of versions that will be downloaded.'
|
||||||
|
: 'This version will NOT be downloaded. Click to add from the list of versions that will be downloaded.'
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{selectedVersionList.includes(v.id) ? (
|
{selectedVersionList.includes(v.id) ? (
|
||||||
<>
|
<>
|
||||||
@@ -535,12 +528,13 @@ export default function RootLayout ({
|
|||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className='button btntheme3 right-1.5 bottom-1.5'
|
className='button btntheme3 right-1.5 bottom-1.75'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setManagingVersion(v.id)
|
setManagingVersion(v.id)
|
||||||
setViewingInfoFromDownloads(true)
|
setViewingInfoFromDownloads(true)
|
||||||
setPopupMode(3)
|
setPopupMode(3)
|
||||||
}}
|
}}
|
||||||
|
title='Click to view version info'
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faInfo} /> Info
|
<FontAwesomeIcon icon={faInfo} /> Info
|
||||||
</button>
|
</button>
|
||||||
@@ -559,7 +553,10 @@ export default function RootLayout ({
|
|||||||
<div key={i} className='popup-entry'>
|
<div key={i} className='popup-entry'>
|
||||||
<p className='text-2xl'>{v.name}</p>
|
<p className='text-2xl'>{v.name}</p>
|
||||||
<div className='flex gap-2'>
|
<div className='flex gap-2'>
|
||||||
<div className='entry-info-item btntheme3'>
|
<div
|
||||||
|
className='entry-info-item btntheme3'
|
||||||
|
title='The amount of versions installed of this game in installed/installable format.'
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
{(() => {
|
{(() => {
|
||||||
const data = getVersionsAmountData(v.id)
|
const data = getVersionsAmountData(v.id)
|
||||||
@@ -572,6 +569,7 @@ export default function RootLayout ({
|
|||||||
<div
|
<div
|
||||||
className='entry-info-item btntheme3'
|
className='entry-info-item btntheme3'
|
||||||
hidden={!v.official}
|
hidden={!v.official}
|
||||||
|
title='This game is official.'
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={faCheck}
|
icon={faCheck}
|
||||||
@@ -582,6 +580,11 @@ export default function RootLayout ({
|
|||||||
<div
|
<div
|
||||||
className='entry-info-item btntheme3'
|
className='entry-info-item btntheme3'
|
||||||
hidden={v.official}
|
hidden={v.official}
|
||||||
|
title={
|
||||||
|
v.verified
|
||||||
|
? 'This game is verified to be safe'
|
||||||
|
: 'This game is NOT verified to be save. Proceed with caution.'
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={
|
icon={
|
||||||
@@ -596,7 +599,8 @@ export default function RootLayout ({
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className='entry-info-item btntheme3 mt-2'
|
className='entry-info-item btntheme3 mt-2'
|
||||||
hidden={v.official}
|
hidden={v.developer == null}
|
||||||
|
title={`The developer of ${v.name} is ${v.developer}.`}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={faCode}
|
icon={faCode}
|
||||||
@@ -607,6 +611,11 @@ export default function RootLayout ({
|
|||||||
<button
|
<button
|
||||||
className='button btntheme3 right-2 bottom-2'
|
className='button btntheme3 right-2 bottom-2'
|
||||||
onClick={() => setSelectedGame(v.id)}
|
onClick={() => setSelectedGame(v.id)}
|
||||||
|
title={`Click to download specific versions of the game. You have ${(() => {
|
||||||
|
const data = getVersionsAmountData(v.id)
|
||||||
|
if (!data) return 'N/A'
|
||||||
|
return `${data.installed} of ${data.total}`
|
||||||
|
})()} versions downloaded.`}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
<FontAwesomeIcon icon={faDownload} />{' '}
|
<FontAwesomeIcon icon={faDownload} />{' '}
|
||||||
@@ -621,96 +630,85 @@ export default function RootLayout ({
|
|||||||
<>
|
<>
|
||||||
<p className='text-xl text-center'>Downloads</p>
|
<p className='text-xl text-center'>Downloads</p>
|
||||||
<div className='popup-content'>
|
<div className='popup-content'>
|
||||||
{downloadProgress.length === 0 ? (
|
{downloadProgress.map((v, i) => (
|
||||||
<p className='text-center mt-6'>
|
<div
|
||||||
No more downloads!
|
key={i}
|
||||||
</p>
|
className='popup-entry flex flex-col justify-between'
|
||||||
) : (
|
>
|
||||||
downloadProgress.map((v, i) => (
|
<p className='text-2xl text-center'>
|
||||||
<div
|
{getVersionInfo(v.version)?.displayName}
|
||||||
key={i}
|
</p>
|
||||||
className='popup-entry flex flex-col justify-between'
|
<div className='mt-6.25 flex items-center justify-between'>
|
||||||
>
|
{v.failed ? (
|
||||||
<p className='text-2xl text-center'>
|
<>
|
||||||
{
|
<div className='flex items-center'>
|
||||||
getVersionGame(
|
<span className='text-red-500 inline-block w-full text-center'>
|
||||||
getVersionInfo(v.version)?.game
|
Download failed
|
||||||
)?.name
|
|
||||||
}{' '}
|
|
||||||
v{getVersionInfo(v.version)?.versionName}
|
|
||||||
</p>
|
|
||||||
<div className='mt-6.25 flex items-center justify-between'>
|
|
||||||
{v.failed ? (
|
|
||||||
<>
|
|
||||||
<div className='flex items-center'>
|
|
||||||
<span className='text-red-500 inline-block w-full text-center'>
|
|
||||||
Download failed
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
className='button btntheme3 ml-30 mb-2'
|
|
||||||
onClick={() => {
|
|
||||||
setDownloadProgress(prev =>
|
|
||||||
prev.filter(
|
|
||||||
d => d.version !== v.version
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) : v.queued ? (
|
|
||||||
<span className='text-yellow-500 inline-block w-full text-center'>
|
|
||||||
Queued…
|
|
||||||
</span>
|
|
||||||
) : v.queued ? (
|
|
||||||
<span className='text-yellow-500 inline-block w-full text-center'>
|
|
||||||
Queued…
|
|
||||||
</span>
|
|
||||||
) : v.hash_checking ? (
|
|
||||||
<span className='text-blue-500 inline-block w-full text-center'>
|
|
||||||
Checking hash...
|
|
||||||
</span>
|
|
||||||
) : v.finishing ? (
|
|
||||||
<span className='text-green-500 inline-block w-full text-center'>
|
|
||||||
Finishing...
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<div className='flex flex-col gap-1 w-full'>
|
|
||||||
<span className='text-center'>
|
|
||||||
Downloaded{' '}
|
|
||||||
{prettyBytes(v.progressBytes, {
|
|
||||||
minimumFractionDigits: 1,
|
|
||||||
maximumFractionDigits: 1
|
|
||||||
})}{' '}
|
|
||||||
of{' '}
|
|
||||||
{prettyBytes(
|
|
||||||
getVersionInfo(v.version)?.size ??
|
|
||||||
0,
|
|
||||||
{
|
|
||||||
minimumFractionDigits: 1,
|
|
||||||
maximumFractionDigits: 1
|
|
||||||
}
|
|
||||||
)}{' '}
|
|
||||||
(ETA: {formatEtaSmart(v.etaSecs)}{' '}
|
|
||||||
• Speed:{' '}
|
|
||||||
{prettyBytes(v.speed, {
|
|
||||||
minimumFractionDigits: 1,
|
|
||||||
maximumFractionDigits: 1
|
|
||||||
})}
|
|
||||||
/s)
|
|
||||||
</span>
|
</span>
|
||||||
<ProgressBar
|
<button
|
||||||
progress={v.progress}
|
className='button btntheme3 ml-30 mb-2'
|
||||||
className='w-full'
|
onClick={() => {
|
||||||
/>
|
setDownloadProgress(prev =>
|
||||||
|
prev.filter(
|
||||||
|
d => d.version !== v.version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
title='Click to remove this version from this menu.'
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</>
|
||||||
</div>
|
) : v.queued ? (
|
||||||
|
<span className='text-yellow-500 inline-block w-full text-center'>
|
||||||
|
Queued…
|
||||||
|
</span>
|
||||||
|
) : v.queued ? (
|
||||||
|
<span className='text-yellow-500 inline-block w-full text-center'>
|
||||||
|
Queued…
|
||||||
|
</span>
|
||||||
|
) : v.hash_checking ? (
|
||||||
|
<span className='text-blue-500 inline-block w-full text-center'>
|
||||||
|
Checking hash...
|
||||||
|
</span>
|
||||||
|
) : v.finishing ? (
|
||||||
|
<span className='text-green-500 inline-block w-full text-center'>
|
||||||
|
Finishing...
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<div className='flex flex-col gap-1 w-full'>
|
||||||
|
<span className='text-center'>
|
||||||
|
Downloaded{' '}
|
||||||
|
{prettyBytes(v.progressBytes, {
|
||||||
|
minimumFractionDigits: 1,
|
||||||
|
maximumFractionDigits: 1
|
||||||
|
})}{' '}
|
||||||
|
of{' '}
|
||||||
|
{prettyBytes(
|
||||||
|
getVersionInfo(v.version)?.size ?? 0,
|
||||||
|
{
|
||||||
|
minimumFractionDigits: 1,
|
||||||
|
maximumFractionDigits: 1
|
||||||
|
}
|
||||||
|
)}{' '}
|
||||||
|
(ETA: {formatEtaSmart(v.etaSecs)} •
|
||||||
|
Speed:{' '}
|
||||||
|
{prettyBytes(v.speed, {
|
||||||
|
minimumFractionDigits: 1,
|
||||||
|
maximumFractionDigits: 1
|
||||||
|
})}
|
||||||
|
/s)
|
||||||
|
</span>
|
||||||
|
<ProgressBar
|
||||||
|
progress={v.progress}
|
||||||
|
className='w-full'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
))
|
</div>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : popupMode === 2 ? (
|
) : popupMode === 2 ? (
|
||||||
@@ -718,22 +716,44 @@ export default function RootLayout ({
|
|||||||
<>
|
<>
|
||||||
<p className='text-xl text-center'>
|
<p className='text-xl text-center'>
|
||||||
Manage{' '}
|
Manage{' '}
|
||||||
{
|
{getVersionInfo(managingVersion)?.displayName}
|
||||||
getVersionGame(
|
|
||||||
getVersionInfo(managingVersion)?.game
|
|
||||||
)?.name
|
|
||||||
}{' '}
|
|
||||||
v{getVersionInfo(managingVersion)?.versionName}
|
|
||||||
</p>
|
</p>
|
||||||
<div className='popup-content flex flex-col items-center justify-center gap-2 h-full'>
|
<div className='popup-content flex flex-col items-center justify-center gap-2 h-full'>
|
||||||
<button
|
<button
|
||||||
className='button btntheme2'
|
className='button btntheme2'
|
||||||
disabled={downloadProgress.length != 0}
|
disabled={downloadProgress.length != 0}
|
||||||
onClick={() =>
|
onClick={async () => {
|
||||||
invoke('uninstall_version', {
|
closePopup()
|
||||||
name: managingVersion
|
|
||||||
|
setDownloadedVersionsConfig(prev => {
|
||||||
|
if (!prev) return prev
|
||||||
|
const updatedList = Object.fromEntries(
|
||||||
|
Object.entries(prev.list).filter(
|
||||||
|
([k]) => k !== managingVersion
|
||||||
|
)
|
||||||
|
)
|
||||||
|
const updatedConfig = {
|
||||||
|
...prev,
|
||||||
|
list: updatedList
|
||||||
|
}
|
||||||
|
writeVersionsConfig(updatedConfig)
|
||||||
|
setManagingVersion(null)
|
||||||
|
setFadeOut(true)
|
||||||
|
setTimeout(() => setShowPopup(false), 200)
|
||||||
|
return updatedConfig
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
if (
|
||||||
|
await exists('game/' + managingVersion, {
|
||||||
|
baseDir: BaseDirectory.AppLocalData
|
||||||
|
})
|
||||||
|
)
|
||||||
|
await remove('game/' + managingVersion, {
|
||||||
|
baseDir: BaseDirectory.AppLocalData,
|
||||||
|
recursive: true
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
title='Click to uninstall this game. This will NOT remove any progress or any save files.'
|
||||||
>
|
>
|
||||||
Uninstall
|
Uninstall
|
||||||
</button>
|
</button>
|
||||||
@@ -744,6 +764,7 @@ export default function RootLayout ({
|
|||||||
name: managingVersion
|
name: managingVersion
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
title="Click to browse the game's files."
|
||||||
>
|
>
|
||||||
Open Folder
|
Open Folder
|
||||||
</button>
|
</button>
|
||||||
@@ -762,6 +783,14 @@ export default function RootLayout ({
|
|||||||
No version selected
|
No version selected
|
||||||
</p>
|
</p>
|
||||||
)
|
)
|
||||||
|
) : popupMode === 4 ? (
|
||||||
|
managingVersion && downloadedVersionsConfig ? (
|
||||||
|
<VersionChangelog />
|
||||||
|
) : (
|
||||||
|
<p className='text-xl text-center'>
|
||||||
|
No version selected
|
||||||
|
</p>
|
||||||
|
)
|
||||||
) : null}
|
) : null}
|
||||||
{popupMode == 0 &&
|
{popupMode == 0 &&
|
||||||
selectedGame &&
|
selectedGame &&
|
||||||
@@ -774,6 +803,16 @@ export default function RootLayout ({
|
|||||||
setTimeout(() => setShowPopup(false), 200)
|
setTimeout(() => setShowPopup(false), 200)
|
||||||
downloadVersions()
|
downloadVersions()
|
||||||
}}
|
}}
|
||||||
|
disabled={downloadProgress.length != 0}
|
||||||
|
title={
|
||||||
|
downloadProgress.length != 0
|
||||||
|
? "You cannot download the versions as you have another download that hasn't completed."
|
||||||
|
: `Click to download ${
|
||||||
|
selectedVersionList.length
|
||||||
|
} version${
|
||||||
|
selectedVersionList.length == 1 ? '' : 's'
|
||||||
|
} of ${getGameInfo(selectedGame)?.name}`
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Download {selectedVersionList.length} version
|
Download {selectedVersionList.length} version
|
||||||
{selectedVersionList.length == 1 ? '' : 's'}
|
{selectedVersionList.length == 1 ? '' : 's'}
|
||||||
@@ -788,6 +827,12 @@ export default function RootLayout ({
|
|||||||
prev.length === allIds.length ? [] : allIds
|
prev.length === allIds.length ? [] : allIds
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
title={
|
||||||
|
selectedVersionList.length ===
|
||||||
|
getSpecialVersionsList(selectedGame).length
|
||||||
|
? 'Click to remove all selected versions for download.'
|
||||||
|
: 'Click to add all selected versions for download.'
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{selectedVersionList.length ===
|
{selectedVersionList.length ===
|
||||||
getSpecialVersionsList(selectedGame).length
|
getSpecialVersionsList(selectedGame).length
|
||||||
|
|||||||
+27
-28
@@ -15,7 +15,6 @@ import { useRouter } from 'next/navigation'
|
|||||||
|
|
||||||
export default function Installs () {
|
export default function Installs () {
|
||||||
const {
|
const {
|
||||||
downloadProgress,
|
|
||||||
showPopup,
|
showPopup,
|
||||||
setShowPopup,
|
setShowPopup,
|
||||||
setPopupMode,
|
setPopupMode,
|
||||||
@@ -29,7 +28,6 @@ export default function Installs () {
|
|||||||
} = useGlobal()
|
} = useGlobal()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [hoveredIds, setHoveredIds] = useState<number[]>([])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!showPopup) return
|
if (!showPopup) return
|
||||||
@@ -41,14 +39,14 @@ export default function Installs () {
|
|||||||
<div className='flex justify-between items-center mb-4'>
|
<div className='flex justify-between items-center mb-4'>
|
||||||
<p className='text-3xl'>Games</p>
|
<p className='text-3xl'>Games</p>
|
||||||
<button
|
<button
|
||||||
className='button btntheme1 text-3xl'
|
className='button btntheme1'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedGame(null)
|
setSelectedGame(null)
|
||||||
setPopupMode(0)
|
setPopupMode(0)
|
||||||
setShowPopup(true)
|
setShowPopup(true)
|
||||||
setFadeOut(false)
|
setFadeOut(false)
|
||||||
}}
|
}}
|
||||||
disabled={downloadProgress.length != 0}
|
title='Click to download more games.'
|
||||||
>
|
>
|
||||||
Download game
|
Download game
|
||||||
</button>
|
</button>
|
||||||
@@ -74,23 +72,24 @@ export default function Installs () {
|
|||||||
? ''
|
? ''
|
||||||
: 'cursor-pointer'
|
: 'cursor-pointer'
|
||||||
}`}
|
}`}
|
||||||
title='Click to view game installs'
|
title={
|
||||||
|
normalConfig?.settings.useLegacyInteractButtons
|
||||||
|
? ''
|
||||||
|
: 'Click to view game installs'
|
||||||
|
}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (normalConfig?.settings.useLegacyInteractButtons) return
|
if (normalConfig?.settings.useLegacyInteractButtons) return
|
||||||
router.push('/game?id=' + i.id)
|
router.push('/game?id=' + i.id)
|
||||||
}}
|
}}
|
||||||
onMouseEnter={() => setHoveredIds(prev => [...prev, i.id])}
|
|
||||||
onMouseLeave={() =>
|
|
||||||
setHoveredIds(prev => prev.filter(e => e !== i.id))
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<div className='flex flex-col'>
|
<div className='h-18 w-screen relative'>
|
||||||
<p className='text-2xl'>{i.name}</p>
|
<p className='text-2xl'>{i.name}</p>
|
||||||
<div className='flex gap-2'>
|
|
||||||
|
<div className='flex gap-2 absolute left-0 bottom-0'>
|
||||||
<div
|
<div
|
||||||
className={`entry-info-item ${
|
className='entry-info-item'
|
||||||
hoveredIds.includes(i.id) ? 'btntheme3' : 'btntheme2'
|
title='The amount of versions installed of this game in installed/installable format.'
|
||||||
}`}
|
onClick={e => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
{(() => {
|
{(() => {
|
||||||
@@ -102,19 +101,23 @@ export default function Installs () {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`entry-info-item ${
|
className='entry-info-item'
|
||||||
hoveredIds.includes(i.id) ? 'btntheme3' : 'btntheme2'
|
|
||||||
}`}
|
|
||||||
hidden={!i.official}
|
hidden={!i.official}
|
||||||
|
title='This game is official.'
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faCheck} color='#19c84b' />
|
<FontAwesomeIcon icon={faCheck} color='#19c84b' />
|
||||||
<p>Official</p>
|
<p>Official</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`entry-info-item ${
|
className='entry-info-item'
|
||||||
hoveredIds.includes(i.id) ? 'btntheme3' : 'btntheme2'
|
|
||||||
}`}
|
|
||||||
hidden={i.official}
|
hidden={i.official}
|
||||||
|
title={
|
||||||
|
i.verified
|
||||||
|
? 'This game is verified to be safe'
|
||||||
|
: 'This game is not verified to be save. Proceed with caution.'
|
||||||
|
}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={i.verified ? faShieldHalved : faWarning}
|
icon={i.verified ? faShieldHalved : faWarning}
|
||||||
@@ -123,16 +126,12 @@ export default function Installs () {
|
|||||||
<p>{i.verified ? 'Verified' : 'Unverified'}</p>
|
<p>{i.verified ? 'Verified' : 'Unverified'}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className='flex flex-row items-center gap-2'
|
|
||||||
hidden={!normalConfig?.settings.useLegacyInteractButtons}
|
|
||||||
>
|
|
||||||
<Link
|
<Link
|
||||||
className={`button ${
|
className='button absolute right-0 bottom-0'
|
||||||
hoveredIds.includes(i.id) ? 'btntheme3' : 'btntheme2'
|
|
||||||
}`}
|
|
||||||
href={'/game?id=' + i.id}
|
href={'/game?id=' + i.id}
|
||||||
|
hidden={!normalConfig?.settings.useLegacyInteractButtons}
|
||||||
|
title='Click to view game installs'
|
||||||
>
|
>
|
||||||
Installs
|
Installs
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Setting } from '../componets/Setting'
|
|||||||
import { writeNormalConfig } from '../util/BazookaManager'
|
import { writeNormalConfig } from '../util/BazookaManager'
|
||||||
import { useGlobal } from '../GlobalProvider'
|
import { useGlobal } from '../GlobalProvider'
|
||||||
import { copyToClipboard } from '../util/Clipboard'
|
import { copyToClipboard } from '../util/Clipboard'
|
||||||
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
|
|
||||||
export default function Settings () {
|
export default function Settings () {
|
||||||
const [allowNotifications, setAllowNotifications] = useState(false)
|
const [allowNotifications, setAllowNotifications] = useState(false)
|
||||||
@@ -12,6 +13,8 @@ export default function Settings () {
|
|||||||
useState(false)
|
useState(false)
|
||||||
const [useLegacyInteractButtons, setUseLegacyInteractButtons] =
|
const [useLegacyInteractButtons, setUseLegacyInteractButtons] =
|
||||||
useState(false)
|
useState(false)
|
||||||
|
const [useWineOnUnixWhenNeeded, setUseWineOnUnixWhenNeeded] = useState(false)
|
||||||
|
const [wineOnUnixCommand, setWineOnUnixCommand] = useState('wine %path%')
|
||||||
const [theme, setTheme] = useState(0)
|
const [theme, setTheme] = useState(0)
|
||||||
|
|
||||||
const [loaded, setLoaded] = useState(false)
|
const [loaded, setLoaded] = useState(false)
|
||||||
@@ -27,6 +30,10 @@ export default function Settings () {
|
|||||||
setUseLegacyInteractButtons(
|
setUseLegacyInteractButtons(
|
||||||
normalConfig.settings.useLegacyInteractButtons
|
normalConfig.settings.useLegacyInteractButtons
|
||||||
)
|
)
|
||||||
|
setUseWineOnUnixWhenNeeded(
|
||||||
|
normalConfig.settings.useWineOnUnixWhenNeeded
|
||||||
|
)
|
||||||
|
setWineOnUnixCommand(normalConfig.settings.wineOnUnixCommand)
|
||||||
setTheme(normalConfig.settings.theme)
|
setTheme(normalConfig.settings.theme)
|
||||||
setLoaded(true)
|
setLoaded(true)
|
||||||
break
|
break
|
||||||
@@ -62,6 +69,7 @@ export default function Settings () {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
title='This setting does as you expect, allow the launcher to send notifications for when stuff like downloading is done.'
|
||||||
/>
|
/>
|
||||||
<Setting
|
<Setting
|
||||||
label='Always show games in sidebar'
|
label='Always show games in sidebar'
|
||||||
@@ -86,9 +94,10 @@ export default function Settings () {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
title="This setting will make it so when you are on a page like this, the games won't disappear."
|
||||||
/>
|
/>
|
||||||
<Setting
|
<Setting
|
||||||
label='Show Installs/Launch Buttons'
|
label='Show Installs/Launch/Manage Buttons'
|
||||||
value={useLegacyInteractButtons}
|
value={useLegacyInteractButtons}
|
||||||
onChange={async () => {
|
onChange={async () => {
|
||||||
while (normalConfig != null) {
|
while (normalConfig != null) {
|
||||||
@@ -110,8 +119,41 @@ export default function Settings () {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
title='Enable the legacy method of using the installs/launch/manage buttons. In the future this setting may be removed so try and get used to the new method.'
|
||||||
/>
|
/>
|
||||||
<div>
|
<Setting
|
||||||
|
label='Use wine when needed to launch games'
|
||||||
|
value={useWineOnUnixWhenNeeded}
|
||||||
|
onChange={async () => {
|
||||||
|
while (normalConfig != null) {
|
||||||
|
setUseWineOnUnixWhenNeeded(!useWineOnUnixWhenNeeded)
|
||||||
|
normalConfig.settings.useWineOnUnixWhenNeeded =
|
||||||
|
!useWineOnUnixWhenNeeded
|
||||||
|
await writeNormalConfig(normalConfig)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className={platform() == 'linux' ? '' : 'hidden'}
|
||||||
|
/>
|
||||||
|
<p hidden={!(platform() == 'linux' && useWineOnUnixWhenNeeded)}>
|
||||||
|
Wine Command:
|
||||||
|
</p>
|
||||||
|
<input
|
||||||
|
type='text'
|
||||||
|
value={wineOnUnixCommand}
|
||||||
|
onChange={async e => {
|
||||||
|
while (normalConfig != null) {
|
||||||
|
setWineOnUnixCommand(e.target.value)
|
||||||
|
normalConfig.settings.wineOnUnixCommand = e.target.value
|
||||||
|
await writeNormalConfig(normalConfig)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className={`input-field my-1 ${
|
||||||
|
platform() == 'linux' && useWineOnUnixWhenNeeded ? '' : 'hidden'
|
||||||
|
}`}
|
||||||
|
></input>
|
||||||
|
<div title='The theme you want the launcher to use.'>
|
||||||
<label className='text-lg'>Theme:</label>
|
<label className='text-lg'>Theme:</label>
|
||||||
<select
|
<select
|
||||||
className='ml-2 bg-(--col2) border border-(--col4) rounded-md'
|
className='ml-2 bg-(--col2) border border-(--col4) rounded-md'
|
||||||
@@ -143,6 +185,7 @@ export default function Settings () {
|
|||||||
<option value={2}>Green</option>
|
<option value={2}>Green</option>
|
||||||
<option value={3}>Blue</option>
|
<option value={3}>Blue</option>
|
||||||
<option value={4}>Purple</option>
|
<option value={4}>Purple</option>
|
||||||
|
<option value={5}>Mint</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -152,6 +195,7 @@ export default function Settings () {
|
|||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await copyToClipboard(`v${version}`, normalConfig)
|
await copyToClipboard(`v${version}`, normalConfig)
|
||||||
}}
|
}}
|
||||||
|
title='The current launcher version.'
|
||||||
>
|
>
|
||||||
v{version}
|
v{version}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ export interface Game {
|
|||||||
official: boolean
|
official: boolean
|
||||||
verified: boolean
|
verified: boolean
|
||||||
developer: string | null
|
developer: string | null
|
||||||
|
categoryNames: Record<string, string>
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
export interface GameVersion {
|
export interface GameVersion {
|
||||||
id: string
|
id: string
|
||||||
versionName: string
|
displayName: string
|
||||||
releaseDate: number
|
releaseDate: number
|
||||||
game: number
|
game: number
|
||||||
downloadUrl: string
|
downloadUrl: string
|
||||||
@@ -8,4 +8,8 @@ export interface GameVersion {
|
|||||||
sha512sum: string
|
sha512sum: string
|
||||||
size: number
|
size: number
|
||||||
place: number
|
place: number
|
||||||
|
changelog: string
|
||||||
|
wine: number | undefined
|
||||||
|
category: number
|
||||||
|
lastRevision: number
|
||||||
}
|
}
|
||||||
@@ -3,4 +3,5 @@ export type SettingProps = {
|
|||||||
value: boolean
|
value: boolean
|
||||||
onChange: (val: boolean) => void
|
onChange: (val: boolean) => void
|
||||||
className?: string
|
className?: string
|
||||||
|
title?: string
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,8 @@ export class SettingsType {
|
|||||||
public allowNotifications: boolean = true,
|
public allowNotifications: boolean = true,
|
||||||
public alwaysShowGamesInSidebar: boolean = true,
|
public alwaysShowGamesInSidebar: boolean = true,
|
||||||
public useLegacyInteractButtons: boolean = false,
|
public useLegacyInteractButtons: boolean = false,
|
||||||
|
public useWineOnUnixWhenNeeded: boolean = false,
|
||||||
|
public wineOnUnixCommand: string = 'wine %path%',
|
||||||
public theme: number = 0
|
public theme: number = 0
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,17 @@
|
|||||||
type VersionsConfigData = {
|
export type VersionsConfigData = {
|
||||||
version: string
|
version: string
|
||||||
list: string[]
|
list: Record<string, number>
|
||||||
timestamps: Record<string, number>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class VersionsConfig {
|
export class VersionsConfig {
|
||||||
constructor (
|
constructor (
|
||||||
public version: string,
|
public version: string,
|
||||||
public list: string[] = [],
|
public list: Record<string, number> = {}
|
||||||
public timestamps: Record<string, number> = {}
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
static import (data: VersionsConfigData) {
|
static import (data: VersionsConfigData) {
|
||||||
const cfg = new VersionsConfig(data.version)
|
const cfg = new VersionsConfig(data.version)
|
||||||
cfg.list = [...data.list]
|
cfg.list = { ...data.list }
|
||||||
cfg.timestamps = { ...data.timestamps }
|
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
readTextFile,
|
readTextFile,
|
||||||
writeFile
|
writeFile
|
||||||
} from '@tauri-apps/plugin-fs'
|
} from '@tauri-apps/plugin-fs'
|
||||||
import { VersionsConfig } from '../types/VersionsConfig'
|
import { VersionsConfig, VersionsConfigData } from '../types/VersionsConfig'
|
||||||
|
|
||||||
export async function readNormalConfig (): Promise<NormalConfig> {
|
export async function readNormalConfig (): Promise<NormalConfig> {
|
||||||
const version = await app.getVersion()
|
const version = await app.getVersion()
|
||||||
@@ -82,7 +82,19 @@ export async function readVersionsConfig (): Promise<VersionsConfig> {
|
|||||||
return new VersionsConfig(version)
|
return new VersionsConfig(version)
|
||||||
}
|
}
|
||||||
const config = await readTextFile('versions.json', options)
|
const config = await readTextFile('versions.json', options)
|
||||||
return VersionsConfig.import(JSON.parse(config))
|
const raw = JSON.parse(config)
|
||||||
|
if (raw.version && raw.list && raw.timestamps) {
|
||||||
|
raw.version = version
|
||||||
|
raw.list = raw.timestamps
|
||||||
|
delete raw.timestamps
|
||||||
|
|
||||||
|
await writeFile(
|
||||||
|
'versions.json',
|
||||||
|
new TextEncoder().encode(JSON.stringify(raw, null, 2)),
|
||||||
|
options
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return VersionsConfig.import(raw)
|
||||||
} catch {
|
} catch {
|
||||||
return new VersionsConfig(version)
|
return new VersionsConfig(version)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user