Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
82af543322
|
|||
|
dd2187b4a4
|
9
README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Berry Dash Launcher
|
||||
|
||||
> [!CAUTION]
|
||||
> This project has moved to the Lncvrt Games organization.
|
||||
> You can find the new repository [here](https://git.lncvrt.xyz/Lncvrt-Games/launcher)
|
||||
|
||||
---
|
||||
|
||||
The version launcher for Berry Dash users
|
||||
433
bun.lock
@@ -1,40 +1,37 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "lncvrt-games-launcher",
|
||||
"name": "berry-dash-launcher",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "7.2.0",
|
||||
"@fortawesome/free-brands-svg-icons": "7.2.0",
|
||||
"@fortawesome/free-solid-svg-icons": "7.2.0",
|
||||
"@fortawesome/react-fontawesome": "3.2.0",
|
||||
"@tauri-apps/api": "2.10.1",
|
||||
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
||||
"@tauri-apps/plugin-dialog": "2.6.0",
|
||||
"@tauri-apps/plugin-fs": "2.4.5",
|
||||
"@tauri-apps/plugin-notification": "2.3.3",
|
||||
"@tauri-apps/plugin-opener": "2.5.3",
|
||||
"@tauri-apps/plugin-os": "2.3.2",
|
||||
"@tauri-apps/plugin-window-state": "2.4.1",
|
||||
"axios": "1.13.5",
|
||||
"next": "16.1.6",
|
||||
"pretty-bytes": "7.1.0",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4",
|
||||
"@fortawesome/fontawesome-svg-core": "7.1.0",
|
||||
"@fortawesome/free-brands-svg-icons": "7.1.0",
|
||||
"@fortawesome/free-solid-svg-icons": "7.1.0",
|
||||
"@fortawesome/react-fontawesome": "3.1.0",
|
||||
"@tauri-apps/api": "2.8.0",
|
||||
"@tauri-apps/plugin-dialog": "2.4.0",
|
||||
"@tauri-apps/plugin-fs": "2.4.2",
|
||||
"@tauri-apps/plugin-notification": "2.3.1",
|
||||
"@tauri-apps/plugin-opener": "2.5.0",
|
||||
"@tauri-apps/plugin-os": "2.3.1",
|
||||
"axios": "1.12.2",
|
||||
"date-fns": "4.1.0",
|
||||
"next": "15.5.4",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "3.3.3",
|
||||
"@tailwindcss/postcss": "4.1.18",
|
||||
"@tauri-apps/cli": "2.10.0",
|
||||
"@eslint/eslintrc": "3.3.1",
|
||||
"@tailwindcss/postcss": "4.1.14",
|
||||
"@tauri-apps/cli": "2.8.4",
|
||||
"@types/crypto-js": "4.2.2",
|
||||
"@types/node": "25.2.3",
|
||||
"@types/react": "19.2.14",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"@types/node": "24.6.2",
|
||||
"@types/react": "19.2.0",
|
||||
"@types/react-dom": "19.2.0",
|
||||
"crypto-js": "4.2.0",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-next": "16.1.6",
|
||||
"tailwindcss": "4.1.18",
|
||||
"eslint": "9.37.0",
|
||||
"eslint-config-next": "15.5.4",
|
||||
"tailwindcss": "4.1.14",
|
||||
"typescript": "5.9.3",
|
||||
},
|
||||
},
|
||||
@@ -42,71 +39,39 @@
|
||||
"packages": {
|
||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||
|
||||
"@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
|
||||
"@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="],
|
||||
|
||||
"@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="],
|
||||
|
||||
"@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@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-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="],
|
||||
|
||||
"@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="],
|
||||
|
||||
"@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-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.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-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
|
||||
|
||||
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
|
||||
|
||||
"@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.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],
|
||||
|
||||
"@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.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="],
|
||||
|
||||
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
|
||||
|
||||
"@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.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="],
|
||||
|
||||
"@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.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/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/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="],
|
||||
|
||||
"@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="],
|
||||
"@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="],
|
||||
|
||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="],
|
||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.4.0", "", { "dependencies": { "@eslint/core": "^0.16.0" } }, "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog=="],
|
||||
|
||||
"@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
|
||||
"@eslint/core": ["@eslint/core@0.16.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q=="],
|
||||
|
||||
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.3", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ=="],
|
||||
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
|
||||
|
||||
"@eslint/js": ["@eslint/js@9.39.2", "", {}, "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA=="],
|
||||
"@eslint/js": ["@eslint/js@9.37.0", "", {}, "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg=="],
|
||||
|
||||
"@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
|
||||
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
|
||||
|
||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="],
|
||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.0", "", { "dependencies": { "@eslint/core": "^0.16.0", "levn": "^0.4.1" } }, "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A=="],
|
||||
|
||||
"@fortawesome/fontawesome-common-types": ["@fortawesome/fontawesome-common-types@7.2.0", "", {}, "sha512-IpR0bER9FY25p+e7BmFH25MZKEwFHTfRAfhOyJubgiDnoJNsSvJ7nigLraHtp4VOG/cy8D7uiV0dLkHOne5Fhw=="],
|
||||
"@fortawesome/fontawesome-common-types": ["@fortawesome/fontawesome-common-types@7.1.0", "", {}, "sha512-l/BQM7fYntsCI//du+6sEnHOP6a74UixFyOYUyz2DLMXKx+6DEhfR3F2NYGE45XH1JJuIamacb4IZs9S0ZOWLA=="],
|
||||
|
||||
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@7.2.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.2.0" } }, "sha512-6639htZMjEkwskf3J+e6/iar+4cTNM9qhoWuRfj9F3eJD6r7iCzV1SWnQr2Mdv0QT0suuqU8BoJCZUyCtP9R4Q=="],
|
||||
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@7.1.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.1.0" } }, "sha512-fNxRUk1KhjSbnbuBxlWSnBLKLBNun52ZBTcs22H/xEEzM6Ap81ZFTQ4bZBxVQGQgVY0xugKGoRcCbaKjLQ3XZA=="],
|
||||
|
||||
"@fortawesome/free-brands-svg-icons": ["@fortawesome/free-brands-svg-icons@7.2.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.2.0" } }, "sha512-VNG8xqOip1JuJcC3zsVsKRQ60oXG9+oYNDCosjoU/H9pgYmLTEwWw8pE0jhPz/JWdHeUuK6+NQ3qsM4gIbdbYQ=="],
|
||||
"@fortawesome/free-brands-svg-icons": ["@fortawesome/free-brands-svg-icons@7.1.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.1.0" } }, "sha512-9byUd9bgNfthsZAjBl6GxOu1VPHgBuRUP9juI7ZoM98h8xNPTCTagfwUFyYscdZq4Hr7gD1azMfM9s5tIWKZZA=="],
|
||||
|
||||
"@fortawesome/free-solid-svg-icons": ["@fortawesome/free-solid-svg-icons@7.2.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.2.0" } }, "sha512-YTVITFGN0/24PxzXrwqCgnyd7njDuzp5ZvaCx5nq/jg55kUYd94Nj8UTchBdBofi/L0nwRfjGOg0E41d2u9T1w=="],
|
||||
"@fortawesome/free-solid-svg-icons": ["@fortawesome/free-solid-svg-icons@7.1.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.1.0" } }, "sha512-Udu3K7SzAo9N013qt7qmm22/wo2hADdheXtBfxFTecp+ogsc0caQNRKEb7pkvvagUGOpG9wJC1ViH6WXs8oXIA=="],
|
||||
|
||||
"@fortawesome/react-fontawesome": ["@fortawesome/react-fontawesome@3.2.0", "", { "peerDependencies": { "@fortawesome/fontawesome-svg-core": "~6 || ~7", "react": "^18.0.0 || ^19.0.0" } }, "sha512-E9Gu1hqd6JussVO26EC4WqRZssXMnQr2ol7ZNWkkFOH8jZUaxDJ9Z9WF9wIVkC+kJGXUdY3tlffpDwEKfgQrQw=="],
|
||||
"@fortawesome/react-fontawesome": ["@fortawesome/react-fontawesome@3.1.0", "", { "peerDependencies": { "@fortawesome/fontawesome-svg-core": "~6 || ~7", "react": "^18.0.0 || ^19.0.0" } }, "sha512-5OUQH9aDH/xHJwnpD4J7oEdGvFGJgYnGe0UebaPIdMW9UxYC/f5jv2VjVEgnikdJN0HL8yQxp9Nq+7gqGZpIIA=="],
|
||||
|
||||
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
||||
|
||||
@@ -118,53 +83,51 @@
|
||||
|
||||
"@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="],
|
||||
|
||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
|
||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.3" }, "os": "darwin", "cpu": "arm64" }, "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA=="],
|
||||
|
||||
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="],
|
||||
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.3" }, "os": "darwin", "cpu": "x64" }, "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="],
|
||||
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="],
|
||||
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="],
|
||||
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.3", "", { "os": "linux", "cpu": "arm" }, "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="],
|
||||
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ=="],
|
||||
|
||||
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="],
|
||||
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg=="],
|
||||
|
||||
"@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="],
|
||||
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w=="],
|
||||
|
||||
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="],
|
||||
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg=="],
|
||||
|
||||
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="],
|
||||
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw=="],
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="],
|
||||
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g=="],
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="],
|
||||
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.3" }, "os": "linux", "cpu": "arm" }, "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA=="],
|
||||
|
||||
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="],
|
||||
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.3" }, "os": "linux", "cpu": "arm64" }, "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ=="],
|
||||
|
||||
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="],
|
||||
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.3" }, "os": "linux", "cpu": "ppc64" }, "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ=="],
|
||||
|
||||
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="],
|
||||
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.3" }, "os": "linux", "cpu": "s390x" }, "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw=="],
|
||||
|
||||
"@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="],
|
||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.3" }, "os": "linux", "cpu": "x64" }, "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A=="],
|
||||
|
||||
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="],
|
||||
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" }, "os": "linux", "cpu": "arm64" }, "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA=="],
|
||||
|
||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="],
|
||||
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.3" }, "os": "linux", "cpu": "x64" }, "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg=="],
|
||||
|
||||
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="],
|
||||
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.4", "", { "dependencies": { "@emnapi/runtime": "^1.5.0" }, "cpu": "none" }, "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA=="],
|
||||
|
||||
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="],
|
||||
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA=="],
|
||||
|
||||
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="],
|
||||
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw=="],
|
||||
|
||||
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="],
|
||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.4", "", { "os": "win32", "cpu": "x64" }, "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig=="],
|
||||
|
||||
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="],
|
||||
|
||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="],
|
||||
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||
|
||||
@@ -178,25 +141,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=="],
|
||||
|
||||
"@next/env": ["@next/env@16.1.6", "", {}, "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ=="],
|
||||
"@next/env": ["@next/env@15.5.4", "", {}, "sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A=="],
|
||||
|
||||
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.1.6", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ=="],
|
||||
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@15.5.4", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-SR1vhXNNg16T4zffhJ4TS7Xn7eq4NfKfcOsRwea7RIAHrjRpI9ALYbamqIJqkAhowLlERffiwk0FMvTLNdnVtw=="],
|
||||
|
||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw=="],
|
||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.5.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA=="],
|
||||
|
||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.1.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ=="],
|
||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.5.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA=="],
|
||||
|
||||
"@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-gnu": ["@next/swc-linux-arm64-gnu@15.5.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA=="],
|
||||
|
||||
"@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-arm64-musl": ["@next/swc-linux-arm64-musl@15.5.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A=="],
|
||||
|
||||
"@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-gnu": ["@next/swc-linux-x64-gnu@15.5.4", "", { "os": "linux", "cpu": "x64" }, "sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA=="],
|
||||
|
||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg=="],
|
||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.5.4", "", { "os": "linux", "cpu": "x64" }, "sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw=="],
|
||||
|
||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.1.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw=="],
|
||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.5.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA=="],
|
||||
|
||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.1.6", "", { "os": "win32", "cpu": "x64" }, "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A=="],
|
||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.5.4", "", { "os": "win32", "cpu": "x64" }, "sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg=="],
|
||||
|
||||
"@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=="],
|
||||
|
||||
@@ -208,77 +171,75 @@
|
||||
|
||||
"@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="],
|
||||
|
||||
"@rushstack/eslint-patch": ["@rushstack/eslint-patch@1.12.0", "", {}, "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw=="],
|
||||
|
||||
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
|
||||
|
||||
"@tailwindcss/node": ["@tailwindcss/node@4.1.18", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.18" } }, "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ=="],
|
||||
"@tailwindcss/node": ["@tailwindcss/node@4.1.14", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.0", "lightningcss": "1.30.1", "magic-string": "^0.30.19", "source-map-js": "^1.2.1", "tailwindcss": "4.1.14" } }, "sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw=="],
|
||||
|
||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.18", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.18", "@tailwindcss/oxide-darwin-arm64": "4.1.18", "@tailwindcss/oxide-darwin-x64": "4.1.18", "@tailwindcss/oxide-freebsd-x64": "4.1.18", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", "@tailwindcss/oxide-linux-x64-musl": "4.1.18", "@tailwindcss/oxide-wasm32-wasi": "4.1.18", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A=="],
|
||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.14", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.5.1" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.14", "@tailwindcss/oxide-darwin-arm64": "4.1.14", "@tailwindcss/oxide-darwin-x64": "4.1.14", "@tailwindcss/oxide-freebsd-x64": "4.1.14", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.14", "@tailwindcss/oxide-linux-arm64-musl": "4.1.14", "@tailwindcss/oxide-linux-x64-gnu": "4.1.14", "@tailwindcss/oxide-linux-x64-musl": "4.1.14", "@tailwindcss/oxide-wasm32-wasi": "4.1.14", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.14", "@tailwindcss/oxide-win32-x64-msvc": "4.1.14" } }, "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw=="],
|
||||
|
||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.18", "", { "os": "android", "cpu": "arm64" }, "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q=="],
|
||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.14", "", { "os": "android", "cpu": "arm64" }, "sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ=="],
|
||||
|
||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.18", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A=="],
|
||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA=="],
|
||||
|
||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.18", "", { "os": "darwin", "cpu": "x64" }, "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw=="],
|
||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw=="],
|
||||
|
||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.18", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA=="],
|
||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.14", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18", "", { "os": "linux", "cpu": "arm" }, "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA=="],
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14", "", { "os": "linux", "cpu": "arm" }, "sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw=="],
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg=="],
|
||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g=="],
|
||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.14", "", { "os": "linux", "cpu": "x64" }, "sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ=="],
|
||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.14", "", { "os": "linux", "cpu": "x64" }, "sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.18", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.0", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA=="],
|
||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.14", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.0.5", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ=="],
|
||||
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.18", "", { "os": "win32", "cpu": "arm64" }, "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA=="],
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA=="],
|
||||
|
||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.18", "", { "os": "win32", "cpu": "x64" }, "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q=="],
|
||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.14", "", { "os": "win32", "cpu": "x64" }, "sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA=="],
|
||||
|
||||
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.18", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "postcss": "^8.4.41", "tailwindcss": "4.1.18" } }, "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g=="],
|
||||
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.14", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.14", "@tailwindcss/oxide": "4.1.14", "postcss": "^8.4.41", "tailwindcss": "4.1.14" } }, "sha512-BdMjIxy7HUNThK87C7BC8I1rE8BVUsfNQSI5siQ4JK3iIa3w0XyVvVL9SXLWO//CtYTcp1v7zci0fYwJOjB+Zg=="],
|
||||
|
||||
"@tauri-apps/api": ["@tauri-apps/api@2.10.1", "", {}, "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw=="],
|
||||
"@tauri-apps/api": ["@tauri-apps/api@2.8.0", "", {}, "sha512-ga7zdhbS2GXOMTIZRT0mYjKJtR9fivsXzsyq5U3vjDL0s6DTMwYRm0UHNjzTY5dh4+LSC68Sm/7WEiimbQNYlw=="],
|
||||
|
||||
"@tauri-apps/cli": ["@tauri-apps/cli@2.10.0", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.10.0", "@tauri-apps/cli-darwin-x64": "2.10.0", "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.0", "@tauri-apps/cli-linux-arm64-gnu": "2.10.0", "@tauri-apps/cli-linux-arm64-musl": "2.10.0", "@tauri-apps/cli-linux-riscv64-gnu": "2.10.0", "@tauri-apps/cli-linux-x64-gnu": "2.10.0", "@tauri-apps/cli-linux-x64-musl": "2.10.0", "@tauri-apps/cli-win32-arm64-msvc": "2.10.0", "@tauri-apps/cli-win32-ia32-msvc": "2.10.0", "@tauri-apps/cli-win32-x64-msvc": "2.10.0" }, "bin": { "tauri": "tauri.js" } }, "sha512-ZwT0T+7bw4+DPCSWzmviwq5XbXlM0cNoleDKOYPFYqcZqeKY31KlpoMW/MOON/tOFBPgi31a2v3w9gliqwL2+Q=="],
|
||||
"@tauri-apps/cli": ["@tauri-apps/cli@2.8.4", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.8.4", "@tauri-apps/cli-darwin-x64": "2.8.4", "@tauri-apps/cli-linux-arm-gnueabihf": "2.8.4", "@tauri-apps/cli-linux-arm64-gnu": "2.8.4", "@tauri-apps/cli-linux-arm64-musl": "2.8.4", "@tauri-apps/cli-linux-riscv64-gnu": "2.8.4", "@tauri-apps/cli-linux-x64-gnu": "2.8.4", "@tauri-apps/cli-linux-x64-musl": "2.8.4", "@tauri-apps/cli-win32-arm64-msvc": "2.8.4", "@tauri-apps/cli-win32-ia32-msvc": "2.8.4", "@tauri-apps/cli-win32-x64-msvc": "2.8.4" }, "bin": { "tauri": "tauri.js" } }, "sha512-ejUZBzuQRcjFV+v/gdj/DcbyX/6T4unZQjMSBZwLzP/CymEjKcc2+Fc8xTORThebHDUvqoXMdsCZt8r+hyN15g=="],
|
||||
|
||||
"@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.10.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-avqHD4HRjrMamE/7R/kzJPcAJnZs0IIS+1nkDP5b+TNBn3py7N2aIo9LIpy+VQq0AkN8G5dDpZtOOBkmWt/zjA=="],
|
||||
"@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.8.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BKu8HRkYV01SMTa7r4fLx+wjgtRK8Vep7lmBdHDioP6b8XH3q2KgsAyPWfEZaZIkZ2LY4SqqGARaE9oilNe0oA=="],
|
||||
|
||||
"@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.10.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-keDmlvJRStzVFjZTd0xYkBONLtgBC9eMTpmXnBXzsHuawV2q9PvDo2x6D5mhuoMVrJ9QWjgaPKBBCFks4dK71Q=="],
|
||||
"@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.8.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-imb9PfSd/7G6VAO7v1bQ2A3ZH4NOCbhGJFLchxzepGcXf9NKkfun157JH9mko29K6sqAwuJ88qtzbKCbWJTH9g=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.10.0", "", { "os": "linux", "cpu": "arm" }, "sha512-e5u0VfLZsMAC9iHaOEANumgl6lfnJx0Dtjkd8IJpysZ8jp0tJ6wrIkto2OzQgzcYyRCKgX72aKE0PFgZputA8g=="],
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.8.4", "", { "os": "linux", "cpu": "arm" }, "sha512-Ml215UnDdl7/fpOrF1CNovym/KjtUbCuPgrcZ4IhqUCnhZdXuphud/JT3E8X97Y03TZ40Sjz8raXYI2ET0exzw=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.10.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-YrYYk2dfmBs5m+OIMCrb+JH/oo+4FtlpcrTCgiFYc7vcs6m3QDd1TTyWu0u01ewsCtK2kOdluhr/zKku+KP7HA=="],
|
||||
"@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.8.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-pbcgBpMyI90C83CxE5REZ9ODyIlmmAPkkJXtV398X3SgZEIYy5TACYqlyyv2z5yKgD8F8WH4/2fek7+jH+ZXAw=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.10.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-GUoPdVJmrJRIXFfW3Rkt+eGK9ygOdyISACZfC/bCSfOnGt8kNdQIQr5WRH9QUaTVFIwxMlQyV3m+yXYP+xhSVA=="],
|
||||
"@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.8.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-zumFeaU1Ws5Ay872FTyIm7z8kfzEHu8NcIn8M6TxbJs0a7GRV21KBdpW1zNj2qy7HynnpQCqjAYXTUUmm9JAOw=="],
|
||||
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.10.0", "", { "os": "linux", "cpu": "none" }, "sha512-JO7s3TlSxshwsoKNCDkyvsx5gw2QAs/Y2GbR5UE2d5kkU138ATKoPOtxn8G1fFT1aDW4LH0rYAAfBpGkDyJJnw=="],
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.8.4", "", { "os": "linux", "cpu": "none" }, "sha512-qiqbB3Zz6IyO201f+1ojxLj65WYj8mixL5cOMo63nlg8CIzsP23cPYUrx1YaDPsCLszKZo7tVs14pc7BWf+/aQ=="],
|
||||
|
||||
"@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.10.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Uvh4SUUp4A6DVRSMWjelww0GnZI3PlVy7VS+DRF5napKuIehVjGl9XD0uKoCoxwAQBLctvipyEK+pDXpJeoHng=="],
|
||||
"@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.8.4", "", { "os": "linux", "cpu": "x64" }, "sha512-TaqaDd9Oy6k45Hotx3pOf+pkbsxLaApv4rGd9mLuRM1k6YS/aw81YrsMryYPThrxrScEIUcmNIHaHsLiU4GMkw=="],
|
||||
|
||||
"@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.10.0", "", { "os": "linux", "cpu": "x64" }, "sha512-AP0KRK6bJuTpQ8kMNWvhIpKUkQJfcPFeba7QshOQZjJ8wOS6emwTN4K5g/d3AbCMo0RRdnZWwu67MlmtJyxC1Q=="],
|
||||
"@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.8.4", "", { "os": "linux", "cpu": "x64" }, "sha512-ot9STAwyezN8w+bBHZ+bqSQIJ0qPZFlz/AyscpGqB/JnJQVDFQcRDmUPFEaAtt2UUHSWzN3GoTJ5ypqLBp2WQA=="],
|
||||
|
||||
"@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.10.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-97DXVU3dJystrq7W41IX+82JEorLNY+3+ECYxvXWqkq7DBN6FsA08x/EFGE8N/b0LTOui9X2dvpGGoeZKKV08g=="],
|
||||
"@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.8.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-+2aJ/g90dhLiOLFSD1PbElXX3SoMdpO7HFPAZB+xot3CWlAZD1tReUFy7xe0L5GAR16ZmrxpIDM9v9gn5xRy/w=="],
|
||||
|
||||
"@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.10.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-EHyQ1iwrWy1CwMalEm9z2a6L5isQ121pe7FcA2xe4VWMJp+GHSDDGvbTv/OPdkt2Lyr7DAZBpZHM6nvlHXEc4A=="],
|
||||
"@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.8.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-yj7WDxkL1t9Uzr2gufQ1Hl7hrHuFKTNEOyascbc109EoiAqCp0tgZ2IykQqOZmZOHU884UAWI1pVMqBhS/BfhA=="],
|
||||
|
||||
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.10.0", "", { "os": "win32", "cpu": "x64" }, "sha512-NTpyQxkpzGmU6ceWBTY2xRIEaS0ZLbVx1HE1zTA3TY/pV3+cPoPPOs+7YScr4IMzXMtOw7tLw5LEXo5oIG3qaQ=="],
|
||||
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.8.4", "", { "os": "win32", "cpu": "x64" }, "sha512-XuvGB4ehBdd7QhMZ9qbj/8icGEatDuBNxyYHbLKsTYh90ggUlPa/AtaqcC1Fo69lGkTmq9BOKrs1aWSi7xDonA=="],
|
||||
|
||||
"@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.0", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-OvXkrEBfWwtd8tzVCEXIvRfNEX87qs2jv6SqmVPiHcJjBhSF/GUvjqUNIDmKByb5N8nvDqVUM7+g1sXwdC/S9w=="],
|
||||
|
||||
"@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.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-YGhmYuTgXGsi6AjoV+5mh2NvicgWBfVJHHheuck6oHD+HC9bVWPaHvCP0/Aw4pHDejwrvT8hE3+zZAaWf+hrig=="],
|
||||
|
||||
"@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.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-7gqgfANSREKhh35fY1L4j3TUjUdePmU735FYDqRGeIf8nMXWpcx6j4FhN9/4nYz+m0mv79DCTPLqIPTySggGgg=="],
|
||||
|
||||
"@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.0", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-B0LShOYae4CZjN8leiNDbnfjSrTwoZakqKaWpfoH6nXiJwt6Rgj6RnVIffG3DoJiKsffRhMkjmBV9VeilSb4TA=="],
|
||||
|
||||
"@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-window-state": ["@tauri-apps/plugin-window-state@2.4.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-OuvdrzyY8Q5Dbzpj+GcrnV1iCeoZbcFdzMjanZMMcAEUNy/6PH5pxZPXpaZLOR7whlzXiuzx0L9EKZbH7zpdRw=="],
|
||||
"@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.3.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ty5V8XDUIFbSnrk3zsFoP3kzN+vAufYzalJSlmrVhQTImIZa1aL1a03bOaP2vuBvfR+WDRC6NgV2xBl8G07d+w=="],
|
||||
|
||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||
|
||||
@@ -290,31 +251,31 @@
|
||||
|
||||
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
|
||||
|
||||
"@types/node": ["@types/node@25.2.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ=="],
|
||||
"@types/node": ["@types/node@24.6.2", "", { "dependencies": { "undici-types": "~7.13.0" } }, "sha512-d2L25Y4j+W3ZlNAeMKcy7yDsK425ibcAOO2t7aPTz6gNMH0z2GThtwENCDc0d/Pw9wgyRqE5Px1wkV7naz8ang=="],
|
||||
|
||||
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||
"@types/react": ["@types/react@19.2.0", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-1LOH8xovvsKsCBq1wnT4ntDUdCJKmnEakhsuoUSy6ExlHCkGP2hqnatagYTgFk6oeL0VU31u7SNjunPN+GchtA=="],
|
||||
|
||||
"@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.0", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-brtBs0MnE9SMx7px208g39lRmC5uHZs96caOJfTjFcYSLHNamvaSMfJNagChVNkup2SdtOxKX1FDBkRSJe1ZAg=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.55.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.55.0", "@typescript-eslint/type-utils": "8.55.0", "@typescript-eslint/utils": "8.55.0", "@typescript-eslint/visitor-keys": "8.55.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.55.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ=="],
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.44.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.44.0", "@typescript-eslint/type-utils": "8.44.0", "@typescript-eslint/utils": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.44.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-EGDAOGX+uwwekcS0iyxVDmRV9HX6FLSM5kzrAToLTsr9OWCIKG/y3lQheCq18yZ5Xh78rRKJiEpP0ZaCs4ryOQ=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.55.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.55.0", "@typescript-eslint/types": "8.55.0", "@typescript-eslint/typescript-estree": "8.55.0", "@typescript-eslint/visitor-keys": "8.55.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw=="],
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.44.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.44.0", "@typescript-eslint/types": "8.44.0", "@typescript-eslint/typescript-estree": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-VGMpFQGUQWYT9LfnPcX8ouFojyrZ/2w3K5BucvxL/spdNehccKhB4jUyB1yBCXpr2XFm0jkECxgrpXBW2ipoAw=="],
|
||||
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.55.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.55.0", "@typescript-eslint/types": "^8.55.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ=="],
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.44.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.44.0", "@typescript-eslint/types": "^8.44.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA=="],
|
||||
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.55.0", "", { "dependencies": { "@typescript-eslint/types": "8.55.0", "@typescript-eslint/visitor-keys": "8.55.0" } }, "sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q=="],
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0" } }, "sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA=="],
|
||||
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.55.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q=="],
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.44.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ=="],
|
||||
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.55.0", "", { "dependencies": { "@typescript-eslint/types": "8.55.0", "@typescript-eslint/typescript-estree": "8.55.0", "@typescript-eslint/utils": "8.55.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-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g=="],
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "@typescript-eslint/typescript-estree": "8.44.0", "@typescript-eslint/utils": "8.44.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-9cwsoSxJ8Sak67Be/hD2RNt/fsqmWnNE1iHohG8lxqLSNY8xNfyY7wloo5zpW3Nu9hxVgURevqfcH6vvKCt6yg=="],
|
||||
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.55.0", "", {}, "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w=="],
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.44.0", "", {}, "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.55.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.55.0", "@typescript-eslint/tsconfig-utils": "8.55.0", "@typescript-eslint/types": "8.55.0", "@typescript-eslint/visitor-keys": "8.55.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-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw=="],
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.44.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.44.0", "@typescript-eslint/tsconfig-utils": "8.44.0", "@typescript-eslint/types": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.55.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.55.0", "@typescript-eslint/types": "8.55.0", "@typescript-eslint/typescript-estree": "8.55.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow=="],
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.44.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.44.0", "@typescript-eslint/types": "8.44.0", "@typescript-eslint/typescript-estree": "8.44.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-nktOlVcg3ALo0mYlV+L7sWUD58KG4CMj1rb2HUVOO4aL3K/6wcD+NERqd0rrA5Vg06b42YhF6cFxeixsp9Riqg=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.55.0", "", { "dependencies": { "@typescript-eslint/types": "8.55.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA=="],
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw=="],
|
||||
|
||||
"@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="],
|
||||
|
||||
@@ -390,22 +351,18 @@
|
||||
|
||||
"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.1", "", {}, "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A=="],
|
||||
"axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="],
|
||||
|
||||
"axios": ["axios@1.13.5", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q=="],
|
||||
"axios": ["axios@1.12.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw=="],
|
||||
|
||||
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.19", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
||||
|
||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||
|
||||
"browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
|
||||
|
||||
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
|
||||
|
||||
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||
@@ -414,10 +371,12 @@
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001769", "", {}, "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg=="],
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001743", "", {}, "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw=="],
|
||||
|
||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
|
||||
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
||||
|
||||
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
@@ -428,13 +387,11 @@
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"crypto-js": ["crypto-js@4.2.0", "", {}, "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="],
|
||||
|
||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
|
||||
"damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="],
|
||||
|
||||
@@ -444,6 +401,8 @@
|
||||
|
||||
"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=="],
|
||||
|
||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||
@@ -454,25 +413,23 @@
|
||||
|
||||
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
"detect-libc": ["detect-libc@2.1.0", "", {}, "sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg=="],
|
||||
|
||||
"doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
|
||||
|
||||
"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.286", "", {}, "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
"enhanced-resolve": ["enhanced-resolve@5.19.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg=="],
|
||||
"enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
|
||||
|
||||
"es-abstract": ["es-abstract@1.24.1", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw=="],
|
||||
"es-abstract": ["es-abstract@1.24.0", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg=="],
|
||||
|
||||
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||
|
||||
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||
|
||||
"es-iterator-helpers": ["es-iterator-helpers@1.2.2", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.1", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "safe-array-concat": "^1.1.3" } }, "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w=="],
|
||||
"es-iterator-helpers": ["es-iterator-helpers@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.4", "safe-array-concat": "^1.1.3" } }, "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w=="],
|
||||
|
||||
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||
|
||||
@@ -482,13 +439,11 @@
|
||||
|
||||
"es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
|
||||
|
||||
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||
|
||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||
|
||||
"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.37.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.4.0", "@eslint/core": "^0.16.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.37.0", "@eslint/plugin-kit": "^0.4.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "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-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig=="],
|
||||
|
||||
"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-config-next": ["eslint-config-next@15.5.4", "", { "dependencies": { "@next/eslint-plugin-next": "15.5.4", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^5.0.0" }, "peerDependencies": { "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", "typescript": ">=3.3.1" }, "optionalPeers": ["typescript"] }, "sha512-BzgVVuT3kfJes8i2GHenC1SRJ+W3BTML11lAOYFOOPzrk2xp66jBOAGEFRw+3LkYCln5UzvFsLhojrshb5Zfaw=="],
|
||||
|
||||
"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=="],
|
||||
|
||||
@@ -502,7 +457,7 @@
|
||||
|
||||
"eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="],
|
||||
|
||||
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.0.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA=="],
|
||||
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
|
||||
|
||||
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
|
||||
|
||||
@@ -510,7 +465,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=="],
|
||||
|
||||
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
|
||||
"esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
|
||||
|
||||
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
||||
|
||||
@@ -526,7 +481,7 @@
|
||||
|
||||
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
|
||||
|
||||
"fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
|
||||
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
|
||||
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
@@ -544,7 +499,7 @@
|
||||
|
||||
"for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
|
||||
|
||||
"form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
|
||||
"form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
|
||||
@@ -552,17 +507,13 @@
|
||||
|
||||
"functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
|
||||
|
||||
"generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="],
|
||||
|
||||
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
|
||||
|
||||
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||
|
||||
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||
|
||||
"get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
|
||||
|
||||
"get-tsconfig": ["get-tsconfig@4.13.6", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw=="],
|
||||
"get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="],
|
||||
|
||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||
|
||||
@@ -574,6 +525,8 @@
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
|
||||
|
||||
"has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
|
||||
|
||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||
@@ -588,10 +541,6 @@
|
||||
|
||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||
|
||||
"hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
||||
|
||||
"hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
|
||||
|
||||
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||
|
||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||
@@ -622,7 +571,7 @@
|
||||
|
||||
"is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="],
|
||||
|
||||
"is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="],
|
||||
"is-generator-function": ["is-generator-function@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ=="],
|
||||
|
||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
||||
@@ -662,9 +611,7 @@
|
||||
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
|
||||
|
||||
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
|
||||
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
||||
|
||||
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
|
||||
|
||||
@@ -684,29 +631,27 @@
|
||||
|
||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||
|
||||
"lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],
|
||||
"lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
|
||||
|
||||
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
|
||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
|
||||
|
||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="],
|
||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
|
||||
|
||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="],
|
||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
|
||||
|
||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="],
|
||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
|
||||
|
||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="],
|
||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
|
||||
|
||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="],
|
||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
|
||||
|
||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="],
|
||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
|
||||
|
||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="],
|
||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
|
||||
|
||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="],
|
||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
|
||||
|
||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="],
|
||||
|
||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
|
||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
|
||||
|
||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||
|
||||
@@ -714,9 +659,7 @@
|
||||
|
||||
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||
|
||||
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||
|
||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||
"magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="],
|
||||
|
||||
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||
|
||||
@@ -732,17 +675,19 @@
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
||||
|
||||
"minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||
|
||||
"napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="],
|
||||
"napi-postinstall": ["napi-postinstall@0.3.3", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow=="],
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"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=="],
|
||||
"next": ["next@15.5.4", "", { "dependencies": { "@next/env": "15.5.4", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.5.4", "@next/swc-darwin-x64": "15.5.4", "@next/swc-linux-arm64-gnu": "15.5.4", "@next/swc-linux-arm64-musl": "15.5.4", "@next/swc-linux-x64-gnu": "15.5.4", "@next/swc-linux-x64-musl": "15.5.4", "@next/swc-win32-arm64-msvc": "15.5.4", "@next/swc-win32-x64-msvc": "15.5.4", "sharp": "^0.34.3" }, "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-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA=="],
|
||||
|
||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||
|
||||
@@ -786,8 +731,6 @@
|
||||
|
||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||
|
||||
"pretty-bytes": ["pretty-bytes@7.1.0", "", {}, "sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw=="],
|
||||
|
||||
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||
|
||||
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
||||
@@ -796,9 +739,9 @@
|
||||
|
||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||
|
||||
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
||||
"react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="],
|
||||
|
||||
"react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
|
||||
"react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="],
|
||||
|
||||
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||
|
||||
@@ -806,7 +749,7 @@
|
||||
|
||||
"regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
|
||||
|
||||
"resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
|
||||
"resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="],
|
||||
|
||||
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
@@ -832,7 +775,7 @@
|
||||
|
||||
"set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="],
|
||||
|
||||
"sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
|
||||
"sharp": ["sharp@0.34.4", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.0", "semver": "^7.7.2" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.4", "@img/sharp-darwin-x64": "0.34.4", "@img/sharp-libvips-darwin-arm64": "1.2.3", "@img/sharp-libvips-darwin-x64": "1.2.3", "@img/sharp-libvips-linux-arm": "1.2.3", "@img/sharp-libvips-linux-arm64": "1.2.3", "@img/sharp-libvips-linux-ppc64": "1.2.3", "@img/sharp-libvips-linux-s390x": "1.2.3", "@img/sharp-libvips-linux-x64": "1.2.3", "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", "@img/sharp-libvips-linuxmusl-x64": "1.2.3", "@img/sharp-linux-arm": "0.34.4", "@img/sharp-linux-arm64": "0.34.4", "@img/sharp-linux-ppc64": "0.34.4", "@img/sharp-linux-s390x": "0.34.4", "@img/sharp-linux-x64": "0.34.4", "@img/sharp-linuxmusl-arm64": "0.34.4", "@img/sharp-linuxmusl-x64": "0.34.4", "@img/sharp-wasm32": "0.34.4", "@img/sharp-win32-arm64": "0.34.4", "@img/sharp-win32-ia32": "0.34.4", "@img/sharp-win32-x64": "0.34.4" } }, "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
@@ -874,15 +817,17 @@
|
||||
|
||||
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||
|
||||
"tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="],
|
||||
"tailwindcss": ["tailwindcss@4.1.14", "", {}, "sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA=="],
|
||||
|
||||
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
|
||||
"tapable": ["tapable@2.2.3", "", {}, "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg=="],
|
||||
|
||||
"tar": ["tar@7.5.1", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
||||
"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.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="],
|
||||
"ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
|
||||
|
||||
"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,16 +845,12 @@
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"typescript-eslint": ["typescript-eslint@8.55.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.55.0", "@typescript-eslint/parser": "8.55.0", "@typescript-eslint/typescript-estree": "8.55.0", "@typescript-eslint/utils": "8.55.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw=="],
|
||||
|
||||
"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=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
"undici-types": ["undici-types@7.13.0", "", {}, "sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ=="],
|
||||
|
||||
"unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="],
|
||||
|
||||
"update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
|
||||
|
||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
@@ -920,29 +861,23 @@
|
||||
|
||||
"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.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=="],
|
||||
"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=="],
|
||||
|
||||
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
||||
|
||||
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
||||
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
||||
|
||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
"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=="],
|
||||
|
||||
"@babel/core/json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
||||
|
||||
"@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.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/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="],
|
||||
|
||||
"@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/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="],
|
||||
|
||||
"@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.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/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.6", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-DXj75ewm11LIWUk198QSKUTxjyRjsBwk09MuMk5DGK+GDUtyPhhEHOGP/Xwwj3DjQXXkivoBirmOnKrLfc0+9g=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||
|
||||
@@ -950,11 +885,11 @@
|
||||
|
||||
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||
|
||||
"eslint-config-next/globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="],
|
||||
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||
|
||||
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
@@ -966,13 +901,15 @@
|
||||
|
||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"is-bun-module/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||
"is-bun-module/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
||||
|
||||
"sharp/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||
"sharp/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
}
|
||||
|
||||
25
eslint.config.mjs
Normal file
@@ -0,0 +1,25 @@
|
||||
import { dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { FlatCompat } from "@eslint/eslintrc";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
});
|
||||
|
||||
const eslintConfig = [
|
||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
||||
{
|
||||
ignores: [
|
||||
"node_modules/**",
|
||||
".next/**",
|
||||
"out/**",
|
||||
"build/**",
|
||||
"next-env.d.ts",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default eslintConfig;
|
||||
@@ -1,19 +0,0 @@
|
||||
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||
import nextVitals from 'eslint-config-next/core-web-vitals'
|
||||
import nextTs from 'eslint-config-next/typescript'
|
||||
|
||||
const eslintConfig = defineConfig([
|
||||
...nextVitals,
|
||||
...nextTs,
|
||||
// Override default ignores of eslint-config-next.
|
||||
globalIgnores([
|
||||
// Default ignores of eslint-config-next:
|
||||
'.next/**',
|
||||
'out/**',
|
||||
'build/**',
|
||||
'next-env.d.ts',
|
||||
'src-tauri/**'
|
||||
])
|
||||
])
|
||||
|
||||
export default eslintConfig
|
||||
58
package.json
@@ -1,46 +1,44 @@
|
||||
{
|
||||
"name": "lncvrt-games-launcher",
|
||||
"name": "berry-dash-launcher",
|
||||
"private": true,
|
||||
"version": "1.6.1",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint",
|
||||
"lint": "next lint",
|
||||
"tauri": "tauri"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "7.2.0",
|
||||
"@fortawesome/free-brands-svg-icons": "7.2.0",
|
||||
"@fortawesome/free-solid-svg-icons": "7.2.0",
|
||||
"@fortawesome/react-fontawesome": "3.2.0",
|
||||
"@tauri-apps/api": "2.10.1",
|
||||
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
||||
"@tauri-apps/plugin-dialog": "2.6.0",
|
||||
"@tauri-apps/plugin-fs": "2.4.5",
|
||||
"@tauri-apps/plugin-notification": "2.3.3",
|
||||
"@tauri-apps/plugin-opener": "2.5.3",
|
||||
"@tauri-apps/plugin-os": "2.3.2",
|
||||
"@tauri-apps/plugin-window-state": "2.4.1",
|
||||
"axios": "1.13.5",
|
||||
"next": "16.1.6",
|
||||
"pretty-bytes": "7.1.0",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4"
|
||||
"@tauri-apps/api": "2.8.0",
|
||||
"@tauri-apps/plugin-dialog": "2.4.0",
|
||||
"@tauri-apps/plugin-fs": "2.4.2",
|
||||
"@tauri-apps/plugin-notification": "2.3.1",
|
||||
"@tauri-apps/plugin-opener": "2.5.0",
|
||||
"@tauri-apps/plugin-os": "2.3.1",
|
||||
"axios": "1.12.2",
|
||||
"date-fns": "4.1.0",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
"next": "15.5.4",
|
||||
"@fortawesome/fontawesome-svg-core": "7.1.0",
|
||||
"@fortawesome/free-brands-svg-icons": "7.1.0",
|
||||
"@fortawesome/free-solid-svg-icons": "7.1.0",
|
||||
"@fortawesome/react-fontawesome": "3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "3.3.3",
|
||||
"@tailwindcss/postcss": "4.1.18",
|
||||
"@tauri-apps/cli": "2.10.0",
|
||||
"@tailwindcss/postcss": "4.1.14",
|
||||
"@tauri-apps/cli": "2.8.4",
|
||||
"@types/crypto-js": "4.2.2",
|
||||
"@types/node": "25.2.3",
|
||||
"@types/react": "19.2.14",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"@types/react": "19.2.0",
|
||||
"@types/react-dom": "19.2.0",
|
||||
"crypto-js": "4.2.0",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-next": "16.1.6",
|
||||
"tailwindcss": "4.1.18",
|
||||
"typescript": "5.9.3"
|
||||
"@types/node": "24.6.2",
|
||||
"tailwindcss": "4.1.14",
|
||||
"typescript": "5.9.3",
|
||||
"eslint": "9.37.0",
|
||||
"eslint-config-next": "15.5.4",
|
||||
"@eslint/eslintrc": "3.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
const config = {
|
||||
plugins: {
|
||||
'@tailwindcss/postcss': {}
|
||||
}
|
||||
}
|
||||
plugins: ["@tailwindcss/postcss"],
|
||||
};
|
||||
|
||||
export default config
|
||||
export default config;
|
||||
|
||||
@@ -1,41 +1,37 @@
|
||||
[package]
|
||||
name = "lncvrt-games-launcher"
|
||||
version = "1.6.1"
|
||||
name = "berry-dash-launcher"
|
||||
version = "1.1.0"
|
||||
authors = ["Lncvrt"]
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
name = "lncvrt_games_launcher_lib"
|
||||
name = "berry_dash_launcher_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.5.5", features = [] }
|
||||
tauri-build = { version = "2.4.1", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.10.2", features = ["macos-private-api"] }
|
||||
tauri-plugin-opener = "2.5.3"
|
||||
tauri = { version = "2.8.5", features = ["macos-private-api"] }
|
||||
tauri-plugin-opener = "2.5.0"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.149"
|
||||
tauri-plugin-os = "2.3.2"
|
||||
reqwest = { version = "0.13.2", default-features = false, features = ["stream", "rustls"] }
|
||||
tokio = "1.49.0"
|
||||
serde_json = "1.0.145"
|
||||
tauri-plugin-os = "2.3.1"
|
||||
reqwest = { version = "0.12.23", default-features = false, features = ["stream", "rustls-tls"] }
|
||||
tokio = "1.47.1"
|
||||
futures-util = { version = "0.3.31", features = ["io"] }
|
||||
tauri-plugin-decorum = "1.1.1"
|
||||
tauri-plugin-fs = "2.4.5"
|
||||
zip = "8.0.0"
|
||||
libc = "0.2.182"
|
||||
tauri-plugin-dialog = "2.6.0"
|
||||
tauri-plugin-notification = "2.3.3"
|
||||
sysinfo = "0.38.1"
|
||||
sha2 = "0.10.9"
|
||||
tauri-plugin-clipboard-manager = "2.3.2"
|
||||
tauri-plugin-prevent-default = "4.0.3"
|
||||
tauri-plugin-fs = "2.4.2"
|
||||
zip = "5.1.1"
|
||||
libc = "0.2.176"
|
||||
tauri-plugin-dialog = "2.4.0"
|
||||
tauri-plugin-notification = "2.3.1"
|
||||
sysinfo = "0.37.2"
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
shlex = "1.3.0"
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-single-instance = "2.4.0"
|
||||
tauri-plugin-window-state = "2.4.1"
|
||||
tauri-plugin-single-instance = "2.3.4"
|
||||
|
||||
|
||||
|
||||
10
src-tauri/Info.plist
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>Berry Dash Launcher</string>
|
||||
<key>CFBundleIconName</key>
|
||||
<string>Berry Dash Launcher</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -21,23 +21,9 @@
|
||||
"core:window:allow-toggle-maximize",
|
||||
"decorum:allow-show-snap-overlay",
|
||||
"fs:default",
|
||||
"dialog:default",
|
||||
"notification:default",
|
||||
"clipboard-manager:default",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"fs:allow-applocaldata-read",
|
||||
"fs:allow-applocaldata-write",
|
||||
{
|
||||
"identifier": "fs:scope",
|
||||
"allow": [
|
||||
{ "path": "$APPLOCALDATA/game/**" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "opener:allow-open-path",
|
||||
"allow": [
|
||||
{ "path": "$APPLOCALDATA/game/**" }
|
||||
]
|
||||
}
|
||||
"dialog:default",
|
||||
"notification:default"
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"identifier": "desktop-capability",
|
||||
"platforms": [
|
||||
"macOS",
|
||||
"windows",
|
||||
"linux"
|
||||
],
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"window-state:default"
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 249 KiB After Width: | Height: | Size: 88 KiB |
BIN
src-tauri/mac-resources/Assets.car
Normal file
BIN
src-tauri/mac-resources/Berry Dash Launcher.icns
Normal file
8
src-tauri/src/keys.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
pub struct Keys;
|
||||
|
||||
impl Keys {
|
||||
pub const SERVER_RECEIVE_TRANSFER_KEY: &str = "";
|
||||
pub const SERVER_SEND_TRANSFER_KEY: &str = "";
|
||||
pub const CONFIG_ENCRYPTION_KEY: &str = "";
|
||||
pub const VERSIONS_ENCRYPTION_KEY: &str = "";
|
||||
}
|
||||
@@ -1,128 +1,62 @@
|
||||
mod keys;
|
||||
|
||||
use futures_util::stream::StreamExt;
|
||||
use sha2::{Digest, Sha512};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
use keys::Keys;
|
||||
use std::{
|
||||
fs::{File, create_dir_all},
|
||||
io::{BufReader, copy},
|
||||
io::{BufReader, Write, copy},
|
||||
path::PathBuf,
|
||||
process::Command,
|
||||
time::Duration,
|
||||
};
|
||||
use sysinfo::System;
|
||||
use tauri::{AppHandle, Emitter, Manager};
|
||||
use tauri::{AppHandle, Emitter, Manager, PhysicalSize};
|
||||
use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
|
||||
use tauri_plugin_opener::OpenerExt;
|
||||
use tauri_plugin_os::platform;
|
||||
use tauri_plugin_prevent_default::Flags;
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::{io::AsyncWriteExt, time::timeout};
|
||||
use tokio::{io::AsyncWriteExt, task::spawn_blocking, time::timeout};
|
||||
use zip::ZipArchive;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::{fs, os::unix::fs::PermissionsExt};
|
||||
#[cfg(target_os = "windows")]
|
||||
use tauri_plugin_decorum::WebviewWindowExt;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
#[allow(unused)]
|
||||
fn is_running_by_path(path: &Path) -> bool {
|
||||
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| {
|
||||
proc.exe()
|
||||
.and_then(|exe| exe.canonicalize().ok())
|
||||
.map_or(false, |exe| exe == target)
|
||||
})
|
||||
}
|
||||
|
||||
fn should_skip(name: &str) -> bool {
|
||||
name.starts_with("__MACOSX/")
|
||||
|| name == "__MACOSX"
|
||||
|| name.ends_with("/.DS_Store")
|
||||
|| name.ends_with(".DS_Store")
|
||||
}
|
||||
|
||||
async fn unzip_to_dir(zip_path: PathBuf, out_dir: PathBuf) -> String {
|
||||
let res = tauri::async_runtime::spawn_blocking(move || {
|
||||
pub async fn unzip_to_dir(zip_path: PathBuf, out_dir: PathBuf) -> zip::result::ZipResult<()> {
|
||||
spawn_blocking(move || {
|
||||
let file = File::open(zip_path)?;
|
||||
let mut archive = ZipArchive::new(BufReader::new(file))?;
|
||||
|
||||
for i in 0..archive.len() {
|
||||
let mut entry = archive.by_index(i)?;
|
||||
let name = entry.name();
|
||||
let mut file = archive.by_index(i)?;
|
||||
let outpath = out_dir.join(file.name());
|
||||
|
||||
if should_skip(name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let outpath = out_dir.join(name);
|
||||
|
||||
if entry.is_dir() {
|
||||
if file.is_dir() {
|
||||
create_dir_all(&outpath)?;
|
||||
|
||||
#[cfg(unix)]
|
||||
if let Some(mode) = entry.unix_mode() {
|
||||
std::fs::set_permissions(&outpath, std::fs::Permissions::from_mode(mode))?;
|
||||
}
|
||||
} else {
|
||||
if let Some(parent) = outpath.parent() {
|
||||
create_dir_all(parent)?;
|
||||
}
|
||||
|
||||
let mut outfile = File::create(&outpath)?;
|
||||
copy(&mut entry, &mut outfile)?;
|
||||
|
||||
#[cfg(unix)]
|
||||
if let Some(mode) = entry.unix_mode() {
|
||||
std::fs::set_permissions(&outpath, std::fs::Permissions::from_mode(mode))?;
|
||||
}
|
||||
copy(&mut file, &mut outfile)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok::<(), zip::result::ZipError>(())
|
||||
Ok(())
|
||||
})
|
||||
.await;
|
||||
|
||||
match res {
|
||||
Ok(Ok(())) => "1".into(),
|
||||
_ => "-1".into(),
|
||||
}
|
||||
.await
|
||||
.map_err(|e| zip::result::ZipError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))?
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn folder_size(app: AppHandle, version: String) -> String {
|
||||
let path = app
|
||||
.path()
|
||||
.app_local_data_dir()
|
||||
.unwrap()
|
||||
.join("game")
|
||||
.join(&version);
|
||||
fn inner(path: &Path) -> u64 {
|
||||
let mut size = 0;
|
||||
if let Ok(entries) = fs::read_dir(path) {
|
||||
for entry in entries.flatten() {
|
||||
if let Ok(metadata) = entry.metadata() {
|
||||
if metadata.is_file() {
|
||||
size += metadata.len();
|
||||
} else if metadata.is_dir() {
|
||||
size += inner(&entry.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
fn is_running_by_path(path: &PathBuf) -> bool {
|
||||
let sys = System::new_all();
|
||||
sys.processes().values().any(|proc| {
|
||||
if let Some(exe) = proc.exe() {
|
||||
exe == path
|
||||
} else {
|
||||
false
|
||||
}
|
||||
size
|
||||
}
|
||||
|
||||
let p = Path::new(&path);
|
||||
if p.exists() && p.is_dir() {
|
||||
inner(p).to_string()
|
||||
} else {
|
||||
"-1".to_string()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
@@ -132,13 +66,15 @@ async fn download(
|
||||
url: String,
|
||||
name: String,
|
||||
executable: String,
|
||||
hash: String,
|
||||
) -> String {
|
||||
) -> Result<(), String> {
|
||||
app.emit("download-started", &name).unwrap();
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let resp = match client.get(&url).send().await {
|
||||
Ok(r) => r,
|
||||
Err(_) => {
|
||||
return "-1".to_string();
|
||||
Err(e) => {
|
||||
app.emit("download-failed", &name).unwrap();
|
||||
return Err(e.to_string());
|
||||
}
|
||||
};
|
||||
let total_size = resp.content_length().unwrap_or(0);
|
||||
@@ -161,193 +97,295 @@ async fn download(
|
||||
let _ = tokio::fs::remove_dir_all(&game_path.join(name.clone())).await;
|
||||
}
|
||||
let _ = tokio::fs::create_dir_all(&game_path.join(&name)).await;
|
||||
let mut file = tokio::fs::File::create(download_part_path.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let start = Instant::now();
|
||||
let mut file = tokio::fs::File::create(download_part_path).await.unwrap();
|
||||
|
||||
while let Ok(Some(chunk_result)) = timeout(Duration::from_secs(5), stream.next()).await {
|
||||
let chunk = match chunk_result {
|
||||
Ok(c) => c,
|
||||
Err(_) => {
|
||||
return "-1".to_string();
|
||||
Err(e) => {
|
||||
app.emit("download-failed", &name).unwrap();
|
||||
return Err(e.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(_) = file.write_all(&chunk).await {
|
||||
return "-1".to_string();
|
||||
if let Err(e) = file.write_all(&chunk).await {
|
||||
app.emit("download-failed", &name).unwrap();
|
||||
return Err(e.to_string());
|
||||
}
|
||||
|
||||
downloaded += chunk.len() as u64;
|
||||
|
||||
let progress = if total_size > 0 {
|
||||
((downloaded as f64) / (total_size as f64)) * 100.0
|
||||
(downloaded * 100 / total_size) as u8
|
||||
} else {
|
||||
0.0
|
||||
0
|
||||
};
|
||||
|
||||
let elapsed_secs = start.elapsed().as_secs_f64();
|
||||
let speed = (downloaded as f64) / elapsed_secs;
|
||||
let eta_secs = if total_size > downloaded {
|
||||
((total_size - downloaded) as f64) / speed
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
app.emit(
|
||||
"download-progress",
|
||||
format!(
|
||||
"{}:{:.8}:{}:{}:{:.2}",
|
||||
&name, progress, downloaded, speed, eta_secs
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
app.emit("download-progress", format!("{}:{}", &name, progress))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if total_size > 0 && downloaded < total_size {
|
||||
return "-1".to_string();
|
||||
app.emit("download-failed", &name).unwrap();
|
||||
return Err("Download incomplete".into());
|
||||
}
|
||||
|
||||
app.emit("download-hash-checking", format!("{}", &name))
|
||||
.unwrap();
|
||||
|
||||
let download_hash = {
|
||||
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 {
|
||||
tokio::fs::remove_file(download_part_path.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
return "-1".to_string();
|
||||
}
|
||||
app.emit("download-finishing", format!("{}", &name))
|
||||
.unwrap();
|
||||
|
||||
tokio::fs::rename(download_part_path.clone(), download_zip_path.clone())
|
||||
tokio::fs::rename(
|
||||
downloads_path.join(format!("{}.part", name)),
|
||||
download_zip_path.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
unzip_to_dir(download_zip_path.clone(), game_path.join(&name))
|
||||
.await
|
||||
.unwrap();
|
||||
let unzip_res = unzip_to_dir(download_zip_path.clone(), game_path.join(&name)).await;
|
||||
.map_err(|e| e.to_string())?;
|
||||
tokio::fs::remove_file(download_zip_path.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
if unzip_res == "-1" {
|
||||
return "-1".to_string();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let executable_path = game_path.join(&name).join(&executable);
|
||||
let mut perms = fs::metadata(&executable_path).unwrap().permissions();
|
||||
perms.set_mode(0o755);
|
||||
fs::set_permissions(executable_path, perms).unwrap();
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
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 _ = Command::new("osascript")
|
||||
.arg("-e")
|
||||
.arg(format!(
|
||||
"do shell script \"chmod 755 \\\"{}\\\"\" with prompt \"Administrator is required to make Berry Dash v{} executable\" with administrator privileges",
|
||||
macos_app_path.to_string_lossy(),
|
||||
name
|
||||
))
|
||||
.spawn();
|
||||
}
|
||||
|
||||
return "1".to_string();
|
||||
app.emit("download-done", &name).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
#[tauri::command]
|
||||
fn launch_game(
|
||||
app: AppHandle,
|
||||
name: String,
|
||||
executable: String,
|
||||
display_name: String,
|
||||
use_wine: bool,
|
||||
wine_command: String,
|
||||
) {
|
||||
fn launch_game(app: AppHandle, name: String, executable: String, wine: bool, wine_command: String) {
|
||||
let game_folder = app
|
||||
.path()
|
||||
.app_local_data_dir()
|
||||
.unwrap()
|
||||
.join("game")
|
||||
.join(&name);
|
||||
if !game_folder.exists() {
|
||||
let game_path = game_folder.join(&executable);
|
||||
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;
|
||||
}
|
||||
let result = if wine && platform() == "linux" {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let wine_cmd_to_use =
|
||||
wine_command.replace("%path%", &format!("\"{}\"", game_path.to_string_lossy()));
|
||||
|
||||
let exe_path = game_folder.join(&executable);
|
||||
let parts = shlex::split(&wine_cmd_to_use).expect("failed to split command");
|
||||
let exe = &parts[0];
|
||||
let args = &parts[1..];
|
||||
|
||||
//if already running on macos, it'll auto take the user to that proccess
|
||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||
{
|
||||
use tauri_plugin_dialog::DialogExt;
|
||||
use tauri_plugin_dialog::MessageDialogKind;
|
||||
Command::new(exe)
|
||||
.args(args)
|
||||
.current_dir(&game_folder)
|
||||
.spawn()
|
||||
}
|
||||
|
||||
if !use_wine && is_running_by_path(&exe_path) {
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
Err(std::io::Error::new(std::io::ErrorKind::Other, "not linux"))
|
||||
}
|
||||
} else {
|
||||
if is_running_by_path(&game_path) {
|
||||
app.dialog()
|
||||
.message(format!(
|
||||
"{} is already running, if this doesn't seem true, try to kill the proccess.",
|
||||
display_name
|
||||
))
|
||||
.message(format!("The version {} is already running.", 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)
|
||||
if platform() == "macos" {
|
||||
Command::new("open")
|
||||
.arg(&game_path)
|
||||
.current_dir(&game_folder)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
} else {
|
||||
Command::new(&game_path).current_dir(&game_folder).spawn()
|
||||
}
|
||||
};
|
||||
|
||||
return;
|
||||
match result {
|
||||
Ok(_) => println!("Game launched successfully."),
|
||||
Err(e) => {
|
||||
app.dialog()
|
||||
.message(format!("Failed to load game:\n{}\n\nTry reinstalling the game or make a support request in the Community link on the sidebar.", e))
|
||||
.kind(MessageDialogKind::Error)
|
||||
.title("Failed to launch game")
|
||||
.show(|_| {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if platform() == "macos" {
|
||||
Command::new("open")
|
||||
.arg(&executable)
|
||||
.current_dir(&game_folder)
|
||||
.spawn()
|
||||
#[tauri::command]
|
||||
fn download_leaderboard(app: AppHandle, content: String) {
|
||||
app.dialog().file().save_file(move |file_path| {
|
||||
if let Some(path) = file_path {
|
||||
let mut path_buf = PathBuf::from(path.to_string());
|
||||
if path_buf.extension().map(|ext| ext != "csv").unwrap_or(true) {
|
||||
path_buf.set_extension("csv");
|
||||
}
|
||||
let path_str = path_buf.to_string_lossy().to_string();
|
||||
if path_str.is_empty() {
|
||||
app.dialog()
|
||||
.message("No file selected.")
|
||||
.kind(MessageDialogKind::Error)
|
||||
.title("Error")
|
||||
.show(|_| {});
|
||||
return;
|
||||
}
|
||||
let mut file = match File::create(&path_buf) {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
app.dialog()
|
||||
.message(format!("Failed to create file: {}", e))
|
||||
.kind(MessageDialogKind::Error)
|
||||
.title("Error")
|
||||
.show(|_| {});
|
||||
return;
|
||||
}
|
||||
};
|
||||
if let Err(e) = file.write_all(content.as_bytes()) {
|
||||
app.dialog()
|
||||
.message(format!("Failed to write to file: {}", e))
|
||||
.kind(MessageDialogKind::Error)
|
||||
.title("Error")
|
||||
.show(|_| {});
|
||||
} else {
|
||||
let _ = app.opener().open_path(path.to_string(), None::<&str>);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_keys_config(key: i8) -> String {
|
||||
match key {
|
||||
0 => Keys::SERVER_RECEIVE_TRANSFER_KEY.to_string(),
|
||||
1 => Keys::SERVER_SEND_TRANSFER_KEY.to_string(),
|
||||
2 => Keys::CONFIG_ENCRYPTION_KEY.to_string(),
|
||||
3 => Keys::VERSIONS_ENCRYPTION_KEY.to_string(),
|
||||
_ => "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
#[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]
|
||||
async fn open_folder(app: AppHandle, name: String) {
|
||||
let game_path = app
|
||||
.path()
|
||||
.app_local_data_dir()
|
||||
.unwrap()
|
||||
.join("game")
|
||||
.join(&name);
|
||||
if game_path.exists() {
|
||||
app.opener()
|
||||
.open_path(game_path.to_string_lossy(), None::<&str>)
|
||||
.unwrap();
|
||||
} else {
|
||||
Command::new(&exe_path)
|
||||
.current_dir(&game_folder)
|
||||
.spawn()
|
||||
.unwrap();
|
||||
app.dialog()
|
||||
.message(format!(
|
||||
"Game folder \"{}\" not found.",
|
||||
game_path.display()
|
||||
))
|
||||
.kind(MessageDialogKind::Error)
|
||||
.title("Folder not found")
|
||||
.show(|_| {});
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
#[tauri::command]
|
||||
fn fix_mac_permissions(app: AppHandle, name: String, executable: String) {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let macos_app_path = app
|
||||
.path()
|
||||
.app_local_data_dir()
|
||||
.unwrap()
|
||||
.join("game")
|
||||
.join(&name)
|
||||
.join(&executable)
|
||||
.join("Contents")
|
||||
.join("MacOS")
|
||||
.join(
|
||||
&executable
|
||||
.chars()
|
||||
.take(&executable.chars().count() - 4)
|
||||
.collect::<String>(),
|
||||
);
|
||||
let _ = Command::new("osascript")
|
||||
.arg("-e")
|
||||
.arg(format!(
|
||||
"do shell script \"chmod 755 \\\"{}\\\"\" with prompt \"Administrator is required to make Berry Dash v{} executable\" with administrator privileges",
|
||||
macos_app_path.to_string_lossy(),
|
||||
name
|
||||
))
|
||||
.spawn();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn windows_rounded_corners(app: AppHandle, enabled: bool) {
|
||||
let window = app.get_webview_window("main");
|
||||
let _ = window.clone().unwrap().set_shadow(enabled);
|
||||
let _ = window
|
||||
.clone()
|
||||
.unwrap()
|
||||
.set_size(PhysicalSize::new(1000.0, 632.0)); // Yes, this is needed.
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
#[allow(unused_variables)]
|
||||
tauri::Builder::default()
|
||||
.plugin(
|
||||
tauri_plugin_prevent_default::Builder::new()
|
||||
.with_flags(
|
||||
Flags::FIND
|
||||
| Flags::CARET_BROWSING
|
||||
| Flags::DEV_TOOLS
|
||||
| Flags::DOWNLOADS
|
||||
| Flags::FOCUS_MOVE
|
||||
| Flags::RELOAD
|
||||
| Flags::SOURCE
|
||||
| Flags::OPEN
|
||||
| Flags::PRINT
|
||||
| Flags::CONTEXT_MENU,
|
||||
)
|
||||
.build(),
|
||||
)
|
||||
.plugin(tauri_plugin_window_state::Builder::new().build())
|
||||
.plugin(tauri_plugin_clipboard_manager::init())
|
||||
.plugin(tauri_plugin_notification::init())
|
||||
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
||||
let _ = app
|
||||
@@ -360,7 +398,16 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_decorum::init())
|
||||
.plugin(tauri_plugin_os::init())
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.invoke_handler(tauri::generate_handler![download, launch_game, folder_size])
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
download,
|
||||
launch_game,
|
||||
download_leaderboard,
|
||||
get_keys_config,
|
||||
uninstall_version,
|
||||
open_folder,
|
||||
fix_mac_permissions,
|
||||
windows_rounded_corners
|
||||
])
|
||||
.setup(|app| {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
fn main() {
|
||||
lncvrt_games_launcher_lib::run()
|
||||
berry_dash_launcher_lib::run()
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Lncvrt Games Launcher",
|
||||
"version": "1.6.1",
|
||||
"identifier": "xyz.lncvrt.games-launcher",
|
||||
"productName": "Berry Dash Launcher",
|
||||
"version": "1.1.0",
|
||||
"identifier": "xyz.lncvrt.berrydash-launcher",
|
||||
"build": {
|
||||
"beforeDevCommand": "next dev --webpack",
|
||||
"beforeDevCommand": "next dev",
|
||||
"devUrl": "http://localhost:3000",
|
||||
"beforeBuildCommand": "next build",
|
||||
"frontendDist": "../out"
|
||||
@@ -12,11 +12,11 @@
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "Lncvrt Games Launcher",
|
||||
"title": "Berry Dash Launcher",
|
||||
"width": 1000,
|
||||
"height": 600,
|
||||
"minWidth": 875,
|
||||
"minHeight": 500
|
||||
"resizable": false,
|
||||
"maximizable": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Lncvrt Games Launcher",
|
||||
"version": "1.6.1",
|
||||
"identifier": "xyz.lncvrt.games-launcher",
|
||||
"productName": "Berry Dash Launcher",
|
||||
"version": "1.1.0",
|
||||
"identifier": "xyz.lncvrt.berrydash-launcher",
|
||||
"build": {
|
||||
"beforeDevCommand": "next dev --webpack",
|
||||
"beforeDevCommand": "next dev",
|
||||
"devUrl": "http://localhost:3000",
|
||||
"beforeBuildCommand": "next build",
|
||||
"frontendDist": "../out"
|
||||
@@ -12,11 +12,11 @@
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "Lncvrt Games Launcher",
|
||||
"title": "Berry Dash Launcher",
|
||||
"width": 1000,
|
||||
"height": 600,
|
||||
"minWidth": 875,
|
||||
"minHeight": 500
|
||||
"resizable": false,
|
||||
"maximizable": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
@@ -24,6 +24,18 @@
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": false
|
||||
"active": true,
|
||||
"targets": [
|
||||
"appimage",
|
||||
"deb",
|
||||
"rpm"
|
||||
],
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Lncvrt Games Launcher",
|
||||
"version": "1.6.1",
|
||||
"identifier": "xyz.lncvrt.games-launcher",
|
||||
"productName": "Berry Dash Launcher",
|
||||
"version": "1.1.0",
|
||||
"identifier": "xyz.lncvrt.berrydash-launcher",
|
||||
"build": {
|
||||
"beforeDevCommand": "next dev --webpack",
|
||||
"beforeDevCommand": "next dev",
|
||||
"devUrl": "http://localhost:3000",
|
||||
"beforeBuildCommand": "next build",
|
||||
"frontendDist": "../out"
|
||||
@@ -13,11 +13,11 @@
|
||||
"macOSPrivateApi": true,
|
||||
"windows": [
|
||||
{
|
||||
"title": "Lncvrt Games Launcher",
|
||||
"title": "Berry Dash Launcher",
|
||||
"width": 1000,
|
||||
"height": 600,
|
||||
"minWidth": 875,
|
||||
"minHeight": 500,
|
||||
"resizable": false,
|
||||
"maximizable": false,
|
||||
"titleBarStyle": "Overlay",
|
||||
"hiddenTitle": true
|
||||
}
|
||||
@@ -28,10 +28,12 @@
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": ["app"],
|
||||
"targets": "dmg",
|
||||
"macOS": {
|
||||
"minimumSystemVersion": "13.0"
|
||||
"minimumSystemVersion": "12.7.4"
|
||||
},
|
||||
"icon": ["icons/icon.icns"]
|
||||
"resources": {
|
||||
"./mac-resources/*": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Lncvrt Games Launcher",
|
||||
"version": "1.6.1",
|
||||
"identifier": "xyz.lncvrt.games-launcher",
|
||||
"productName": "Berry Dash Launcher",
|
||||
"version": "1.1.0",
|
||||
"identifier": "xyz.lncvrt.berrydash-launcher",
|
||||
"build": {
|
||||
"beforeDevCommand": "next dev --webpack",
|
||||
"beforeDevCommand": "next dev",
|
||||
"devUrl": "http://localhost:3000",
|
||||
"beforeBuildCommand": "next build",
|
||||
"frontendDist": "../out"
|
||||
@@ -13,15 +13,15 @@
|
||||
"withGlobalTauri": true,
|
||||
"windows": [
|
||||
{
|
||||
"title": "Lncvrt Games Launcher",
|
||||
"title": "Berry Dash Launcher",
|
||||
"width": 1000,
|
||||
"height": 632,
|
||||
"minWidth": 875,
|
||||
"minHeight": 532,
|
||||
"resizable": false,
|
||||
"maximizable": false,
|
||||
"titleBarStyle": "Overlay",
|
||||
"hiddenTitle": true,
|
||||
"decorations": false,
|
||||
"shadow": true
|
||||
"shadow": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
@@ -29,7 +29,14 @@
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": false,
|
||||
"icon": ["icons/icon.ico"]
|
||||
"active": true,
|
||||
"targets": "msi",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,31 @@
|
||||
'use client'
|
||||
|
||||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
ReactNode,
|
||||
Dispatch,
|
||||
SetStateAction
|
||||
} from 'react'
|
||||
import { DownloadProgress } from '@/types/DownloadProgress'
|
||||
import { VersionsConfig } from '@/types/VersionsConfig'
|
||||
import { NormalConfig } from '@/types/NormalConfig'
|
||||
import { ServerVersionsResponse } from '@/types/ServerVersionsResponse'
|
||||
import { GameVersion } from '@/types/GameVersion'
|
||||
import { Game } from '@/types/Game'
|
||||
import { createContext, useContext, ReactNode } from 'react'
|
||||
import { LauncherVersion } from './types/LauncherVersion'
|
||||
import { DownloadProgress } from './types/DownloadProgress'
|
||||
import { VersionsConfig } from './types/VersionsConfig'
|
||||
import { NormalConfig } from './types/NormalConfig'
|
||||
import { DownloadedVersion } from './types/DownloadedVersion'
|
||||
|
||||
type GlobalCtxType = {
|
||||
serverVersionList: ServerVersionsResponse | null
|
||||
selectedVersionList: string[]
|
||||
setSelectedVersionList: (value: SetStateAction<string[]>) => void
|
||||
versionList: LauncherVersion[] | null
|
||||
setVersionList: (v: LauncherVersion[] | null) => void
|
||||
selectedVersionList: LauncherVersion[]
|
||||
setSelectedVersionList: (v: LauncherVersion[]) => void
|
||||
downloadProgress: DownloadProgress[]
|
||||
setDownloadProgress: Dispatch<SetStateAction<DownloadProgress[]>>
|
||||
setDownloadProgress: (v: DownloadProgress[]) => void
|
||||
showPopup: boolean
|
||||
setShowPopup: Dispatch<SetStateAction<boolean>>
|
||||
setShowPopup: (v: boolean) => void
|
||||
popupMode: number | null
|
||||
setPopupMode: Dispatch<SetStateAction<number | null>>
|
||||
setPopupMode: (v: number | null) => void
|
||||
fadeOut: boolean
|
||||
setFadeOut: Dispatch<SetStateAction<boolean>>
|
||||
setFadeOut: (v: boolean) => void
|
||||
downloadedVersionsConfig: VersionsConfig | null
|
||||
setDownloadedVersionsConfig: Dispatch<SetStateAction<VersionsConfig | null>>
|
||||
setDownloadedVersionsConfig: (v: VersionsConfig | null) => void
|
||||
normalConfig: NormalConfig | null
|
||||
setNormalConfig: Dispatch<SetStateAction<NormalConfig | null>>
|
||||
managingVersion: string | null
|
||||
setManagingVersion: Dispatch<SetStateAction<string | null>>
|
||||
setSelectedGame: Dispatch<SetStateAction<number | null>>
|
||||
getVersionInfo: (id: string | undefined) => GameVersion | undefined
|
||||
getGameInfo: (game: number | undefined) => Game | undefined
|
||||
getListOfGames(): Game[]
|
||||
getVersionsAmountData: (gameId: number) => {
|
||||
installed: number
|
||||
total: number
|
||||
} | null
|
||||
viewingInfoFromDownloads: boolean
|
||||
version: string | null
|
||||
downloadVersions: (list: string[]) => Promise<void>
|
||||
category: number
|
||||
setCategory: Dispatch<SetStateAction<number>>
|
||||
downloadQueue: string[]
|
||||
setDownloadQueue: Dispatch<SetStateAction<string[]>>
|
||||
closePopup: () => void
|
||||
getSpecialVersionsList(game?: number | undefined): GameVersion[]
|
||||
selectedGame: number | null
|
||||
setViewingInfoFromDownloads: Dispatch<SetStateAction<boolean>>
|
||||
setNormalConfig: (v: NormalConfig | null) => void
|
||||
managingVersion: DownloadedVersion | null
|
||||
setManagingVersion: (v: DownloadedVersion | null) => void
|
||||
}
|
||||
|
||||
const GlobalCtx = createContext<GlobalCtxType | null>(null)
|
||||
|
||||
@@ -1,75 +1,15 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
body {
|
||||
@apply bg-(--col0) text-white select-none;
|
||||
}
|
||||
|
||||
.dark-theme {
|
||||
--col0: rgb(8, 8, 8);
|
||||
--col1: rgb(16, 16, 16);
|
||||
--col2: rgb(32, 32, 32);
|
||||
--col3: rgb(48, 48, 48);
|
||||
--col4: rgb(64, 64, 64);
|
||||
--col5: rgb(80, 80, 80);
|
||||
--col6: rgb(96, 96, 96);
|
||||
--col7: rgb(112, 112, 112);
|
||||
--col8: rgb(128, 128, 128);
|
||||
}
|
||||
|
||||
.red-theme {
|
||||
--col0: rgb(32, 8, 8);
|
||||
--col1: rgb(40, 16, 16);
|
||||
--col2: rgb(56, 32, 32);
|
||||
--col3: rgb(72, 48, 48);
|
||||
--col4: rgb(88, 64, 64);
|
||||
--col5: rgb(104, 80, 80);
|
||||
--col6: rgb(120, 96, 96);
|
||||
--col7: rgb(136, 112, 112);
|
||||
--col8: rgb(152, 128, 128);
|
||||
}
|
||||
|
||||
.blue-theme {
|
||||
--col0: rgb(8, 8, 32);
|
||||
--col1: rgb(16, 16, 40);
|
||||
--col2: rgb(32, 32, 56);
|
||||
--col3: rgb(48, 48, 72);
|
||||
--col4: rgb(64, 64, 88);
|
||||
--col5: rgb(80, 80, 104);
|
||||
--col6: rgb(96, 96, 120);
|
||||
--col7: rgb(112, 112, 136);
|
||||
--col8: rgb(128, 128, 152);
|
||||
}
|
||||
|
||||
.purple-theme {
|
||||
--col0: rgb(20, 8, 32);
|
||||
--col1: rgb(28, 16, 40);
|
||||
--col2: rgb(44, 32, 56);
|
||||
--col3: rgb(60, 48, 72);
|
||||
--col4: rgb(76, 64, 88);
|
||||
--col5: rgb(92, 80, 104);
|
||||
--col6: rgb(108, 96, 120);
|
||||
--col7: rgb(124, 112, 136);
|
||||
--col8: rgb(140, 128, 152);
|
||||
@apply bg-[#0f0f0f] text-white select-none;
|
||||
}
|
||||
|
||||
.button {
|
||||
@apply rounded-md cursor-pointer text-[16px] py-1 px-2 transition-colors border;
|
||||
@apply bg-[#0a6ec8] hover:bg-[#1361ad] disabled:bg-[#124c7e] disabled:hover:bg-[#1b3f63] disabled:text-[#bdbdbd] disabled:hover:text-[#e6e6e6] rounded-md cursor-pointer text-[16px] py-1.5 px-3 transition-colors duration-[0.25s];
|
||||
}
|
||||
|
||||
.btntheme1 {
|
||||
@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,
|
||||
.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,
|
||||
.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);
|
||||
.button-green {
|
||||
@apply bg-[#28a745] hover:bg-[#218838] disabled:bg-[#1c7430] disabled:hover:bg-[#1a5c24] disabled:text-[#bdbdbd] disabled:hover:text-[#e6e6e6];
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
@@ -77,11 +17,11 @@ body {
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
@apply bg-(--col2) rounded-lg;
|
||||
@apply bg-[#1f1f1f] rounded-lg;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
@apply bg-(--col4) w-1 rounded-lg active:bg-(--col5);
|
||||
@apply bg-[#555] w-1 rounded-lg active:bg-[#888];
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
@@ -103,7 +43,7 @@ body {
|
||||
}
|
||||
|
||||
.popup-overlay {
|
||||
@apply fixed w-screen h-screen z-99999 flex justify-center items-center animate-[fadeIn_0.2s_ease-out_forwards] left-0 top-0 bg-[rgba(0,0,0,0.5)];
|
||||
@apply fixed w-screen h-screen z-[99999] flex justify-center items-center animate-[fadeIn_0.2s_ease-out_forwards] left-0 top-0 bg-[rgba(0,0,0,0.5)];
|
||||
}
|
||||
|
||||
.popup-overlay.fade-out {
|
||||
@@ -111,15 +51,15 @@ body {
|
||||
}
|
||||
|
||||
.popup-box {
|
||||
@apply relative w-150 h-120 rounded-lg bg-(--col1) border border-(--col3) flex flex-col p-6;
|
||||
@apply relative w-[60vw] h-[80vh] rounded-lg bg-[#161616] border border-[#323232] flex flex-col p-6;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
@apply flex-1 overflow-auto bg-(--col2) border border-(--col4) rounded-lg mt-4;
|
||||
@apply flex-1 overflow-auto bg-[#242424] border border-[#484848] rounded-lg mt-4;
|
||||
}
|
||||
|
||||
.popup-entry {
|
||||
@apply relative h-fit bg-(--col3) m-2 p-2 rounded-lg border border-(--col5);
|
||||
@apply relative h-[100px] bg-[#323232] m-2 p-2 rounded-lg border border-[#646464];
|
||||
}
|
||||
|
||||
.popup-entry button {
|
||||
@@ -127,7 +67,7 @@ body {
|
||||
}
|
||||
|
||||
.close-button {
|
||||
@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;
|
||||
@apply flex justify-center items-center absolute bg-[#323232] hover:bg-[#484848] 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-[#484848] hover:border-[#646464];
|
||||
}
|
||||
|
||||
*:focus {
|
||||
@@ -135,9 +75,5 @@ body {
|
||||
}
|
||||
|
||||
.input-field {
|
||||
@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 {
|
||||
@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;
|
||||
@apply border-2 border-[#484848] rounded-md bg-[#242424] p-2 px-4 focus:border-blue-600 transition-colors;
|
||||
}
|
||||
|
||||
@@ -5,9 +5,13 @@
|
||||
}
|
||||
|
||||
.downloads-scroll {
|
||||
@apply bg-(--col1) border border-(--col3) rounded-lg overflow-y-auto w-full;
|
||||
@apply h-[515px] bg-[#161616] border border-[#242424] rounded-lg overflow-y-auto w-full;
|
||||
}
|
||||
|
||||
.downloads-entry {
|
||||
@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) cursor-pointer;
|
||||
@apply flex justify-between items-center m-2 p-4 rounded-lg text-gray-200 text-lg transition-colors cursor-default bg-[#242424] hover:bg-[#323232] border border-[#484848] hover:border-[#565656];
|
||||
}
|
||||
|
||||
.downloads-entry p.score {
|
||||
@apply font-mono text-blue-500 text-lg;
|
||||
}
|
||||
|
||||
BIN
src/app/assets/Icon.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/app/assets/berries/AntiBerry.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
src/app/assets/berries/Berry.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/app/assets/berries/BerryNoColor.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/app/assets/berries/CoinBerry.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
src/app/assets/berries/GoldenBerry.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
src/app/assets/berries/PoisonBerry.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/app/assets/berries/SlowBerry.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
src/app/assets/berries/SpeedyBerry.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
src/app/assets/berries/UltraBerry.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
49
src/app/componets/RandomBerry.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import Image from 'next/image'
|
||||
import BerryNoColor from '../assets/berries/BerryNoColor.png'
|
||||
|
||||
export default function RandomBerry () {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null)
|
||||
const imgRef = useRef<HTMLImageElement>(document.createElement('img'))
|
||||
|
||||
useEffect(() => {
|
||||
imgRef.current.src = BerryNoColor.src
|
||||
const canvas = canvasRef.current
|
||||
const ctx = canvas?.getContext('2d')
|
||||
if (!canvas || !ctx) return
|
||||
|
||||
canvas.width = 24
|
||||
canvas.height = 24
|
||||
|
||||
let frame: number
|
||||
const frequency = 5
|
||||
|
||||
const update = () => {
|
||||
const t = (performance.now() / 1000) * frequency
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||
ctx.drawImage(imgRef.current, 0, 0, canvas.width, canvas.height)
|
||||
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
||||
const data = imageData.data
|
||||
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
const gray = data[i]
|
||||
const r = (Math.sin(t) * 0.5 + 0.5) * 255 * (gray / 255)
|
||||
const g = (Math.sin(t + 2) * 0.5 + 0.5) * 255 * (gray / 255)
|
||||
const b = (Math.sin(t + 4) * 0.5 + 0.5) * 255 * (gray / 255)
|
||||
data[i] = r
|
||||
data[i + 1] = g
|
||||
data[i + 2] = b
|
||||
}
|
||||
|
||||
ctx.putImageData(imageData, 0, 0)
|
||||
frame = requestAnimationFrame(update)
|
||||
}
|
||||
|
||||
imgRef.current.onload = () => update()
|
||||
return () => cancelAnimationFrame(frame)
|
||||
}, [])
|
||||
|
||||
return <canvas ref={canvasRef} style={{ width: 24, height: 24 }} />
|
||||
}
|
||||
@@ -5,11 +5,11 @@
|
||||
}
|
||||
|
||||
.setting-checkbox {
|
||||
@apply appearance-none w-full h-full border-2 border-(--col4) rounded-md bg-(--col2) transition-colors cursor-pointer;
|
||||
@apply appearance-none w-full h-full border-2 border-[#484848] rounded-md bg-[#242424] transition-colors duration-200 cursor-pointer;
|
||||
}
|
||||
|
||||
.setting-checkbox:checked {
|
||||
@apply bg-(--col4) border-(--col6);
|
||||
@apply bg-blue-500 border-blue-600;
|
||||
}
|
||||
|
||||
.fa-check-icon {
|
||||
@@ -1,17 +1,11 @@
|
||||
import './Setting.css'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
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,
|
||||
title
|
||||
}: SettingProps) {
|
||||
export function Setting ({ label, value, onChange, className }: SettingProps) {
|
||||
return (
|
||||
<div className={`flex items-center gap-2 mb-2 ${className}`} title={title}>
|
||||
<div className={`flex items-center gap-2 mb-2 ${className}`}>
|
||||
<label className='text-white text-lg'>{label}</label>
|
||||
<div className='setting-checkbox-wrapper'>
|
||||
<input
|
||||
39
src/app/componets/Sidebar.css
Normal file
@@ -0,0 +1,39 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
.sidebar {
|
||||
@apply fixed top-0 left-0 w-60 h-screen bg-[#161616] flex flex-col border-e-[1px] border-[#242424] z-[1];
|
||||
}
|
||||
|
||||
.sidebar-downloads {
|
||||
@apply text-[#bdbdbd] fixed bottom-3 left-2 bg-[#242424] rounded-lg border border-[#323232] w-55 p-4 cursor-pointer transition-colors duration-[0.25s];
|
||||
}
|
||||
|
||||
.sidebar-downloads:hover {
|
||||
@apply text-white;
|
||||
@apply bg-[#323232] border-[#484848];
|
||||
}
|
||||
|
||||
.logo {
|
||||
@apply text-2xl font-bold p-4;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
@apply flex flex-col p-4 space-y-1;
|
||||
}
|
||||
|
||||
.link {
|
||||
@apply text-[#bdbdbd] p-2 rounded-md no-underline cursor-pointer transition-colors duration-[0.25s] border border-transparent;
|
||||
}
|
||||
|
||||
.link.active {
|
||||
@apply bg-[#242424] border-[#323232];
|
||||
}
|
||||
|
||||
.link.active,
|
||||
.link:hover {
|
||||
@apply text-white;
|
||||
}
|
||||
|
||||
.link.active:hover {
|
||||
@apply bg-[#323232] border-[#484848];
|
||||
}
|
||||
135
src/app/componets/Sidebar.tsx
Normal file
@@ -0,0 +1,135 @@
|
||||
'use client'
|
||||
|
||||
import './Sidebar.css'
|
||||
import Icon from '../assets/Icon.png'
|
||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import {
|
||||
faCog,
|
||||
faDownload,
|
||||
faRankingStar,
|
||||
faServer
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { faDiscord } from '@fortawesome/free-brands-svg-icons'
|
||||
import { useState } from 'react'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { useGlobal } from '../GlobalProvider'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
|
||||
export default function Sidebar () {
|
||||
const [rot, setRot] = useState(0)
|
||||
const [dir, setDir] = useState(1)
|
||||
const { setShowPopup, setPopupMode, setFadeOut, downloadProgress } =
|
||||
useGlobal()
|
||||
const pathname = usePathname()
|
||||
|
||||
return (
|
||||
<aside className='sidebar'>
|
||||
<div
|
||||
className='dragarea'
|
||||
style={{
|
||||
height: '30px',
|
||||
width: 'calc(var(--spacing) * 60)',
|
||||
top: 0,
|
||||
left: 0,
|
||||
marginBottom: '-15px',
|
||||
position: 'absolute',
|
||||
zIndex: 9999,
|
||||
display: platform() == 'macos' ? 'block' : 'none',
|
||||
pointerEvents: 'auto'
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
getCurrentWindow().startDragging()
|
||||
}}
|
||||
></div>
|
||||
<div className='logo'>
|
||||
<Image
|
||||
draggable={false}
|
||||
src={Icon}
|
||||
width={48}
|
||||
height={48}
|
||||
alt=''
|
||||
style={{
|
||||
transform: `rotate(${rot}deg)`,
|
||||
transition: 'transform 0.3s ease',
|
||||
marginTop: ['windows', 'macos'].includes(platform())
|
||||
? '20px'
|
||||
: '0px'
|
||||
}}
|
||||
onClick={() =>
|
||||
setRot(r => {
|
||||
let next = r + dir * 90
|
||||
if (next >= 360) {
|
||||
next = 360
|
||||
setDir(-1)
|
||||
} else if (next <= 0) {
|
||||
next = 0
|
||||
setDir(1)
|
||||
}
|
||||
return next
|
||||
})
|
||||
}
|
||||
onContextMenu={() =>
|
||||
setRot(r => {
|
||||
let next = r - dir * 90
|
||||
if (next >= 360) {
|
||||
next = 360
|
||||
setDir(-1)
|
||||
} else if (next <= 0) {
|
||||
next = 0
|
||||
setDir(1)
|
||||
}
|
||||
return next
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<nav className='nav-links'>
|
||||
<Link
|
||||
draggable={false}
|
||||
href='/'
|
||||
className={`link ${pathname === '/' ? 'active' : ''}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faServer} className='mr-1' /> Installs
|
||||
</Link>
|
||||
<Link
|
||||
draggable={false}
|
||||
href='/settings'
|
||||
className={`link ${pathname === '/settings' ? 'active' : ''}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCog} className='mr-1' /> Settings
|
||||
</Link>
|
||||
<Link
|
||||
draggable={false}
|
||||
href='/leaderboards'
|
||||
className={`link ${pathname === '/leaderboards' ? 'active' : ''}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faRankingStar} className='mr-1' /> Leaderboards
|
||||
</Link>
|
||||
<a
|
||||
draggable={false}
|
||||
onClick={() => openUrl('https://berrydash.lncvrt.xyz/discord')}
|
||||
className='link'
|
||||
>
|
||||
<FontAwesomeIcon icon={faDiscord} className='mr-1' /> Community
|
||||
</a>
|
||||
</nav>
|
||||
<div
|
||||
className='sidebar-downloads'
|
||||
style={{ display: downloadProgress.length != 0 ? 'block' : 'none' }}
|
||||
onClick={() => {
|
||||
setPopupMode(1)
|
||||
setShowPopup(true)
|
||||
setFadeOut(false)
|
||||
}}
|
||||
>
|
||||
<p>
|
||||
<FontAwesomeIcon icon={faDownload} /> Downloads
|
||||
</p>
|
||||
</div>
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { BirdColor } from '@/types/BerryDash/BirdColor'
|
||||
import axios from 'axios'
|
||||
import { GetIconForUser } from '@/lib/BerryDash'
|
||||
import Image from 'next/image'
|
||||
import './styles.css'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
|
||||
interface BaseEntry {
|
||||
id: number
|
||||
username: string
|
||||
value: number
|
||||
icon: number
|
||||
overlay: number
|
||||
birdColor: BirdColor
|
||||
overlayColor: BirdColor
|
||||
customIcon: string | null
|
||||
}
|
||||
|
||||
interface Stats {
|
||||
highScore: string
|
||||
totalNormalBerries: string
|
||||
totalPoisonBerries: string
|
||||
totalSlowBerries: string
|
||||
totalUltraBerries: string
|
||||
totalSpeedyBerries: string
|
||||
totalCoinBerries: string
|
||||
totalRandomBerries: string
|
||||
totalAntiBerries: string
|
||||
totalGoldenBerries: string
|
||||
coins: string
|
||||
}
|
||||
|
||||
interface LeaderboardEntry extends BaseEntry {
|
||||
type: 'leaderboard'
|
||||
value: number
|
||||
}
|
||||
|
||||
interface Account extends BaseEntry {
|
||||
type: 'account'
|
||||
stats: Stats
|
||||
xp: bigint
|
||||
}
|
||||
|
||||
export function calculateXP (
|
||||
normalBerries: bigint,
|
||||
poisonBerries: bigint,
|
||||
slowBerries: bigint,
|
||||
ultraBerries: bigint,
|
||||
speedyBerries: bigint,
|
||||
coinBerries: bigint,
|
||||
randomBerries: bigint,
|
||||
antiBerries: bigint,
|
||||
goldenBerries: bigint
|
||||
): bigint {
|
||||
let totalXp = 0n
|
||||
totalXp += normalBerries
|
||||
totalXp -= poisonBerries
|
||||
totalXp -= slowBerries
|
||||
totalXp += ultraBerries * 5n
|
||||
totalXp += speedyBerries * 10n
|
||||
totalXp += coinBerries * 10n
|
||||
totalXp += randomBerries
|
||||
totalXp -= antiBerries
|
||||
totalXp += goldenBerries * 4n
|
||||
|
||||
if (totalXp < 0n) totalXp = 0n
|
||||
return totalXp
|
||||
}
|
||||
|
||||
export function calculateLevel (xp: bigint): number {
|
||||
const levelDivisor = 50.0
|
||||
|
||||
const xpNumber = Number(xp)
|
||||
const discriminant = 95 * 95 + levelDivisor * 2 * xpNumber
|
||||
const level = (-95 + Math.sqrt(discriminant)) / levelDivisor
|
||||
return Math.floor(level) + 1
|
||||
}
|
||||
|
||||
export default function BerryDashLeaderboards () {
|
||||
const [selected, setSelected] = useState<number>(-1)
|
||||
const [selectedBerryOption, setSelectedBerryOption] = useState<number>(0)
|
||||
const [entries, setEntries] = useState<(LeaderboardEntry | Account)[]>([])
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const Refresh = useCallback(async () => {
|
||||
try {
|
||||
if (selected == 3 || selected == 4) {
|
||||
const result = await axios.get(
|
||||
'https://games.lncvrt.xyz/api/berrydash/account?username='
|
||||
)
|
||||
if (result.data.success) {
|
||||
let accounts = result.data.data as Account[]
|
||||
|
||||
accounts = accounts.map(acc => {
|
||||
const xp = calculateXP(
|
||||
BigInt(acc.stats.totalNormalBerries),
|
||||
BigInt(acc.stats.totalPoisonBerries),
|
||||
BigInt(acc.stats.totalSlowBerries),
|
||||
BigInt(acc.stats.totalUltraBerries),
|
||||
BigInt(acc.stats.totalSpeedyBerries),
|
||||
BigInt(acc.stats.totalCoinBerries),
|
||||
BigInt(acc.stats.totalRandomBerries),
|
||||
BigInt(acc.stats.totalAntiBerries),
|
||||
BigInt(acc.stats.totalGoldenBerries)
|
||||
)
|
||||
return { ...acc, xp }
|
||||
})
|
||||
|
||||
accounts.sort((a, b) => (b.xp > a.xp ? 1 : b.xp < a.xp ? -1 : 0))
|
||||
|
||||
setEntries(accounts)
|
||||
}
|
||||
} else {
|
||||
const result = await axios.get(
|
||||
'https://games.lncvrt.xyz/api/berrydash/leaderboard/' +
|
||||
(selected == 0
|
||||
? 'score'
|
||||
: selected == 1
|
||||
? 'berry?berry=' + selectedBerryOption
|
||||
: selected == 2
|
||||
? 'coin'
|
||||
: selected == 5
|
||||
? 'legacy'
|
||||
: 'total')
|
||||
)
|
||||
if (result.data.success) {
|
||||
setEntries(result.data.data as LeaderboardEntry[])
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
setEntries([])
|
||||
}
|
||||
}, [selected, selectedBerryOption])
|
||||
|
||||
useEffect(() => {
|
||||
document.title = 'Lncvrt Games - Berry Dash Leaderboards'
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (selected != -1) setTimeout(() => Refresh(), 0)
|
||||
}, [selected, Refresh])
|
||||
|
||||
return (
|
||||
<div className='mx-4 mt-4'>
|
||||
<div className='flex justify-between items-center mb-4'>
|
||||
<p className='text-3xl'>Berry Dash Leaderboards</p>
|
||||
<div className='flex gap-2'>
|
||||
<button
|
||||
className='button btntheme1'
|
||||
onClick={() => {
|
||||
setEntries([])
|
||||
Refresh()
|
||||
}}
|
||||
title='Click to refresh the leaderboards.'
|
||||
hidden={selected == -1}
|
||||
>
|
||||
Refresh
|
||||
</button>
|
||||
<button
|
||||
className='button btntheme1'
|
||||
onClick={() => {
|
||||
if (selected == -1) router.push('/game?id=1')
|
||||
else {
|
||||
setSelected(-1)
|
||||
setEntries([])
|
||||
}
|
||||
}}
|
||||
title='Click to go up a level.'
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`box ${
|
||||
platform() == 'windows'
|
||||
? 'h-[calc(100vh-116px)]'
|
||||
: 'h-[calc(100vh-84px)]'
|
||||
}`}
|
||||
>
|
||||
{selected == -1 ? (
|
||||
<>
|
||||
<p className='text-center mt-2 text-xl'>Select a Leaderboard</p>
|
||||
<div className='flex flex-col gap-2 mt-2 items-center justify-center'>
|
||||
<button
|
||||
className='leaderboard-button'
|
||||
onClick={() => setSelected(0)}
|
||||
>
|
||||
Score Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className='leaderboard-button'
|
||||
onClick={() => setSelected(1)}
|
||||
>
|
||||
Berry Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className='leaderboard-button'
|
||||
onClick={() => setSelected(2)}
|
||||
>
|
||||
Coins Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className='leaderboard-button'
|
||||
onClick={() => setSelected(3)}
|
||||
>
|
||||
Level Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className='leaderboard-button'
|
||||
onClick={() => setSelected(4)}
|
||||
>
|
||||
Total XP Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className='leaderboard-button'
|
||||
onClick={() => setSelected(5)}
|
||||
>
|
||||
Legacy Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className='leaderboard-button'
|
||||
onClick={() => setSelected(6)}
|
||||
>
|
||||
Total Berries Leaderboard
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div
|
||||
className={`flex flex-col gap-2 overflow-y-auto ${
|
||||
selected == 1
|
||||
? platform() == 'windows'
|
||||
? 'h-[calc(100vh-168px)]'
|
||||
: 'h-[calc(100vh-136px)]'
|
||||
: platform() == 'windows'
|
||||
? 'h-[calc(100vh-128px)]'
|
||||
: 'h-[calc(100vh-96px)]'
|
||||
} px-1`}
|
||||
>
|
||||
{entries.map((item, index) => {
|
||||
const isAccount = 'stats' in item
|
||||
const isLeaderboard = 'value' in item && !isAccount
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.id}
|
||||
className='leaderboard-entry flex justify-between items-center'
|
||||
>
|
||||
<div className='flex items-center gap-1'>
|
||||
<Image
|
||||
src={
|
||||
!item.customIcon
|
||||
? `https://games-r2.lncvrt.xyz/game-assets/berrydash/icons/bird_${
|
||||
item.icon === 1
|
||||
? GetIconForUser(item.id)
|
||||
: item.icon
|
||||
}.png`
|
||||
: `https://games.lncvrt.xyz/api/berrydash/icon-marketplace/icon?id=${item.customIcon}&raw=true`
|
||||
}
|
||||
className='pointer-events-none'
|
||||
width={48}
|
||||
height={48}
|
||||
alt=''
|
||||
unoptimized
|
||||
/>
|
||||
<p>
|
||||
{item.username} (#{index + 1})
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{isLeaderboard ? (
|
||||
<p>
|
||||
{selected === 1 || selected === 6
|
||||
? 'Berries'
|
||||
: selected === 2
|
||||
? 'Coins'
|
||||
: 'Score'}
|
||||
: {item.value.toLocaleString('en-US')}
|
||||
</p>
|
||||
) : isAccount ? (
|
||||
<p>
|
||||
{selected === 3 ? 'Level' : 'XP'}:{' '}
|
||||
{selected === 3
|
||||
? calculateLevel(item.xp).toLocaleString('en-US')
|
||||
: item.xp.toLocaleString('en-US')}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
{selected == 1 && (
|
||||
<div className='flex justify-center'>
|
||||
<select
|
||||
value={selectedBerryOption}
|
||||
onChange={e => setSelectedBerryOption(Number(e.target.value))}
|
||||
className='leaderboard-select mt-0.75'
|
||||
>
|
||||
<option value='0'>Normal Berry</option>
|
||||
<option value='1'>Poison Berry</option>
|
||||
<option value='2'>Slow Berry</option>
|
||||
<option value='3'>Ultra Berry</option>
|
||||
<option value='4'>Speedy Berry</option>
|
||||
<option value='5'>Coin Berry</option>
|
||||
<option value='6'>Random Berry</option>
|
||||
<option value='7'>Anti Berry</option>
|
||||
<option value='8'>Golden Berry</option>
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
.box {
|
||||
@apply bg-(--col1) border border-(--col3) rounded-lg w-auto p-1;
|
||||
}
|
||||
|
||||
.leaderboard-button,
|
||||
.leaderboard-select {
|
||||
@apply bg-(--col2) hover:bg-(--col4) border border-(--col4) hover:border-(--col6) rounded-lg px-4 py-2 inline-block transition-all duration-200 cursor-pointer;
|
||||
}
|
||||
|
||||
.leaderboard-entry {
|
||||
@apply rounded-lg text-gray-200 text-lg px-1 py-0.5 transition-colors bg-(--col2) hover:bg-(--col3) border border-(--col4) hover:border-(--col5) cursor-pointer;
|
||||
}
|
||||
@@ -1,370 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect } from 'react'
|
||||
import '@/app/Installs.css'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { faWarning } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { ask } from '@tauri-apps/plugin-dialog'
|
||||
import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs'
|
||||
import { writeVersionsConfig } from '@/lib/BazookaManager'
|
||||
import { openFolder } from '@/lib/Util'
|
||||
|
||||
export default function Installs () {
|
||||
const {
|
||||
showPopup,
|
||||
setShowPopup,
|
||||
setPopupMode,
|
||||
setFadeOut,
|
||||
setSelectedVersionList,
|
||||
downloadedVersionsConfig,
|
||||
normalConfig,
|
||||
setManagingVersion,
|
||||
getVersionInfo,
|
||||
getGameInfo,
|
||||
setSelectedGame,
|
||||
serverVersionList,
|
||||
category,
|
||||
setCategory,
|
||||
setDownloadedVersionsConfig,
|
||||
downloadVersions
|
||||
} = useGlobal()
|
||||
|
||||
const params = useSearchParams()
|
||||
const router = useRouter()
|
||||
|
||||
const id = Number(params.get('id') || 0)
|
||||
const game = serverVersionList?.games.find(g => g.id === id)
|
||||
|
||||
useEffect(() => {
|
||||
if (!showPopup) return
|
||||
setSelectedVersionList([])
|
||||
}, [normalConfig, setSelectedVersionList, showPopup])
|
||||
|
||||
if (!id || !game) return <p>Invalid game</p>
|
||||
|
||||
const needsRevisionUpdate = (
|
||||
lastRevision: number | undefined,
|
||||
version: string
|
||||
) => {
|
||||
if (!lastRevision) return false
|
||||
return (
|
||||
lastRevision > 0 &&
|
||||
(downloadedVersionsConfig == undefined
|
||||
? 0
|
||||
: downloadedVersionsConfig?.list[version]) /
|
||||
1000 <=
|
||||
lastRevision
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='mx-4 mt-4'>
|
||||
<div className='flex justify-between items-center mb-4'>
|
||||
<p
|
||||
className={`text-3xl truncate ${
|
||||
category != -1
|
||||
? 'w-[calc(100vw-495px)]'
|
||||
: game.id == 1
|
||||
? 'w-[calc(100vw-560px)]'
|
||||
: 'w-[calc(100vw-440px)]'
|
||||
}`}
|
||||
>
|
||||
{game.name} Installs
|
||||
</p>
|
||||
<div className='flex gap-2'>
|
||||
<button
|
||||
className='button btntheme1'
|
||||
onClick={() => {
|
||||
router.push('/game/berrydash/leaderboards')
|
||||
}}
|
||||
title='View the leaderboards for this game.'
|
||||
hidden={game.id != 1}
|
||||
>
|
||||
Leaderboards
|
||||
</button>
|
||||
<button
|
||||
className='button btntheme1'
|
||||
onClick={() => {
|
||||
setCategory(-1)
|
||||
}}
|
||||
title='Click to go up a level.'
|
||||
hidden={category == -1}
|
||||
>
|
||||
Back
|
||||
</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 className='downloads-container'>
|
||||
<div
|
||||
className={`downloads-scroll ${
|
||||
platform() == 'windows'
|
||||
? 'h-[calc(100vh-116px)]'
|
||||
: 'h-[calc(100vh-84px)]'
|
||||
}`}
|
||||
>
|
||||
{category == -1 &&
|
||||
Object.entries(game.categoryNames)
|
||||
.sort(([a], [b]) => Number(b) - Number(a))
|
||||
.filter(([key]) => {
|
||||
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
|
||||
|
||||
return count >= 1
|
||||
})
|
||||
.map(([key, value]) => {
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
className={'downloads-entry'}
|
||||
title={'Click to view category'}
|
||||
onClick={() => 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>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{Object.keys(downloadedVersionsConfig?.list ?? []).filter(v => {
|
||||
const info = getVersionInfo(v)
|
||||
if (!info) return false
|
||||
return info.game === id
|
||||
}).length != 0 ? (
|
||||
Object.keys(downloadedVersionsConfig?.list ?? [])
|
||||
.sort((a, b) => {
|
||||
const infoA = getVersionInfo(a)
|
||||
const infoB = getVersionInfo(b)
|
||||
if (!infoA || !infoB) return -1
|
||||
return infoB.place - infoA.place
|
||||
})
|
||||
.filter(v => {
|
||||
const info = getVersionInfo(v)
|
||||
if (!info) return false
|
||||
if (
|
||||
platform() == 'linux' &&
|
||||
info.wine &&
|
||||
!normalConfig?.settings.useWineOnUnixWhenNeeded
|
||||
)
|
||||
return false
|
||||
return (
|
||||
info.game === id &&
|
||||
(category == -1
|
||||
? info.category == -1
|
||||
: info.category == category)
|
||||
)
|
||||
})
|
||||
.map(entry => (
|
||||
<div
|
||||
key={entry}
|
||||
className={'downloads-entry'}
|
||||
title={
|
||||
'Click to launch game. Right-click to manage this version install'
|
||||
}
|
||||
onClick={async () => {
|
||||
if (
|
||||
needsRevisionUpdate(
|
||||
getVersionInfo(entry)?.lastRevision,
|
||||
entry
|
||||
)
|
||||
) {
|
||||
const answer = await ask(
|
||||
'Before proceeding, if you do not want your installation directory wiped just yet, please backup the files to another directory. When you click "Yes", it will be wiped. Click "No" if you want to open the installation folder instead.',
|
||||
{
|
||||
title: 'Revision Update',
|
||||
kind: 'warning'
|
||||
}
|
||||
)
|
||||
if (answer) {
|
||||
const answer2 = await ask(
|
||||
'Are you sure you want to update? If you did not read the last popup, please go back and read it.',
|
||||
{
|
||||
title: 'Revision Update',
|
||||
kind: 'warning'
|
||||
}
|
||||
)
|
||||
if (!answer2) return
|
||||
|
||||
//open downloads popup
|
||||
setPopupMode(1)
|
||||
setShowPopup(true)
|
||||
setFadeOut(false)
|
||||
|
||||
//uninstall
|
||||
setDownloadedVersionsConfig(prev => {
|
||||
if (!prev) return prev
|
||||
const updatedList = Object.fromEntries(
|
||||
Object.entries(prev.list).filter(
|
||||
([k]) => k !== entry
|
||||
)
|
||||
)
|
||||
const updatedConfig = {
|
||||
...prev,
|
||||
list: updatedList
|
||||
}
|
||||
writeVersionsConfig(updatedConfig)
|
||||
return updatedConfig
|
||||
})
|
||||
|
||||
if (
|
||||
await exists('game/' + entry, {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
})
|
||||
)
|
||||
await remove('game/' + entry, {
|
||||
baseDir: BaseDirectory.AppLocalData,
|
||||
recursive: true
|
||||
})
|
||||
|
||||
//reinstall
|
||||
setSelectedVersionList([entry])
|
||||
downloadVersions([entry])
|
||||
} else {
|
||||
openFolder(entry)
|
||||
}
|
||||
return
|
||||
}
|
||||
const verInfo = getVersionInfo(entry)
|
||||
if (verInfo == undefined) return
|
||||
const gameInfo = getGameInfo(verInfo.game)
|
||||
if (gameInfo == undefined) return
|
||||
invoke('launch_game', {
|
||||
name: verInfo.id,
|
||||
executable: verInfo.executable,
|
||||
displayName: verInfo.displayName,
|
||||
useWine: !!(
|
||||
platform() == 'linux' &&
|
||||
verInfo.wine &&
|
||||
normalConfig?.settings.useWineOnUnixWhenNeeded
|
||||
),
|
||||
wineCommand: normalConfig?.settings.wineOnUnixCommand
|
||||
})
|
||||
}}
|
||||
onContextMenu={e => {
|
||||
e.preventDefault()
|
||||
setManagingVersion(entry)
|
||||
setPopupMode(2)
|
||||
setShowPopup(true)
|
||||
setFadeOut(false)
|
||||
}}
|
||||
>
|
||||
<div className='h-18 w-screen relative'>
|
||||
<p className='text-2xl'>
|
||||
{getVersionInfo(entry)?.displayName}{' '}
|
||||
</p>
|
||||
|
||||
<div className='flex gap-2 absolute left-0 bottom-0'>
|
||||
<div
|
||||
className='entry-info-item'
|
||||
title='The date the game was installed.'
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
<p>
|
||||
Installed{' '}
|
||||
{new Intl.DateTimeFormat(undefined).format(
|
||||
downloadedVersionsConfig?.list[entry]
|
||||
)}
|
||||
</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
|
||||
) ||
|
||||
needsRevisionUpdate(
|
||||
getVersionInfo(entry)?.lastRevision,
|
||||
entry
|
||||
)
|
||||
}
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
|
||||
<p>Uses wine</p>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item'
|
||||
onClick={e => e.stopPropagation()}
|
||||
hidden={
|
||||
!needsRevisionUpdate(
|
||||
getVersionInfo(entry)?.lastRevision,
|
||||
entry
|
||||
)
|
||||
}
|
||||
>
|
||||
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
|
||||
<p>Needs revision update!</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className='flex justify-center items-center h-full'>
|
||||
<p className='text-3xl'>No versions installed</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
53
src/app/leaderboards/Leaderboards.css
Normal file
@@ -0,0 +1,53 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
.leaderboard-container {
|
||||
@apply flex items-end justify-center gap-3;
|
||||
}
|
||||
|
||||
.leaderboard-scroll {
|
||||
@apply h-[510px] bg-[#161616] border border-[#242424] rounded-lg overflow-y-auto w-[475px] relative;
|
||||
}
|
||||
|
||||
.leaderboard-entry {
|
||||
@apply flex items-center m-2 p-4 rounded-lg text-gray-200 text-lg transition-colors cursor-default bg-[#242424] hover:bg-[#323232] border border-[#484848] hover:border-[#565656];
|
||||
}
|
||||
|
||||
.leaderboard-entry p.score {
|
||||
@apply font-mono text-blue-500 text-lg;
|
||||
}
|
||||
|
||||
.side-dropdown {
|
||||
@apply flex items-end min-w-[52px];
|
||||
}
|
||||
|
||||
.dropdown-root {
|
||||
@apply relative w-max;
|
||||
}
|
||||
|
||||
.dropdown-btn {
|
||||
@apply px-3 py-2 rounded-md bg-[#242424] disabled:bg-[#161616] border border-[#484848] disabled:border-[#383838] text-gray-200 hover:bg-[#323232] hover:border-[#565656] transition-colors cursor-pointer;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
@apply absolute bottom-full mb-2 w-55 bg-[#242424] border border-[#484848] rounded-md shadow-lg hidden z-50;
|
||||
}
|
||||
|
||||
.dropdown-left .dropdown-menu {
|
||||
@apply left-0;
|
||||
}
|
||||
|
||||
.dropdown-right .dropdown-menu {
|
||||
@apply right-0 w-42;
|
||||
}
|
||||
|
||||
.dropdown-menu.open {
|
||||
@apply block;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
@apply block w-full text-left px-4 py-2 hover:bg-[#323232] text-gray-200 cursor-pointer;
|
||||
}
|
||||
|
||||
.dropdown-item.selected {
|
||||
@apply bg-[#323232] hover:bg-[#484848];
|
||||
}
|
||||
361
src/app/leaderboards/page.tsx
Normal file
@@ -0,0 +1,361 @@
|
||||
'use client'
|
||||
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import './Leaderboards.css'
|
||||
import axios from 'axios'
|
||||
import { app } from '@tauri-apps/api'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { decrypt, encrypt } from '../util/Encryption'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import Image from 'next/image'
|
||||
import { LeaderboardResponse } from '../types/LeaderboardResponse'
|
||||
import { faChevronDown } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { getKey } from '../util/KeysHelper'
|
||||
|
||||
import Berry from '../assets/berries/Berry.png'
|
||||
import PoisonBerry from '../assets/berries/PoisonBerry.png'
|
||||
import SlowBerry from '../assets/berries/SlowBerry.png'
|
||||
import UltraBerry from '../assets/berries/UltraBerry.png'
|
||||
import SpeedyBerry from '../assets/berries/SpeedyBerry.png'
|
||||
import CoinBerry from '../assets/berries/CoinBerry.png'
|
||||
import RainbowBerry from '../componets/RandomBerry'
|
||||
import AntiBerry from '../assets/berries/AntiBerry.png'
|
||||
|
||||
export default function Leaderboards () {
|
||||
const [leaderboardData, setLeaderboardData] =
|
||||
useState<LeaderboardResponse | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [leftOpen, setLeftOpen] = useState(false)
|
||||
const [rightOpen, setRightOpen] = useState(false)
|
||||
const leftRef = useRef<HTMLDivElement | null>(null)
|
||||
const rightRef = useRef<HTMLDivElement | null>(null)
|
||||
const formatter = new Intl.NumberFormat('en-US')
|
||||
const [leaderboardType, setLeaderboardType] = useState<number>(0)
|
||||
const [berryType, setBerryType] = useState<number>(0)
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
setLoading(true)
|
||||
setLeaderboardData(null)
|
||||
try {
|
||||
const launcherVersion = await app.getVersion()
|
||||
const sendKey = await getKey(1)
|
||||
const formData = new URLSearchParams()
|
||||
formData.append(
|
||||
await encrypt('type', sendKey),
|
||||
await encrypt(leaderboardType.toString(), sendKey)
|
||||
)
|
||||
if (leaderboardType == 1) {
|
||||
formData.append(
|
||||
await encrypt('showType', sendKey),
|
||||
await encrypt(berryType.toString(), sendKey)
|
||||
)
|
||||
}
|
||||
const response = await axios.post(
|
||||
'https://berrydash.lncvrt.xyz/database/getTopPlayers.php',
|
||||
formData,
|
||||
{
|
||||
headers: {
|
||||
Requester: 'BerryDashLauncher',
|
||||
LauncherVersion: launcherVersion,
|
||||
ClientPlatform: platform()
|
||||
}
|
||||
}
|
||||
)
|
||||
const decrypted = await decrypt(response.data)
|
||||
setLeaderboardData(JSON.parse(decrypted))
|
||||
} catch (e) {
|
||||
console.error('Error fetching leaderboard data:', e)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [leaderboardType, berryType])
|
||||
|
||||
function downloadLeaderboard () {
|
||||
let content = '"Username","Score","ScoreFormatted"\n'
|
||||
leaderboardData?.entries.forEach(entry => {
|
||||
content += `"${entry.username}","${entry.value}","${formatter.format(
|
||||
BigInt(entry.value)
|
||||
)}"\n`
|
||||
})
|
||||
while (content.endsWith('\n')) {
|
||||
content = content.slice(0, -1)
|
||||
}
|
||||
invoke('download_leaderboard', { content })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
refresh()
|
||||
}, [refresh])
|
||||
|
||||
useEffect(() => {
|
||||
function onDocClick (e: MouseEvent) {
|
||||
const t = e.target as Node
|
||||
if (leftRef.current && !leftRef.current.contains(t)) setLeftOpen(false)
|
||||
if (rightRef.current && !rightRef.current.contains(t)) setRightOpen(false)
|
||||
}
|
||||
document.addEventListener('mousedown', onDocClick)
|
||||
return () => document.removeEventListener('mousedown', onDocClick)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className='mx-4 mt-4'>
|
||||
<div className='flex justify-between items-center mb-4'>
|
||||
<p className='text-3xl'>Leaderboards</p>
|
||||
<div className='flex gap-2'>
|
||||
<button
|
||||
className='button text-3xl'
|
||||
onClick={downloadLeaderboard}
|
||||
disabled={loading || leaderboardData?.entries?.length === 0}
|
||||
>
|
||||
Download Leaderboards
|
||||
</button>
|
||||
<button
|
||||
className='button text-3xl'
|
||||
onClick={refresh}
|
||||
disabled={loading}
|
||||
>
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='leaderboard-container'>
|
||||
<div className='side-dropdown'>
|
||||
<div ref={leftRef} className='dropdown-root dropdown-left'>
|
||||
<button
|
||||
className='dropdown-btn'
|
||||
onClick={() => setLeftOpen(v => !v)}
|
||||
aria-expanded={leftOpen}
|
||||
disabled={loading}
|
||||
>
|
||||
Type{' '}
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronDown}
|
||||
className={leftOpen ? 'rotate-180' : ''}
|
||||
/>
|
||||
</button>
|
||||
<div className={`dropdown-menu ${leftOpen ? 'open' : ''}`}>
|
||||
<button
|
||||
className={`dropdown-item ${
|
||||
leaderboardType == 0 ? 'selected' : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
setLeftOpen(false)
|
||||
setLeaderboardType(0)
|
||||
}}
|
||||
>
|
||||
Score Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${
|
||||
leaderboardType == 1 ? 'selected' : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
setLeftOpen(false)
|
||||
setLeaderboardType(1)
|
||||
}}
|
||||
>
|
||||
Berry Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${
|
||||
leaderboardType == 2 ? 'selected' : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
setLeftOpen(false)
|
||||
setLeaderboardType(2)
|
||||
}}
|
||||
>
|
||||
Coins Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${
|
||||
leaderboardType == 3 ? 'selected' : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
setLeftOpen(false)
|
||||
setLeaderboardType(3)
|
||||
}}
|
||||
>
|
||||
Legacy Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${
|
||||
leaderboardType == 4 ? 'selected' : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
setLeftOpen(false)
|
||||
setLeaderboardType(4)
|
||||
}}
|
||||
>
|
||||
Total Berries Leaderboard
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='leaderboard-scroll'>
|
||||
{leaderboardData?.entries?.length ? (
|
||||
leaderboardData.entries.map((entry, i) => (
|
||||
<div key={i} className='leaderboard-entry justify-between'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Image
|
||||
src={
|
||||
entry.customIcon == null
|
||||
? entry.overlay == 0
|
||||
? `https://berrydash-api.lncvrt.xyz/icon?r=${entry.birdColor[0]}&g=${entry.birdColor[1]}&b=${entry.birdColor[2]}&id=${entry.icon}`
|
||||
: `https://berrydash-api.lncvrt.xyz/iconandoverlay?br=${entry.birdColor[0]}&bg=${entry.birdColor[1]}&bb=${entry.birdColor[2]}&bid=${entry.icon}&or=${entry.overlayColor[0]}&og=${entry.overlayColor[1]}&ob=${entry.overlayColor[2]}&oid=${entry.overlay}`
|
||||
: `data:image/png;base64,${
|
||||
leaderboardData.customIcons[entry.customIcon]
|
||||
}`
|
||||
}
|
||||
width={28}
|
||||
height={28}
|
||||
alt=''
|
||||
className='scale-x-[-1] -ml-2'
|
||||
onError={e => {
|
||||
;(e.currentTarget as HTMLImageElement).style.display =
|
||||
'none'
|
||||
}}
|
||||
/>
|
||||
<p>
|
||||
{entry.username} (#{i + 1})
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className='score'>
|
||||
{formatter.format(BigInt(entry.value))}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : loading ? (
|
||||
<div className='flex justify-center items-center h-full'>
|
||||
<p className='text-3xl'>Loading...</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className='flex justify-center items-center h-full'>
|
||||
<p className='text-3xl'>No data...</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='side-dropdown'>
|
||||
<div ref={rightRef} className='dropdown-root dropdown-right'>
|
||||
<button
|
||||
className='dropdown-btn'
|
||||
onClick={() => setRightOpen(v => !v)}
|
||||
aria-expanded={rightOpen}
|
||||
disabled={loading || leaderboardType != 1}
|
||||
>
|
||||
Berry Type{' '}
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronDown}
|
||||
className={rightOpen ? 'rotate-180' : ''}
|
||||
/>
|
||||
</button>
|
||||
<div className={`dropdown-menu ${rightOpen ? 'open' : ''}`}>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 0 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(0)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={Berry} width={24} height={24} alt='' />
|
||||
Normal Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 1 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(1)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={PoisonBerry} width={24} height={24} alt='' />
|
||||
Poison Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 2 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(2)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={SlowBerry} width={24} height={24} alt='' />
|
||||
Slow Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 3 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(3)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={UltraBerry} width={24} height={24} alt='' />
|
||||
Ultra Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 4 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(4)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={SpeedyBerry} width={24} height={24} alt='' />
|
||||
Speedy Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 5 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(5)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={CoinBerry} width={24} height={24} alt='' />
|
||||
Coin Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 5 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(6)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<RainbowBerry />
|
||||
Random Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 5 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(7)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={AntiBerry} width={24} height={24} alt='' />
|
||||
Anti Berry
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
197
src/app/page.tsx
@@ -1,130 +1,151 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect } from 'react'
|
||||
import './Installs.css'
|
||||
import { useGlobal } from './GlobalProvider'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import {
|
||||
faCheck,
|
||||
faShieldHalved,
|
||||
faWarning
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import axios from 'axios'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import './Installs.css'
|
||||
import { format } from 'date-fns'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { message } from '@tauri-apps/plugin-dialog'
|
||||
import { useGlobal } from './GlobalProvider'
|
||||
|
||||
export default function Installs () {
|
||||
const {
|
||||
downloadProgress,
|
||||
showPopup,
|
||||
setShowPopup,
|
||||
setPopupMode,
|
||||
setFadeOut,
|
||||
setSelectedVersionList,
|
||||
setVersionList,
|
||||
downloadedVersionsConfig,
|
||||
normalConfig,
|
||||
setSelectedGame,
|
||||
getListOfGames,
|
||||
getVersionsAmountData,
|
||||
setCategory
|
||||
setManagingVersion
|
||||
} = useGlobal()
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
if (!showPopup) return
|
||||
setSelectedVersionList([])
|
||||
}, [normalConfig, setSelectedVersionList, showPopup])
|
||||
setVersionList(null)
|
||||
;(async () => {
|
||||
try {
|
||||
while (normalConfig != null) {
|
||||
const useWine = normalConfig.settings.useWineOnUnixWhenNeeded
|
||||
const res = await axios.get(
|
||||
'https://berrydash.lncvrt.xyz/database/launcher/versions.php'
|
||||
)
|
||||
const p = platform()
|
||||
const filtered = res.data.filter((d: { platforms: string[] }) =>
|
||||
p === 'macos' || p === 'linux'
|
||||
? useWine
|
||||
? d.platforms.includes('windows') || d.platforms.includes(p)
|
||||
: d.platforms.includes(p)
|
||||
: d.platforms.includes(p)
|
||||
)
|
||||
setVersionList(filtered)
|
||||
break
|
||||
}
|
||||
} catch {
|
||||
setVersionList([])
|
||||
}
|
||||
})()
|
||||
}, [normalConfig, setSelectedVersionList, setVersionList, showPopup])
|
||||
|
||||
return (
|
||||
<div className='mx-4 mt-4'>
|
||||
<div className='flex justify-between items-center mb-4'>
|
||||
<p className='text-3xl'>Games</p>
|
||||
<p className='text-3xl'>Installs</p>
|
||||
<button
|
||||
className='button btntheme1'
|
||||
className='button text-3xl'
|
||||
onClick={() => {
|
||||
setSelectedGame(null)
|
||||
setPopupMode(0)
|
||||
setShowPopup(true)
|
||||
setFadeOut(false)
|
||||
}}
|
||||
title='Click to download more games.'
|
||||
disabled={downloadProgress.length != 0}
|
||||
>
|
||||
Download game
|
||||
Download new version
|
||||
</button>
|
||||
</div>
|
||||
<div className='downloads-container'>
|
||||
<div
|
||||
className={`downloads-scroll ${
|
||||
platform() == 'windows'
|
||||
? 'h-[calc(100vh-116px)]'
|
||||
: 'h-[calc(100vh-84px)]'
|
||||
}`}
|
||||
>
|
||||
{downloadedVersionsConfig &&
|
||||
Object.keys(downloadedVersionsConfig.list).length ? (
|
||||
getListOfGames()
|
||||
.sort((a, b) => {
|
||||
return a.id - b.id
|
||||
})
|
||||
.map(i => (
|
||||
<div
|
||||
key={i.id}
|
||||
className={'downloads-entry'}
|
||||
title={'Click to view game installs'}
|
||||
onClick={() => {
|
||||
setCategory(-1)
|
||||
router.push('/game?id=' + i.id)
|
||||
}}
|
||||
>
|
||||
<div className='h-18 w-screen relative'>
|
||||
<p className='text-2xl'>{i.name}</p>
|
||||
|
||||
<div className='flex gap-2 absolute left-0 bottom-0'>
|
||||
<div
|
||||
className='entry-info-item'
|
||||
title='The amount of versions installed of this game in installed/installable format.'
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
<p>
|
||||
{(() => {
|
||||
const data = getVersionsAmountData(i.id)
|
||||
if (!data) return 'N/A'
|
||||
return `${data.installed}/${data.total}`
|
||||
})()}{' '}
|
||||
versions installed
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item'
|
||||
hidden={!i.official}
|
||||
title='This game is official.'
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCheck} color='#19c84b' />
|
||||
<p>Official</p>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item'
|
||||
hidden={i.official}
|
||||
title={
|
||||
i.verified
|
||||
? 'This game is verified to be safe'
|
||||
: 'This game is not verified to be save. Proceed with caution.'
|
||||
<div className='downloads-scroll'>
|
||||
{downloadedVersionsConfig && downloadedVersionsConfig.list.length ? (
|
||||
downloadedVersionsConfig.list
|
||||
.sort((a, b) => b.version.id - a.version.id)
|
||||
.map((entry, i) => (
|
||||
<div key={i} className='downloads-entry'>
|
||||
<div className='flex flex-col'>
|
||||
<p className='text-2xl'>
|
||||
Berry Dash v{entry.version.displayName}
|
||||
</p>
|
||||
<p className='text-gray-400 text-md'>
|
||||
Installed{' '}
|
||||
{format(new Date(entry.installDate), 'MM/dd/yyyy')}
|
||||
</p>
|
||||
</div>
|
||||
<div className='flex flex-row items-center gap-2'>
|
||||
<button
|
||||
className='button'
|
||||
onClick={async () => {
|
||||
setManagingVersion(entry)
|
||||
setPopupMode(2)
|
||||
setShowPopup(true)
|
||||
setFadeOut(false)
|
||||
}}
|
||||
>
|
||||
Manage
|
||||
</button>
|
||||
<button
|
||||
className='button button-green'
|
||||
onClick={async () => {
|
||||
let plat = platform()
|
||||
let willUseWine = false
|
||||
let cfg = null
|
||||
while (normalConfig != null) {
|
||||
cfg = normalConfig
|
||||
break
|
||||
}
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={i.verified ? faShieldHalved : faWarning}
|
||||
color={i.verified ? '#19c84b' : '#ffc800'}
|
||||
/>
|
||||
<p>{i.verified ? 'Verified' : 'Unverified'}</p>
|
||||
</div>
|
||||
</div>
|
||||
if (plat === 'macos' || plat === 'linux') {
|
||||
if (
|
||||
!entry.version.platforms.includes(plat) &&
|
||||
entry.version.platforms.includes('windows')
|
||||
) {
|
||||
if (
|
||||
cfg != null &&
|
||||
!cfg.settings.useWineOnUnixWhenNeeded
|
||||
) {
|
||||
await message(
|
||||
'Wine support is disabled in settings and this version requires wine',
|
||||
{
|
||||
title: 'Wine is needed to load this version',
|
||||
kind: 'error'
|
||||
}
|
||||
)
|
||||
return
|
||||
}
|
||||
plat = 'windows'
|
||||
willUseWine = true
|
||||
}
|
||||
}
|
||||
invoke('launch_game', {
|
||||
name: entry.version.version,
|
||||
executable:
|
||||
entry.version.executables[
|
||||
entry.version.platforms.indexOf(plat)
|
||||
],
|
||||
wine: willUseWine,
|
||||
wineCommand: cfg?.settings.wineOnUnixCommand
|
||||
})
|
||||
}}
|
||||
>
|
||||
Launch
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className='flex justify-center items-center h-full'>
|
||||
<p className='text-3xl'>No games installed</p>
|
||||
<p className='text-3xl'>No versions installed</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,35 +1,37 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Setting } from '@/componets/Setting'
|
||||
import { writeNormalConfig } from '@/lib/BazookaManager'
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { copyToClipboard } from '@/lib/Clipboard'
|
||||
import { Setting } from '../componets/Setting'
|
||||
import { writeNormalConfig } from '../util/BazookaManager'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { useGlobal } from '../GlobalProvider'
|
||||
|
||||
export default function Settings () {
|
||||
const [allowNotifications, setAllowNotifications] = useState(false)
|
||||
const [alwaysShowGamesInSidebar, setAlwaysShowGamesInSidebar] =
|
||||
const [checkForNewVersionOnLoad, setCheckForNewVersionOnLoad] =
|
||||
useState(false)
|
||||
const [allowNotifications, setAllowNotifications] = useState(false)
|
||||
const [useWineOnUnixWhenNeeded, setUseWineOnUnixWhenNeeded] = useState(false)
|
||||
const [wineOnUnixCommand, setWineOnUnixCommand] = useState('wine %path%')
|
||||
const [theme, setTheme] = useState(0)
|
||||
|
||||
const [useWindowsRoundedCorners, setUseWindowsRoundedCorners] =
|
||||
useState(false)
|
||||
const [loaded, setLoaded] = useState(false)
|
||||
const { normalConfig, setNormalConfig, version } = useGlobal()
|
||||
const { normalConfig } = useGlobal()
|
||||
|
||||
useEffect(() => {
|
||||
;(async () => {
|
||||
while (normalConfig != null) {
|
||||
setAllowNotifications(normalConfig.settings.allowNotifications)
|
||||
setAlwaysShowGamesInSidebar(
|
||||
normalConfig.settings.alwaysShowGamesInSidebar
|
||||
setCheckForNewVersionOnLoad(
|
||||
normalConfig.settings.checkForNewVersionOnLoad
|
||||
)
|
||||
setUseWineOnUnixWhenNeeded(
|
||||
normalConfig.settings.useWineOnUnixWhenNeeded
|
||||
)
|
||||
setWineOnUnixCommand(normalConfig.settings.wineOnUnixCommand)
|
||||
setTheme(normalConfig.settings.theme)
|
||||
setAllowNotifications(normalConfig.settings.allowNotifications)
|
||||
setUseWindowsRoundedCorners(
|
||||
normalConfig.settings.useWindowsRoundedCorners
|
||||
)
|
||||
setLoaded(true)
|
||||
break
|
||||
}
|
||||
@@ -40,146 +42,80 @@ export default function Settings () {
|
||||
<>
|
||||
<p className='text-3xl ml-4 mt-4'>Settings</p>
|
||||
{loaded && (
|
||||
<div className='ml-4 mt-4 bg-(--col1) border border-(--col3) rounded-lg p-4 w-fit h-fit'>
|
||||
<div className='ml-4 mt-4 bg-[#161616] border border-[#242424] rounded-lg p-4 w-fit h-fit'>
|
||||
<Setting
|
||||
label='Check for new version on load'
|
||||
value={checkForNewVersionOnLoad}
|
||||
onChange={async () => {
|
||||
while (normalConfig != null) {
|
||||
setCheckForNewVersionOnLoad(!checkForNewVersionOnLoad)
|
||||
normalConfig.settings.checkForNewVersionOnLoad =
|
||||
!checkForNewVersionOnLoad
|
||||
await writeNormalConfig(normalConfig)
|
||||
break
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Setting
|
||||
label='Allow sending notifications'
|
||||
value={allowNotifications}
|
||||
onChange={async () => {
|
||||
if (!normalConfig) return
|
||||
setAllowNotifications(!allowNotifications)
|
||||
setNormalConfig({
|
||||
...normalConfig,
|
||||
settings: {
|
||||
...normalConfig.settings,
|
||||
allowNotifications: !allowNotifications
|
||||
}
|
||||
})
|
||||
await writeNormalConfig({
|
||||
...normalConfig,
|
||||
settings: {
|
||||
...normalConfig.settings,
|
||||
allowNotifications: !allowNotifications
|
||||
}
|
||||
})
|
||||
while (normalConfig != null) {
|
||||
setAllowNotifications(!allowNotifications)
|
||||
normalConfig.settings.allowNotifications = !allowNotifications
|
||||
await writeNormalConfig(normalConfig)
|
||||
break
|
||||
}
|
||||
}}
|
||||
title='This setting does as you expect, allow the launcher to send notifications for when stuff like downloading is done.'
|
||||
/>
|
||||
<Setting
|
||||
label='Always show games in sidebar'
|
||||
value={alwaysShowGamesInSidebar}
|
||||
onChange={async () => {
|
||||
if (!normalConfig) return
|
||||
setAlwaysShowGamesInSidebar(!alwaysShowGamesInSidebar)
|
||||
setNormalConfig({
|
||||
...normalConfig,
|
||||
settings: {
|
||||
...normalConfig.settings,
|
||||
alwaysShowGamesInSidebar: !alwaysShowGamesInSidebar
|
||||
}
|
||||
})
|
||||
await writeNormalConfig({
|
||||
...normalConfig,
|
||||
settings: {
|
||||
...normalConfig.settings,
|
||||
alwaysShowGamesInSidebar: !alwaysShowGamesInSidebar
|
||||
}
|
||||
})
|
||||
}}
|
||||
title="This setting will make it so when you are on a page like this, the games won't disappear."
|
||||
/>
|
||||
<Setting
|
||||
label='Use wine when needed to launch games'
|
||||
label='Use wine to launch Berry Dash when needed'
|
||||
value={useWineOnUnixWhenNeeded}
|
||||
onChange={async () => {
|
||||
if (!normalConfig) return
|
||||
setUseWineOnUnixWhenNeeded(!useWineOnUnixWhenNeeded)
|
||||
setNormalConfig({
|
||||
...normalConfig,
|
||||
settings: {
|
||||
...normalConfig.settings,
|
||||
useWineOnUnixWhenNeeded: !useWineOnUnixWhenNeeded
|
||||
}
|
||||
})
|
||||
await writeNormalConfig({
|
||||
...normalConfig,
|
||||
settings: {
|
||||
...normalConfig.settings,
|
||||
useWineOnUnixWhenNeeded: !useWineOnUnixWhenNeeded
|
||||
}
|
||||
})
|
||||
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 => {
|
||||
if (!normalConfig) return
|
||||
setWineOnUnixCommand(e.target.value)
|
||||
setNormalConfig({
|
||||
...normalConfig,
|
||||
settings: {
|
||||
...normalConfig.settings,
|
||||
wineOnUnixCommand: e.target.value
|
||||
}
|
||||
})
|
||||
await writeNormalConfig({
|
||||
...normalConfig,
|
||||
settings: {
|
||||
...normalConfig.settings,
|
||||
wineOnUnixCommand: e.target.value
|
||||
}
|
||||
})
|
||||
while (normalConfig != null) {
|
||||
setWineOnUnixCommand(e.target.value)
|
||||
normalConfig.settings.wineOnUnixCommand = e.target.value
|
||||
await writeNormalConfig(normalConfig)
|
||||
break
|
||||
}
|
||||
}}
|
||||
className={`input-field my-1 ${
|
||||
className={`input-field ${
|
||||
platform() == 'linux' && useWineOnUnixWhenNeeded ? '' : 'hidden'
|
||||
}`}
|
||||
></input>
|
||||
<div title='The theme you want the launcher to use.'>
|
||||
<label className='text-lg'>Theme:</label>
|
||||
<select
|
||||
className='ml-2 bg-(--col2) border border-(--col4) rounded-md'
|
||||
value={theme}
|
||||
onChange={async e => {
|
||||
if (!normalConfig) return
|
||||
const newTheme = parseInt(e.target.value)
|
||||
setTheme(newTheme)
|
||||
setNormalConfig({
|
||||
...normalConfig,
|
||||
settings: {
|
||||
...normalConfig.settings,
|
||||
theme: newTheme
|
||||
}
|
||||
<Setting
|
||||
label='Use rounded corners (if supported)'
|
||||
value={useWindowsRoundedCorners}
|
||||
onChange={async () => {
|
||||
while (normalConfig != null) {
|
||||
setUseWindowsRoundedCorners(!useWindowsRoundedCorners)
|
||||
normalConfig.settings.useWindowsRoundedCorners =
|
||||
!useWindowsRoundedCorners
|
||||
await writeNormalConfig(normalConfig)
|
||||
invoke('windows_rounded_corners', {
|
||||
enabled: !useWindowsRoundedCorners
|
||||
})
|
||||
await writeNormalConfig({
|
||||
...normalConfig,
|
||||
settings: {
|
||||
...normalConfig.settings,
|
||||
theme: newTheme
|
||||
}
|
||||
})
|
||||
}}
|
||||
>
|
||||
<option value={0}>Dark (default)</option>
|
||||
<option value={1}>Red</option>
|
||||
<option value={2}>Blue</option>
|
||||
<option value={3}>Purple</option>
|
||||
</select>
|
||||
</div>
|
||||
break
|
||||
}
|
||||
}}
|
||||
className={platform() == 'windows' ? '' : 'hidden'}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<p
|
||||
className='fixed bottom-1.5 right-1.5 rounded-md cursor-pointer px-1 border z-100 transition-colors btntheme1'
|
||||
onClick={async () => {
|
||||
await copyToClipboard(`v${version}`, normalConfig)
|
||||
}}
|
||||
title='The current launcher version.'
|
||||
>
|
||||
v{version}
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
10
src/app/types/DownloadProgress.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { LauncherVersion } from './LauncherVersion'
|
||||
|
||||
export class DownloadProgress {
|
||||
constructor (
|
||||
public version: LauncherVersion,
|
||||
public progress: number,
|
||||
public failed: boolean,
|
||||
public queued: boolean
|
||||
) {}
|
||||
}
|
||||
12
src/app/types/DownloadedVersion.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { LauncherVersion } from './LauncherVersion'
|
||||
|
||||
export class DownloadedVersion {
|
||||
constructor (
|
||||
public version: LauncherVersion,
|
||||
public installDate: number = Date.now()
|
||||
) {}
|
||||
|
||||
static import (data: LauncherVersion) {
|
||||
return new DownloadedVersion(data)
|
||||
}
|
||||
}
|
||||
18
src/app/types/InstallsProps.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { DownloadedVersion } from './DownloadedVersion'
|
||||
import { DownloadProgress } from './DownloadProgress'
|
||||
import { LauncherVersion } from './LauncherVersion'
|
||||
import { NormalConfig } from './NormalConfig'
|
||||
import { VersionsConfig } from './VersionsConfig'
|
||||
|
||||
export type InstallsProps = {
|
||||
downloadProgress: DownloadProgress[]
|
||||
showPopup: boolean
|
||||
setShowPopup: (v: boolean) => void
|
||||
setPopupMode: (v: null | number) => void
|
||||
setFadeOut: (v: boolean) => void
|
||||
setSelectedVersionList: (v: LauncherVersion[]) => void
|
||||
setVersionList: (v: null | LauncherVersion[]) => void
|
||||
downloadedVersionsConfig: VersionsConfig | null
|
||||
normalConfig: NormalConfig | null
|
||||
setManagingVersion: (v: DownloadedVersion | null) => void
|
||||
}
|
||||
8
src/app/types/LauncherVersion.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface LauncherVersion {
|
||||
version: string
|
||||
displayName: string
|
||||
platforms: string[]
|
||||
downloadUrls: string[]
|
||||
executables: string[]
|
||||
id: number
|
||||
}
|
||||
10
src/app/types/LeaderboardEntry.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export interface LeaderboardEntry {
|
||||
username: string
|
||||
userid: bigint
|
||||
value: bigint
|
||||
icon: number
|
||||
overlay: number
|
||||
birdColor: number[]
|
||||
overlayColor: number[]
|
||||
customIcon: string | null
|
||||
}
|
||||
6
src/app/types/LeaderboardResponse.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { LeaderboardEntry } from './LeaderboardEntry'
|
||||
|
||||
export interface LeaderboardResponse {
|
||||
entries: LeaderboardEntry[]
|
||||
customIcons: Record<string, string>
|
||||
}
|
||||
@@ -3,5 +3,4 @@ export type SettingProps = {
|
||||
value: boolean
|
||||
onChange: (val: boolean) => void
|
||||
className?: string
|
||||
title?: string
|
||||
}
|
||||
5
src/app/types/SettingsProps.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { NormalConfig } from './NormalConfig'
|
||||
|
||||
export type SettingsProps = {
|
||||
normalConfig: NormalConfig | null
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
export class SettingsType {
|
||||
constructor (
|
||||
public checkForNewVersionOnLoad: boolean = true,
|
||||
public allowNotifications: boolean = true,
|
||||
public alwaysShowGamesInSidebar: boolean = true,
|
||||
public useWineOnUnixWhenNeeded: boolean = false,
|
||||
public wineOnUnixCommand: string = 'wine %path%',
|
||||
public theme: number = 0
|
||||
public useWindowsRoundedCorners: boolean = false
|
||||
) {}
|
||||
}
|
||||
8
src/app/types/SidebarProps.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { DownloadProgress } from './DownloadProgress'
|
||||
|
||||
export type SidebarProps = {
|
||||
setShowPopup: (v: boolean) => void
|
||||
setPopupMode: (v: null | number) => void
|
||||
setFadeOut: (v: boolean) => void
|
||||
downloadProgress: DownloadProgress[]
|
||||
}
|
||||
16
src/app/types/VersionsConfig.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { DownloadedVersion } from './DownloadedVersion'
|
||||
|
||||
type VersionsConfigData = {
|
||||
version: string
|
||||
list: DownloadedVersion[]
|
||||
}
|
||||
|
||||
export class VersionsConfig {
|
||||
constructor (public version: string, public list: DownloadedVersion[] = []) {}
|
||||
|
||||
static import (data: VersionsConfigData) {
|
||||
const cfg = new VersionsConfig(data.version)
|
||||
cfg.list = [...data.list]
|
||||
return cfg
|
||||
}
|
||||
}
|
||||
135
src/app/util/BazookaManager.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { app } from '@tauri-apps/api'
|
||||
import { NormalConfig } from '../types/NormalConfig'
|
||||
import {
|
||||
BaseDirectory,
|
||||
create,
|
||||
exists,
|
||||
mkdir,
|
||||
readTextFile,
|
||||
writeFile
|
||||
} from '@tauri-apps/plugin-fs'
|
||||
import { decrypt, encrypt } from './Encryption'
|
||||
import { VersionsConfig } from '../types/VersionsConfig'
|
||||
import { getKey } from './KeysHelper'
|
||||
|
||||
export async function readNormalConfig (): Promise<NormalConfig> {
|
||||
const version = await app.getVersion()
|
||||
try {
|
||||
const options = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
const doesFolderExist = await exists('', options)
|
||||
const doesConfigExist = await exists('config.dat', options)
|
||||
if (!doesFolderExist || !doesConfigExist) {
|
||||
if (!doesFolderExist) {
|
||||
await mkdir('', options)
|
||||
}
|
||||
const file = await create('config.dat', options)
|
||||
await file.write(
|
||||
new TextEncoder().encode(
|
||||
await encrypt(
|
||||
JSON.stringify(new NormalConfig(version)),
|
||||
await getKey(2)
|
||||
)
|
||||
)
|
||||
)
|
||||
await file.close()
|
||||
return new NormalConfig(version)
|
||||
}
|
||||
const config = await readTextFile('config.dat', options)
|
||||
return NormalConfig.import(
|
||||
JSON.parse(await decrypt(config, await getKey(2)))
|
||||
)
|
||||
} catch {
|
||||
return new NormalConfig(version)
|
||||
}
|
||||
}
|
||||
|
||||
export async function writeNormalConfig (data: NormalConfig) {
|
||||
const options = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
const doesFolderExist = await exists('', options)
|
||||
const doesConfigExist = await exists('config.dat', options)
|
||||
if (!doesFolderExist || !doesConfigExist) {
|
||||
if (!doesFolderExist) {
|
||||
await mkdir('', options)
|
||||
}
|
||||
const file = await create('config.dat', options)
|
||||
await file.write(
|
||||
new TextEncoder().encode(
|
||||
await encrypt(JSON.stringify(data), await getKey(2))
|
||||
)
|
||||
)
|
||||
await file.close()
|
||||
} else {
|
||||
await writeFile(
|
||||
'config.dat',
|
||||
new TextEncoder().encode(
|
||||
await encrypt(JSON.stringify(data), await getKey(2))
|
||||
),
|
||||
options
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function readVersionsConfig (): Promise<VersionsConfig> {
|
||||
const version = await app.getVersion()
|
||||
try {
|
||||
const options = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
const doesFolderExist = await exists('', options)
|
||||
const doesConfigExist = await exists('versions.dat', options)
|
||||
if (!doesFolderExist || !doesConfigExist) {
|
||||
if (!doesFolderExist) {
|
||||
await mkdir('', options)
|
||||
}
|
||||
const file = await create('versions.dat', options)
|
||||
await file.write(
|
||||
new TextEncoder().encode(
|
||||
await encrypt(
|
||||
JSON.stringify(new VersionsConfig(version)),
|
||||
await getKey(3)
|
||||
)
|
||||
)
|
||||
)
|
||||
await file.close()
|
||||
return new VersionsConfig(version)
|
||||
}
|
||||
const config = await readTextFile('versions.dat', options)
|
||||
return VersionsConfig.import(
|
||||
JSON.parse(await decrypt(config, await getKey(3)))
|
||||
)
|
||||
} catch {
|
||||
return new VersionsConfig(version)
|
||||
}
|
||||
}
|
||||
|
||||
export async function writeVersionsConfig (data: VersionsConfig) {
|
||||
const options = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
const doesFolderExist = await exists('', options)
|
||||
const doesConfigExist = await exists('versions.dat', options)
|
||||
if (!doesFolderExist || !doesConfigExist) {
|
||||
if (!doesFolderExist) {
|
||||
await mkdir('', options)
|
||||
}
|
||||
const file = await create('versions.dat', options)
|
||||
await file.write(
|
||||
new TextEncoder().encode(
|
||||
await encrypt(JSON.stringify(data), await getKey(3))
|
||||
)
|
||||
)
|
||||
await file.close()
|
||||
} else {
|
||||
await writeFile(
|
||||
'versions.dat',
|
||||
new TextEncoder().encode(
|
||||
await encrypt(JSON.stringify(data), await getKey(3))
|
||||
),
|
||||
options
|
||||
)
|
||||
}
|
||||
}
|
||||
45
src/app/util/Encryption.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import CryptoJS from 'crypto-js'
|
||||
import { getKey } from './KeysHelper'
|
||||
|
||||
export async function encrypt (
|
||||
plainText: string,
|
||||
key?: string
|
||||
): Promise<string> {
|
||||
if (!key) key = await getKey(1)
|
||||
const iv = CryptoJS.lib.WordArray.random(16)
|
||||
const encrypted = CryptoJS.AES.encrypt(
|
||||
plainText,
|
||||
CryptoJS.enc.Utf8.parse(key),
|
||||
{
|
||||
iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
)
|
||||
const combined = iv.concat(encrypted.ciphertext)
|
||||
return CryptoJS.enc.Base64.stringify(combined)
|
||||
}
|
||||
|
||||
export async function decrypt (dataB64: string, key?: string): Promise<string> {
|
||||
if (!key) key = await getKey(0)
|
||||
const data = CryptoJS.enc.Base64.parse(dataB64)
|
||||
const iv = CryptoJS.lib.WordArray.create(data.words.slice(0, 4), 16)
|
||||
const ciphertext = CryptoJS.lib.WordArray.create(
|
||||
data.words.slice(4),
|
||||
data.sigBytes - 16
|
||||
)
|
||||
const cipherParams = CryptoJS.lib.CipherParams.create({ ciphertext })
|
||||
|
||||
const decrypted = CryptoJS.AES.decrypt(
|
||||
cipherParams,
|
||||
CryptoJS.enc.Utf8.parse(key),
|
||||
{
|
||||
iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
)
|
||||
const result = decrypted.toString(CryptoJS.enc.Utf8)
|
||||
if (!result) throw new Error(await encrypt('-997'))
|
||||
return result
|
||||
}
|
||||
11
src/app/util/KeysHelper.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
|
||||
export async function getKey (key: number): Promise<string> {
|
||||
try {
|
||||
const message = await invoke('get_keys_config', { key })
|
||||
return message as string
|
||||
} catch (error) {
|
||||
console.error('Failed to get key from Tauri backend', error)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 88 KiB |
@@ -1,17 +0,0 @@
|
||||
type ProgressBarProps = {
|
||||
progress: number
|
||||
className?: string
|
||||
}
|
||||
|
||||
export default function ProgressBar ({ progress, className }: ProgressBarProps) {
|
||||
return (
|
||||
<div
|
||||
className={`w-full bg-(--col1) border border-(--col5) rounded-full h-4 overflow-hidden ${className}`}
|
||||
>
|
||||
<div
|
||||
className='bg-(--col8) border-r border-r-(--col5) h-full'
|
||||
style={{ width: `${progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
.sidebar {
|
||||
@apply fixed top-0 left-0 w-60 h-screen bg-(--col1) flex flex-col border-e border-(--col2) z-1;
|
||||
}
|
||||
|
||||
.sidebar-downloads {
|
||||
@apply text-[#bdbdbd] fixed bottom-2 left-2 bg-(--col2) rounded-lg border border-(--col3) px-4 py-3 text-xl cursor-pointer transition-colors duration-[0.25s] opacity-75;
|
||||
}
|
||||
|
||||
.sidebar-downloads:hover {
|
||||
@apply text-white opacity-100;
|
||||
@apply bg-(--col3) border-(--col4);
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
@apply flex flex-col px-4 space-y-1;
|
||||
}
|
||||
|
||||
.link {
|
||||
@apply text-[#bdbdbd] p-2 rounded-md no-underline cursor-pointer transition-colors duration-[0.25s] border border-transparent;
|
||||
}
|
||||
|
||||
.link.active {
|
||||
@apply bg-(--col2) border-(--col3);
|
||||
}
|
||||
|
||||
.link.active,
|
||||
.link:hover {
|
||||
@apply text-white;
|
||||
}
|
||||
|
||||
.link.active:hover {
|
||||
@apply bg-(--col3) border-(--col4);
|
||||
}
|
||||
|
||||
.sidebar ::-webkit-scrollbar {
|
||||
@apply hidden;
|
||||
}
|
||||
|
||||
.macos-drag {
|
||||
@apply h-7 fixed top-0 left-0 w-60 -z-10;
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import './Sidebar.css'
|
||||
import Icon from '@/assets/Icon.png'
|
||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import {
|
||||
faCog,
|
||||
faDownload,
|
||||
faGamepad,
|
||||
faHexagonNodes,
|
||||
faLayerGroup
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { faDiscord } from '@fortawesome/free-brands-svg-icons'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { Lexend } from 'next/font/google'
|
||||
import React from 'react'
|
||||
|
||||
const lexend = Lexend({
|
||||
subsets: ['latin']
|
||||
})
|
||||
|
||||
export default function Sidebar () {
|
||||
const {
|
||||
normalConfig,
|
||||
getListOfGames,
|
||||
setShowPopup,
|
||||
setPopupMode,
|
||||
setFadeOut,
|
||||
downloadProgress,
|
||||
downloadedVersionsConfig,
|
||||
getVersionInfo,
|
||||
category,
|
||||
setCategory
|
||||
} = useGlobal()
|
||||
|
||||
const pathname = usePathname()
|
||||
const params = useSearchParams()
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<aside className='sidebar'>
|
||||
<div
|
||||
className='macos-drag'
|
||||
hidden={platform() != 'macos'}
|
||||
onMouseDown={e => {
|
||||
if (e.buttons === 1) {
|
||||
if (e.detail === 2) {
|
||||
getCurrentWindow().toggleMaximize()
|
||||
} else {
|
||||
getCurrentWindow().startDragging()
|
||||
}
|
||||
}
|
||||
}}
|
||||
></div>
|
||||
<div
|
||||
className={`flex items-center h-10 w-60 ${
|
||||
(platform() == 'windows' ? 'pl-1 pt-1' : 'pl-2 pt-2') +
|
||||
(platform() == 'macos' ? ' mt-7' : '')
|
||||
}`}
|
||||
onMouseDown={e => {
|
||||
if (platform() != 'macos') return
|
||||
if (e.buttons === 1) {
|
||||
if (e.detail === 2) {
|
||||
getCurrentWindow().toggleMaximize()
|
||||
} else {
|
||||
getCurrentWindow().startDragging()
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Image draggable={false} src={Icon} width={36} height={36} alt='' />
|
||||
<p className={`ml-1 text-[16px] whitespace-nowrap ${lexend.className}`}>
|
||||
Lncvrt Games Launcher
|
||||
</p>
|
||||
</div>
|
||||
<nav className='nav-links overflow-auto pt-2'>
|
||||
<Link
|
||||
draggable={false}
|
||||
href='/'
|
||||
className={`link relative flex items-center ${
|
||||
pathname === '/' || pathname.startsWith('/game') ? 'active' : ''
|
||||
}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faHexagonNodes} className='mr-2' /> Games
|
||||
</Link>
|
||||
{getListOfGames()
|
||||
.sort((a, b) => {
|
||||
return a.id - b.id
|
||||
})
|
||||
.map(i => (
|
||||
<React.Fragment key={i.id}>
|
||||
<div
|
||||
draggable={false}
|
||||
className={`link ${
|
||||
(pathname === '/game' &&
|
||||
Number(params.get('id') || 0) == i.id) ||
|
||||
(i.id == 1 && pathname === '/game/berrydash/leaderboards')
|
||||
? 'active'
|
||||
: ''
|
||||
} ml-auto w-50 ${
|
||||
normalConfig?.settings.alwaysShowGamesInSidebar ||
|
||||
pathname === '/' ||
|
||||
pathname.startsWith('/game')
|
||||
? ''
|
||||
: 'hidden'
|
||||
}`}
|
||||
onClick={() => {
|
||||
setCategory(-1)
|
||||
router.push('/game?id=' + i.id)
|
||||
}}
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<FontAwesomeIcon
|
||||
icon={
|
||||
Object.entries(i.categoryNames).length > 0
|
||||
? faLayerGroup
|
||||
: faGamepad
|
||||
}
|
||||
className='mr-1'
|
||||
/>
|
||||
<span className='truncate max-w-full'>{i.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
{Object.entries(i.categoryNames)
|
||||
.sort(([a], [b]) => Number(b) - Number(a))
|
||||
.filter(([key]) => {
|
||||
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 === i.id && info.category === Number(key)
|
||||
}).length
|
||||
|
||||
return count >= 1
|
||||
})
|
||||
.map(([key, value]) => (
|
||||
<div
|
||||
key={`${i.id}-${key}`}
|
||||
draggable={false}
|
||||
className={`link ${
|
||||
(pathname === '/game' &&
|
||||
Number(params.get('id') || 0) == i.id) ||
|
||||
(i.id == 1 &&
|
||||
pathname === '/game/berrydash/leaderboards' &&
|
||||
category == Number(key))
|
||||
? 'active'
|
||||
: ''
|
||||
} ml-auto w-47.5 ${
|
||||
normalConfig?.settings.alwaysShowGamesInSidebar ||
|
||||
pathname === '/' ||
|
||||
pathname.startsWith('/game')
|
||||
? ''
|
||||
: 'hidden'
|
||||
}`}
|
||||
onClick={() => {
|
||||
setCategory(Number(key))
|
||||
router.push('/game?id=' + i.id)
|
||||
}}
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<FontAwesomeIcon icon={faGamepad} className='mr-1' />
|
||||
<span className='truncate max-w-full'>{value}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
<Link
|
||||
draggable={false}
|
||||
href='/settings'
|
||||
className={`link ${pathname === '/settings' ? 'active' : ''}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCog} className='mr-1' /> Settings
|
||||
</Link>
|
||||
<button
|
||||
onClick={() => openUrl('https://games.lncvrt.xyz/discord')}
|
||||
className='link mr-auto'
|
||||
>
|
||||
<FontAwesomeIcon icon={faDiscord} className='mr-1' /> Community
|
||||
</button>
|
||||
</nav>
|
||||
<div
|
||||
className='sidebar-downloads'
|
||||
hidden={downloadProgress.length == 0}
|
||||
onClick={() => {
|
||||
setPopupMode(1)
|
||||
setShowPopup(true)
|
||||
setFadeOut(false)
|
||||
}}
|
||||
>
|
||||
<p>
|
||||
<FontAwesomeIcon icon={faDownload} /> Downloads
|
||||
</p>
|
||||
</div>
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import ProgressBar from '../ProgressBar'
|
||||
import { formatEtaSmart } from '@/lib/Util'
|
||||
|
||||
export default function DownloadsPopup () {
|
||||
const {
|
||||
downloadProgress,
|
||||
getVersionInfo,
|
||||
setDownloadProgress,
|
||||
downloadQueue,
|
||||
setDownloadQueue
|
||||
} = useGlobal()
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className='text-xl text-center'>Downloads</p>
|
||||
<div className='popup-content'>
|
||||
{downloadProgress.map((v, i) => {
|
||||
const queuePosition = downloadQueue.indexOf(v.version)
|
||||
return (
|
||||
<div key={i} className='popup-entry flex flex-col justify-between'>
|
||||
<p className='text-2xl text-center'>
|
||||
{getVersionInfo(v.version)?.displayName}
|
||||
</p>
|
||||
<div className='mt-6.25 flex items-center justify-between'>
|
||||
{v.failed || v.queued ? (
|
||||
<div className='flex items-center justify-between w-full'>
|
||||
<span
|
||||
className={`${
|
||||
v.failed ? 'text-red-500' : 'text-yellow-300'
|
||||
} inline-block text-center flex-1`}
|
||||
>
|
||||
{v.failed
|
||||
? 'Download failed'
|
||||
: queuePosition === 0
|
||||
? 'Starting soon...'
|
||||
: `Queued (Position ${queuePosition + 1})`}
|
||||
</span>
|
||||
<button
|
||||
className='button btntheme3 -ml-1.25'
|
||||
onClick={() => {
|
||||
setDownloadQueue(prev =>
|
||||
prev.filter(id => id !== v.version)
|
||||
)
|
||||
setDownloadProgress(prev =>
|
||||
prev.filter(d => d.version !== v.version)
|
||||
)
|
||||
}}
|
||||
title='Click to remove this version from the download queue.'
|
||||
>
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
) : v.hash_checking || v.finishing ? (
|
||||
<span
|
||||
className={`${
|
||||
v.hash_checking ? 'text-blue-300' : 'text-green-300'
|
||||
} inline-block w-full text-center`}
|
||||
>
|
||||
{v.hash_checking ? 'Verifying file integerty' : '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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import {
|
||||
faCheck,
|
||||
faCode,
|
||||
faDownload,
|
||||
faShieldHalved,
|
||||
faWarning
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
|
||||
export default function GamesDownloadPopup () {
|
||||
const { serverVersionList, getVersionsAmountData, setSelectedGame } =
|
||||
useGlobal()
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className='text-xl text-center'>Select a game to download</p>
|
||||
<div className='popup-content'>
|
||||
{serverVersionList?.games
|
||||
.filter(v => {
|
||||
const data = getVersionsAmountData(v.id)
|
||||
if (!data) return false
|
||||
if (data.total > 0) return true
|
||||
})
|
||||
.map((v, i) => (
|
||||
<div key={i} className='popup-entry'>
|
||||
<p className='text-2xl'>{v.name}</p>
|
||||
<div className='flex gap-2'>
|
||||
<div
|
||||
className='entry-info-item btntheme3'
|
||||
title='The amount of versions installed of this game in installed/installable format.'
|
||||
>
|
||||
<p>
|
||||
{(() => {
|
||||
const data = getVersionsAmountData(v.id)
|
||||
if (!data) return 'N/A'
|
||||
return `${data.installed}/${data.total}`
|
||||
})()}{' '}
|
||||
versions installed
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme3'
|
||||
hidden={!v.official}
|
||||
title='This game is official.'
|
||||
>
|
||||
<FontAwesomeIcon icon={faCheck} color='#19c84b' />
|
||||
<p>Official</p>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme3'
|
||||
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
|
||||
icon={v.verified ? faShieldHalved : faWarning}
|
||||
color={v.verified ? '#19c84b' : '#ffc800'}
|
||||
/>
|
||||
<p>{v.verified ? 'Verified' : 'Unverified'}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme3 mt-2'
|
||||
hidden={v.developer == null}
|
||||
title={`The developer of ${v.name} is ${v.developer}.`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCode} color='lightgray' />
|
||||
<p>Developer: {v.developer}</p>
|
||||
</div>
|
||||
<button
|
||||
className='button btntheme3 right-2 bottom-2'
|
||||
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} /> Download
|
||||
</>
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import {
|
||||
faArrowUpRightFromSquare,
|
||||
faCheck,
|
||||
faCode,
|
||||
faHardDrive,
|
||||
faShieldHalved,
|
||||
faWarning
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { useEffect, useState } from 'react'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import { message } from '@tauri-apps/plugin-dialog'
|
||||
import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs'
|
||||
import { writeVersionsConfig } from '@/lib/BazookaManager'
|
||||
import { openFolder } from '@/lib/Util'
|
||||
|
||||
export default function VersionVersionPopup () {
|
||||
const {
|
||||
getGameInfo,
|
||||
getVersionInfo,
|
||||
managingVersion,
|
||||
downloadedVersionsConfig,
|
||||
viewingInfoFromDownloads,
|
||||
setManagingVersion,
|
||||
closePopup,
|
||||
setDownloadedVersionsConfig,
|
||||
setPopupMode,
|
||||
setSelectedVersionList,
|
||||
downloadVersions
|
||||
} = useGlobal()
|
||||
const [versionSize, setVersionSize] = useState<number>(0)
|
||||
|
||||
useEffect(() => {
|
||||
if (viewingInfoFromDownloads) return
|
||||
invoke<string>('folder_size', {
|
||||
version: managingVersion
|
||||
}).then(size => {
|
||||
setVersionSize(Number(size))
|
||||
})
|
||||
}, [managingVersion, setVersionSize, viewingInfoFromDownloads])
|
||||
|
||||
if (!managingVersion || !downloadedVersionsConfig) return <></>
|
||||
|
||||
const versionInfo = getVersionInfo(managingVersion)
|
||||
const gameInfo = getGameInfo(versionInfo?.game)
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className='text-xl text-center'>Viewing {versionInfo?.displayName}</p>
|
||||
<div className='popup-content flex flex-col items-center justify-center gap-2 h-full'>
|
||||
<div
|
||||
className='entry-info-item btntheme2'
|
||||
hidden={viewingInfoFromDownloads}
|
||||
>
|
||||
<p>
|
||||
Installed{' '}
|
||||
{new Intl.DateTimeFormat(undefined).format(
|
||||
downloadedVersionsConfig.list[managingVersion] ?? 0
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme2'
|
||||
hidden={!versionInfo || versionInfo.releaseDate == 0}
|
||||
>
|
||||
<p>
|
||||
Released{' '}
|
||||
{new Intl.DateTimeFormat(undefined).format(
|
||||
versionInfo?.releaseDate ? versionInfo.releaseDate * 1000 : 0
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div className='entry-info-item btntheme2' hidden={!gameInfo?.official}>
|
||||
<FontAwesomeIcon icon={faCheck} color='#19c84b' />
|
||||
<p>Official</p>
|
||||
</div>
|
||||
<div className='entry-info-item btntheme2' hidden={gameInfo?.official}>
|
||||
<FontAwesomeIcon
|
||||
icon={gameInfo?.verified ? faShieldHalved : faWarning}
|
||||
color={gameInfo?.verified ? '#19c84b' : '#ffc800'}
|
||||
/>
|
||||
<p>{gameInfo?.verified ? 'Verified' : 'Unverified'}</p>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme2'
|
||||
hidden={gameInfo?.developer == null}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCode} color='lightgray' />
|
||||
<p>Developer: {gameInfo?.developer}</p>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme2'
|
||||
hidden={viewingInfoFromDownloads}
|
||||
>
|
||||
<FontAwesomeIcon icon={faHardDrive} color='lightgray' />
|
||||
<p>
|
||||
Size on disk:{' '}
|
||||
{versionSize && versionSize > 0
|
||||
? prettyBytes(versionSize, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
})
|
||||
: 'N/A'}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme2'
|
||||
hidden={!viewingInfoFromDownloads}
|
||||
>
|
||||
<FontAwesomeIcon icon={faHardDrive} color='lightgray' />
|
||||
<p>
|
||||
Size when downloaded (zipped):{' '}
|
||||
{versionInfo
|
||||
? prettyBytes(versionInfo.size, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
})
|
||||
: 'Loading...'}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme2'
|
||||
onClick={async () => {
|
||||
if (!versionInfo) return
|
||||
await message(atob(versionInfo.changelog), {
|
||||
title: 'Changelog for ' + versionInfo.displayName,
|
||||
kind: 'info'
|
||||
})
|
||||
}}
|
||||
hidden={!versionInfo?.changelog}
|
||||
>
|
||||
<p>View Changelog</p>
|
||||
<FontAwesomeIcon icon={faArrowUpRightFromSquare} color='lightgray' />
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme2'
|
||||
onClick={async () => openFolder(managingVersion)}
|
||||
title="Click to browse the game's files."
|
||||
hidden={viewingInfoFromDownloads}
|
||||
>
|
||||
Open Folder
|
||||
<FontAwesomeIcon icon={faArrowUpRightFromSquare} color='lightgray' />
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme2'
|
||||
onClick={async () => {
|
||||
closePopup()
|
||||
|
||||
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)
|
||||
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.'
|
||||
hidden={viewingInfoFromDownloads}
|
||||
>
|
||||
Uninstall
|
||||
</div>
|
||||
<div
|
||||
className='entry-info-item btntheme2'
|
||||
onClick={async () => {
|
||||
//change popup to downloads
|
||||
setManagingVersion(null)
|
||||
setPopupMode(1)
|
||||
|
||||
//uninstall
|
||||
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)
|
||||
return updatedConfig
|
||||
})
|
||||
|
||||
if (
|
||||
await exists('game/' + managingVersion, {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
})
|
||||
)
|
||||
await remove('game/' + managingVersion, {
|
||||
baseDir: BaseDirectory.AppLocalData,
|
||||
recursive: true
|
||||
})
|
||||
|
||||
//reinstall
|
||||
setSelectedVersionList([managingVersion])
|
||||
downloadVersions([managingVersion])
|
||||
}}
|
||||
title="Click to reinstall this game. This will NOT remove any progress or any save files. This WILL uninstall any modifications to the game's executable files."
|
||||
hidden={viewingInfoFromDownloads}
|
||||
>
|
||||
Reinstall
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
import { useGlobal } from '@/app/GlobalProvider'
|
||||
import { faAdd, faInfo, faRemove } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
|
||||
export default function VersionsDownloadPopup () {
|
||||
const {
|
||||
selectedVersionList,
|
||||
setSelectedVersionList,
|
||||
setManagingVersion,
|
||||
setPopupMode,
|
||||
getSpecialVersionsList,
|
||||
selectedGame,
|
||||
setViewingInfoFromDownloads,
|
||||
downloadedVersionsConfig,
|
||||
downloadVersions,
|
||||
getGameInfo
|
||||
} = useGlobal()
|
||||
if (!selectedGame) return <></>
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className='text-xl text-center'>Select versions to download</p>
|
||||
<div className='popup-content'>
|
||||
{getSpecialVersionsList(selectedGame).map((v, i) => (
|
||||
<div key={i} className='popup-entry'>
|
||||
<div className='flex items-center'>
|
||||
<p
|
||||
className={`text-2xl truncate ${
|
||||
selectedVersionList.includes(v.id)
|
||||
? 'max-w-84.5'
|
||||
: 'max-w-91.5'
|
||||
}`}
|
||||
>
|
||||
{v.displayName}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
className='button btntheme3 right-20.75 bottom-1.75'
|
||||
onClick={() => {
|
||||
setSelectedVersionList(prev =>
|
||||
prev.includes(v.id)
|
||||
? prev.filter(i => i !== 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) ? (
|
||||
<>
|
||||
<FontAwesomeIcon icon={faRemove} /> Remove
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<FontAwesomeIcon icon={faAdd} /> Add
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
className='button btntheme3 right-1.5 bottom-1.75'
|
||||
onClick={() => {
|
||||
setManagingVersion(v.id)
|
||||
setViewingInfoFromDownloads(true)
|
||||
setPopupMode(2)
|
||||
}}
|
||||
title='Click to view version info'
|
||||
>
|
||||
<FontAwesomeIcon icon={faInfo} /> Info
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className='flex justify-center'>
|
||||
<button
|
||||
className='button btntheme1 w-fit mt-2 -mb-4'
|
||||
onClick={() => {
|
||||
if (downloadedVersionsConfig) {
|
||||
downloadVersions(selectedVersionList)
|
||||
setPopupMode(1)
|
||||
}
|
||||
}}
|
||||
disabled={selectedVersionList.length == 0}
|
||||
title={
|
||||
selectedVersionList.length == 0
|
||||
? 'Select at least one version to download'
|
||||
: `Download ${selectedVersionList.length} version${
|
||||
selectedVersionList.length == 1 ? '' : 's'
|
||||
} of ${getGameInfo(selectedGame)?.name}`
|
||||
}
|
||||
>
|
||||
Download {selectedVersionList.length} version
|
||||
{selectedVersionList.length == 1 ? '' : 's'}
|
||||
</button>
|
||||
<button
|
||||
className='button btntheme1 w-fit mt-2 ml-2 -mb-4'
|
||||
onClick={() => {
|
||||
const allIds = getSpecialVersionsList(selectedGame).map(v => v.id)
|
||||
setSelectedVersionList(prev =>
|
||||
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 ===
|
||||
getSpecialVersionsList(selectedGame).length
|
||||
? 'Deselect All'
|
||||
: 'Select All'}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
import { app } from '@tauri-apps/api'
|
||||
import { NormalConfig } from '@/types/NormalConfig'
|
||||
import {
|
||||
BaseDirectory,
|
||||
create,
|
||||
exists,
|
||||
mkdir,
|
||||
readTextFile,
|
||||
writeFile
|
||||
} from '@tauri-apps/plugin-fs'
|
||||
import { VersionsConfig } from '@/types/VersionsConfig'
|
||||
|
||||
export async function readNormalConfig (): Promise<NormalConfig> {
|
||||
const version = await app.getVersion()
|
||||
try {
|
||||
const options = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
const doesFolderExist = await exists('', options)
|
||||
const doesConfigExist = await exists('config.json', options)
|
||||
if (!doesFolderExist || !doesConfigExist) {
|
||||
if (!doesFolderExist) {
|
||||
await mkdir('', options)
|
||||
}
|
||||
const file = await create('config.json', options)
|
||||
await file.write(
|
||||
new TextEncoder().encode(
|
||||
JSON.stringify(new NormalConfig(version), null, 2)
|
||||
)
|
||||
)
|
||||
await file.close()
|
||||
return new NormalConfig(version)
|
||||
}
|
||||
const config = await readTextFile('config.json', options)
|
||||
const raw = JSON.parse(config)
|
||||
if (
|
||||
raw.settings &&
|
||||
raw.settings.theme &&
|
||||
(raw.version == '1.0.0' ||
|
||||
raw.version == '1.1.0' ||
|
||||
raw.version == '1.1.1' ||
|
||||
raw.version == '1.2.0' ||
|
||||
raw.version == '1.3.0' ||
|
||||
raw.version == '1.3.1' ||
|
||||
raw.version == '1.4.0' ||
|
||||
raw.version == '1.5.0' ||
|
||||
raw.version == '1.5.1' ||
|
||||
raw.version == '1.5.2' ||
|
||||
raw.version == '1.5.3' ||
|
||||
raw.version == '1.5.4')
|
||||
) {
|
||||
const parsed = Number(raw.settings.theme)
|
||||
if (parsed == 3) raw.settings.theme = 2
|
||||
if (parsed == 4) raw.settings.theme = 3
|
||||
else if (parsed != 0 && parsed != 1) raw.settings.theme = 0
|
||||
}
|
||||
raw.version = version
|
||||
writeNormalConfig(raw)
|
||||
return NormalConfig.import(raw)
|
||||
} catch {
|
||||
return new NormalConfig(version)
|
||||
}
|
||||
}
|
||||
|
||||
export async function writeNormalConfig (data: NormalConfig) {
|
||||
const options = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
const doesFolderExist = await exists('', options)
|
||||
const doesConfigExist = await exists('config.json', options)
|
||||
if (!doesFolderExist || !doesConfigExist) {
|
||||
if (!doesFolderExist) {
|
||||
await mkdir('', options)
|
||||
}
|
||||
const file = await create('config.json', options)
|
||||
await file.write(new TextEncoder().encode(JSON.stringify(data, null, 2)))
|
||||
await file.close()
|
||||
} else {
|
||||
await writeFile(
|
||||
'config.json',
|
||||
new TextEncoder().encode(JSON.stringify(data, null, 2)),
|
||||
options
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function readVersionsConfig (): Promise<VersionsConfig> {
|
||||
const version = await app.getVersion()
|
||||
try {
|
||||
const options = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
const doesFolderExist = await exists('', options)
|
||||
const doesConfigExist = await exists('versions.json', options)
|
||||
if (!doesFolderExist || !doesConfigExist) {
|
||||
if (!doesFolderExist) {
|
||||
await mkdir('', options)
|
||||
}
|
||||
const file = await create('versions.json', options)
|
||||
await file.write(
|
||||
new TextEncoder().encode(
|
||||
JSON.stringify(new VersionsConfig(version), null, 2)
|
||||
)
|
||||
)
|
||||
await file.close()
|
||||
return new VersionsConfig(version)
|
||||
}
|
||||
const config = await readTextFile('versions.json', options)
|
||||
const raw = JSON.parse(config)
|
||||
if (raw.list && raw.timestamps) {
|
||||
raw.list = raw.timestamps
|
||||
delete raw.timestamps
|
||||
|
||||
await writeFile(
|
||||
'versions.json',
|
||||
new TextEncoder().encode(JSON.stringify(raw, null, 2)),
|
||||
options
|
||||
)
|
||||
}
|
||||
raw.version = version
|
||||
writeVersionsConfig(raw)
|
||||
return VersionsConfig.import(raw)
|
||||
} catch {
|
||||
return new VersionsConfig(version)
|
||||
}
|
||||
}
|
||||
|
||||
export async function writeVersionsConfig (data: VersionsConfig) {
|
||||
const options = {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
}
|
||||
const doesFolderExist = await exists('', options)
|
||||
const doesConfigExist = await exists('versions.json', options)
|
||||
if (!doesFolderExist || !doesConfigExist) {
|
||||
if (!doesFolderExist) {
|
||||
await mkdir('', options)
|
||||
}
|
||||
const file = await create('versions.json', options)
|
||||
await file.write(new TextEncoder().encode(JSON.stringify(data, null, 2)))
|
||||
await file.close()
|
||||
} else {
|
||||
await writeFile(
|
||||
'versions.json',
|
||||
new TextEncoder().encode(JSON.stringify(data, null, 2)),
|
||||
options
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
export const GetIconForUser = (user: number) => {
|
||||
if (user == 1) return -1
|
||||
else if (user == 2) return -2
|
||||
else if (user == 4) return -3
|
||||
else if (user == 3) return -4
|
||||
else return 1
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import { NormalConfig } from '@/types/NormalConfig'
|
||||
import { notifyUser } from './Notifications'
|
||||
|
||||
export async function copyToClipboard (
|
||||
text: string,
|
||||
normalConfig: NormalConfig | null
|
||||
) {
|
||||
if (normalConfig?.settings.allowNotifications)
|
||||
await notifyUser('Copied', 'Text "' + text + '" copied to clipboard')
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import {
|
||||
isPermissionGranted,
|
||||
requestPermission,
|
||||
sendNotification
|
||||
} from '@tauri-apps/plugin-notification'
|
||||
|
||||
export async function notifyUser (title: string, body: string) {
|
||||
let permissionGranted = await isPermissionGranted()
|
||||
if (!permissionGranted) {
|
||||
const permission = await requestPermission()
|
||||
permissionGranted = permission === 'granted'
|
||||
}
|
||||
|
||||
if (permissionGranted) {
|
||||
sendNotification({ title, body })
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import { message } from '@tauri-apps/plugin-dialog'
|
||||
import { BaseDirectory, exists, stat } from '@tauri-apps/plugin-fs'
|
||||
import { openPath } from '@tauri-apps/plugin-opener'
|
||||
import { join, appLocalDataDir } from '@tauri-apps/api/path'
|
||||
|
||||
export const openFolder = async (name: string) => {
|
||||
const relativePath = await join('game', name)
|
||||
const basePath = await appLocalDataDir()
|
||||
const absolutePath = await join(basePath, relativePath)
|
||||
|
||||
const folderExists = await exists(relativePath, {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
})
|
||||
|
||||
if (!folderExists) {
|
||||
await message(`Game folder "${absolutePath}" not found.`, {
|
||||
title: 'Folder not found',
|
||||
kind: 'error'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const folderStat = await stat(relativePath, {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
})
|
||||
|
||||
if (folderStat.isFile) {
|
||||
await message(`Game folder "${absolutePath}" not found.`, {
|
||||
title: 'Folder not found',
|
||||
kind: 'error'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
await openPath(absolutePath)
|
||||
}
|
||||
|
||||
export const 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`
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export type BirdColor = [number, number, number]
|
||||
@@ -1,13 +0,0 @@
|
||||
export class DownloadProgress {
|
||||
constructor (
|
||||
public version: string,
|
||||
public progress: number,
|
||||
public progressBytes: number,
|
||||
public failed: boolean,
|
||||
public queued: boolean,
|
||||
public hash_checking: boolean,
|
||||
public finishing: boolean,
|
||||
public speed: number,
|
||||
public etaSecs: number
|
||||
) {}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export interface Game {
|
||||
id: number
|
||||
name: string
|
||||
official: boolean
|
||||
verified: boolean
|
||||
developer: string | null
|
||||
categoryNames: Record<string, string>
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
export interface GameVersion {
|
||||
id: string
|
||||
displayName: string
|
||||
releaseDate: number
|
||||
game: number
|
||||
downloadUrl: string
|
||||
executable: string
|
||||
sha512sum: string
|
||||
size: number
|
||||
place: number
|
||||
changelog: string
|
||||
wine: number | undefined
|
||||
category: number
|
||||
lastRevision: number
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { Game } from './Game'
|
||||
import { GameVersion } from './GameVersion'
|
||||
|
||||
export interface ServerVersionsResponse {
|
||||
versions: GameVersion[]
|
||||
games: Game[]
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
export type VersionsConfigData = {
|
||||
version: string
|
||||
list: Record<string, number>
|
||||
}
|
||||
|
||||
export class VersionsConfig {
|
||||
constructor (
|
||||
public version: string,
|
||||
public list: Record<string, number> = {}
|
||||
) {}
|
||||
|
||||
static import (data: VersionsConfigData) {
|
||||
const cfg = new VersionsConfig(data.version)
|
||||
cfg.list = { ...data.list }
|
||||
return cfg
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2024",
|
||||
"target": "ES2017",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
@@ -11,7 +11,7 @@
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "react-jsx",
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
@@ -22,15 +22,6 @@
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
".next/dev/types/**/*.ts",
|
||||
"**/*.mts",
|
||||
"next.config.ts",
|
||||
"eslint.config.ts"
|
||||
],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
}
|
||||
|
||||