Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3281c4e1a1
|
||
|
|
3a9e0b0358
|
||
|
|
c45e7fb47c
|
||
|
|
c7086fbc31
|
||
|
|
33a1e4e780
|
No files matched your search
@@ -20,8 +20,8 @@
|
||||
"@tauri-apps/plugin-store": "2.4.2",
|
||||
"@tauri-apps/plugin-updater": "2.10.1",
|
||||
"@tauri-apps/plugin-window-state": "2.4.1",
|
||||
"dompurify": "3.3.3",
|
||||
"next": "16.2.3",
|
||||
"dompurify": "3.4.0",
|
||||
"next": "16.2.4",
|
||||
"pretty-bytes": "7.1.0",
|
||||
"react": "19.2.5",
|
||||
"react-dom": "19.2.5",
|
||||
@@ -36,9 +36,9 @@
|
||||
"@types/react-dom": "19.2.3",
|
||||
"crypto-js": "4.2.0",
|
||||
"eslint": "9.39.4",
|
||||
"eslint-config-next": "16.2.3",
|
||||
"eslint-config-next": "16.2.4",
|
||||
"tailwindcss": "4.2.2",
|
||||
"typescript": "6.0.2",
|
||||
"typescript": "6.0.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -77,9 +77,9 @@
|
||||
|
||||
"@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.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="],
|
||||
"@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],
|
||||
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="],
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
|
||||
|
||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
|
||||
|
||||
@@ -111,9 +111,11 @@
|
||||
|
||||
"@fortawesome/react-fontawesome": ["@fortawesome/react-fontawesome@3.3.0", "", { "peerDependencies": { "@fortawesome/fontawesome-svg-core": "~6 || ~7", "react": "^18.0.0 || ^19.0.0" } }, "sha512-EHmHeTf8WgO29sdY3iX/7ekE3gNUdlc2RW6mm/FzELlHFKfTrA9S4MlyquRR+RRCRCn8+jXfLFpLGB2l7wCWyw=="],
|
||||
|
||||
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
||||
"@humanfs/core": ["@humanfs/core@0.19.2", "", { "dependencies": { "@humanfs/types": "^0.15.0" } }, "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA=="],
|
||||
|
||||
"@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
|
||||
"@humanfs/node": ["@humanfs/node@0.16.8", "", { "dependencies": { "@humanfs/core": "^0.19.2", "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ=="],
|
||||
|
||||
"@humanfs/types": ["@humanfs/types@0.15.0", "", {}, "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q=="],
|
||||
|
||||
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
|
||||
|
||||
@@ -181,25 +183,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.2.3", "", {}, "sha512-ZWXyj4uNu4GCWQw9cjRxWlbD+33mcDszIo9iQxFnBX3Wmgq9ulaSJcl6VhuWx5pCWqqD+9W6Wfz7N0lM5lYPMA=="],
|
||||
"@next/env": ["@next/env@16.2.4", "", {}, "sha512-dKkkOzOSwFYe5RX6y26fZgkSpVAlIOJKQHIiydQcrWH6y/97+RceSOAdjZ14Qa3zLduVUy0TXcn+EiM6t4rPgw=="],
|
||||
|
||||
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.2.3", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-nE/b9mht28XJxjTwKs/yk7w4XTaU3t40UHVAky6cjiijdP/SEy3hGsnQMPxmXPTpC7W4/97okm6fngKnvCqVaA=="],
|
||||
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.2.4", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-tOX826JJ96gYK/go18sPUgMq9FK1tqxBFfUCEufJb5XIkWFFmpgU7mahJANKGkHs7F41ir3tReJ3Lv5La0RvhA=="],
|
||||
|
||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-u37KDKTKQ+OQLvY+z7SNXixwo4Q2/IAJFDzU1fYe66IbCE51aDSAzkNDkWmLN0yjTUh4BKBd+hb69jYn6qqqSg=="],
|
||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OXTFFox5EKN1Ym08vfrz+OXxmCcEjT4SFMbNRsWZE99dMqt2Kcusl5MqPXcW232RYkMLQTy0hqgAMEsfEd/l2A=="],
|
||||
|
||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-gHjL/qy6Q6CG3176FWbAKyKh9IfntKZTB3RY/YOJdDFpHGsUDXVH38U4mMNpHVGXmeYW4wj22dMp1lTfmu/bTQ=="],
|
||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-XhpVnUfmYWvD3YrXu55XdcAkQtOnvaI6wtQa8fuF5fGoKoxIUZ0kWPtcOfqJEWngFF/lOS9l3+O9CcownhiQxQ=="],
|
||||
|
||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-U6vtblPtU/P14Y/b/n9ZY0GOxbbIhTFuaFR7F4/uMBidCi2nSdaOFhA0Go81L61Zd6527+yvuX44T4ksnf8T+Q=="],
|
||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-Mx/tjlNA3G8kg14QvuGAJ4xBwPk1tUHq56JxZ8CXnZwz1Etz714soCEzGQQzVMz4bEnGPowzkV6Xrp6wAkEWOQ=="],
|
||||
|
||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-/YV0LgjHUmfhQpn9bVoGc4x4nan64pkhWR5wyEV8yCOfwwrH630KpvRg86olQHTwHIn1z59uh6JwKvHq1h4QEw=="],
|
||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-iVMMp14514u7Nup2umQS03nT/bN9HurK8ufylC3FZNykrwjtx7V1A7+4kvhbDSCeonTVqV3Txnv0Lu+m2oDXNg=="],
|
||||
|
||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-/HiWEcp+WMZ7VajuiMEFGZ6cg0+aYZPqCJD3YJEfpVWQsKYSjXQG06vJP6F1rdA03COD9Fef4aODs3YxKx+RDQ=="],
|
||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-EZOvm1aQWgnI/N/xcWOlnS3RQBk0VtVav5Zo7n4p0A7UKyTDx047k8opDbXgBpHl4CulRqRfbw3QrX2w5UOXMQ=="],
|
||||
|
||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Kt44hGJfZSefebhk/7nIdivoDr3Ugp5+oNz9VvF3GUtfxutucUIHfIO0ZYO8QlOPDQloUVQn4NVC/9JvHRk9hw=="],
|
||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-h9FxsngCm9cTBf71AR4fGznDEDx1hS7+kSEiIRjq5kO1oXWm07DxVGZjCvk0SGx7TSjlUqhI8oOyz7NfwAdPoA=="],
|
||||
|
||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.2.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-O2NZ9ie3Tq6xj5Z5CSwBT3+aWAMW2PIZ4egUi9MaWLkwaehgtB7YZjPm+UpcNpKOme0IQuqDcor7BsW6QBiQBw=="],
|
||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.2.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-3NdJV5OXMSOeJYijX+bjaLge3mJBlh4ybydbT4GFoB/2hAojWHtMhl3CYlYoMrjPuodp0nzFVi4Tj2+WaMg+Ow=="],
|
||||
|
||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.2.3", "", { "os": "win32", "cpu": "x64" }, "sha512-Ibm29/GgB/ab5n7XKqlStkm54qqZE8v2FnijUPBgrd67FWrac45o/RsNlaOWjme/B5UqeWt/8KM4aWBwA1D2Kw=="],
|
||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.2.4", "", { "os": "win32", "cpu": "x64" }, "sha512-kMVGgsqhO5YTYODD9IPGGhA6iprWidQckK3LmPeW08PIFENRmgfb4MjXHO+p//d+ts2rpjvK5gXWzXSMrPl9cw=="],
|
||||
|
||||
"@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=="],
|
||||
|
||||
@@ -405,7 +407,7 @@
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.18", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-VSnGQAOLtP5mib/DPyg2/t+Tlv65NTBz83BJBJvmLVHHuKJVaDOBvJJykiT5TR++em5nfAySPccDZDa4oSrn8A=="],
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.20", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-1AaXxEPfXT+GvTBJFuy4yXVHWJBXa4OdbIebGN/wX5DlsIkU0+wzGnd2lOzokSk51d5LUmqjgBLRLlypLUqInQ=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
|
||||
|
||||
@@ -421,7 +423,7 @@
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001787", "", {}, "sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg=="],
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001788", "", {}, "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ=="],
|
||||
|
||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
|
||||
@@ -461,11 +463,11 @@
|
||||
|
||||
"doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
|
||||
|
||||
"dompurify": ["dompurify@3.3.3", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA=="],
|
||||
"dompurify": ["dompurify@3.4.0", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg=="],
|
||||
|
||||
"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.336", "", {}, "sha512-AbH9q9J455r/nLmdNZes0G0ZKcRX73FicwowalLs6ijwOmCJSRRrLX63lcAlzy9ux3dWK1w1+1nsBJEWN11hcQ=="],
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.340", "", {}, "sha512-908qahOGocRMinT2nM3ajCEM99H4iPdv84eagPP3FfZy/1ZGeOy2CZYzjhms81ckOPCXPlW7LkY4XpxD8r1DrA=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
@@ -493,7 +495,7 @@
|
||||
|
||||
"eslint": ["eslint@9.39.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.5", "@eslint/js": "9.39.4", "@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.14.0", "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.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ=="],
|
||||
|
||||
"eslint-config-next": ["eslint-config-next@16.2.3", "", { "dependencies": { "@next/eslint-plugin-next": "16.2.3", "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-Dnkrylzjof/Az7iNoIQJqD18zTxQZcngir19KJaiRsMnnjpQSVoa6aEg/1Q4hQC+cW90uTlgQYadwL1CYNwFWA=="],
|
||||
"eslint-config-next": ["eslint-config-next@16.2.4", "", { "dependencies": { "@next/eslint-plugin-next": "16.2.4", "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-A6ekXYFj/YQxBPMl45g3e+U8zJo+X2+ZQwcz34pPKjpc/3S4roBA2Rd9xWB4FKuSxhofo1/95WjzmUY+wHrOhg=="],
|
||||
|
||||
"eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.10", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.16.1", "resolve": "^2.0.0-next.6" } }, "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ=="],
|
||||
|
||||
@@ -507,7 +509,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@7.1.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 || ^10.0.0" } }, "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g=="],
|
||||
|
||||
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
|
||||
|
||||
@@ -563,7 +565,7 @@
|
||||
|
||||
"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.7", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q=="],
|
||||
"get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="],
|
||||
|
||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||
|
||||
@@ -587,7 +589,7 @@
|
||||
|
||||
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
||||
|
||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||
"hasown": ["hasown@2.0.3", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg=="],
|
||||
|
||||
"hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
||||
|
||||
@@ -737,7 +739,7 @@
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"next": ["next@16.2.3", "", { "dependencies": { "@next/env": "16.2.3", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.2.3", "@next/swc-darwin-x64": "16.2.3", "@next/swc-linux-arm64-gnu": "16.2.3", "@next/swc-linux-arm64-musl": "16.2.3", "@next/swc-linux-x64-gnu": "16.2.3", "@next/swc-linux-x64-musl": "16.2.3", "@next/swc-win32-arm64-msvc": "16.2.3", "@next/swc-win32-x64-msvc": "16.2.3", "sharp": "^0.34.5" }, "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-9V3zV4oZFza3PVev5/poB9g0dEafVcgNyQ8eTRop8GvxZjV2G15FC5ARuG1eFD42QgeYkzJBJzHghNP8Ad9xtA=="],
|
||||
"next": ["next@16.2.4", "", { "dependencies": { "@next/env": "16.2.4", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.2.4", "@next/swc-darwin-x64": "16.2.4", "@next/swc-linux-arm64-gnu": "16.2.4", "@next/swc-linux-arm64-musl": "16.2.4", "@next/swc-linux-x64-gnu": "16.2.4", "@next/swc-linux-x64-musl": "16.2.4", "@next/swc-win32-arm64-msvc": "16.2.4", "@next/swc-win32-x64-msvc": "16.2.4", "sharp": "^0.34.5" }, "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-kPvz56wF5frc+FxlHI5qnklCzbq53HTwORaWBGdT0vNoKh1Aya9XC8aPauH4NJxqtzbWsS5mAbctm4cr+EkQ2Q=="],
|
||||
|
||||
"node-exports-info": ["node-exports-info@1.6.0", "", { "dependencies": { "array.prototype.flatmap": "^1.3.3", "es-errors": "^1.3.0", "object.entries": "^1.1.9", "semver": "^6.3.1" } }, "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw=="],
|
||||
|
||||
@@ -781,7 +783,7 @@
|
||||
|
||||
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
||||
|
||||
"postcss": ["postcss@8.5.9", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw=="],
|
||||
"postcss": ["postcss@8.5.10", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ=="],
|
||||
|
||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||
|
||||
@@ -895,7 +897,7 @@
|
||||
|
||||
"typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
|
||||
|
||||
"typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
|
||||
"typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
|
||||
|
||||
"typescript-eslint": ["typescript-eslint@8.58.2", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.58.2", "@typescript-eslint/parser": "8.58.2", "@typescript-eslint/typescript-estree": "8.58.2", "@typescript-eslint/utils": "8.58.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ=="],
|
||||
|
||||
@@ -933,13 +935,13 @@
|
||||
|
||||
"@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.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="],
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="],
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.3", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ=="],
|
||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||
|
||||
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "lncvrt-games-launcher",
|
||||
"private": true,
|
||||
"version": "1.9.1",
|
||||
"version": "1.9.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@@ -26,8 +26,8 @@
|
||||
"@tauri-apps/plugin-store": "2.4.2",
|
||||
"@tauri-apps/plugin-updater": "2.10.1",
|
||||
"@tauri-apps/plugin-window-state": "2.4.1",
|
||||
"dompurify": "3.3.3",
|
||||
"next": "16.2.3",
|
||||
"dompurify": "3.4.0",
|
||||
"next": "16.2.4",
|
||||
"pretty-bytes": "7.1.0",
|
||||
"react": "19.2.5",
|
||||
"react-dom": "19.2.5"
|
||||
@@ -42,8 +42,8 @@
|
||||
"@types/react-dom": "19.2.3",
|
||||
"crypto-js": "4.2.0",
|
||||
"eslint": "9.39.4",
|
||||
"eslint-config-next": "16.2.3",
|
||||
"eslint-config-next": "16.2.4",
|
||||
"tailwindcss": "4.2.2",
|
||||
"typescript": "6.0.2"
|
||||
"typescript": "6.0.3"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "lncvrt-games-launcher"
|
||||
version = "1.9.1"
|
||||
version = "1.9.2"
|
||||
authors = ["Lncvrt"]
|
||||
edition = "2024"
|
||||
|
||||
@@ -21,7 +21,7 @@ reqwest = { version = "0.13.2", default-features = false, features = [
|
||||
"stream",
|
||||
"rustls",
|
||||
] }
|
||||
tokio = "1.51.1"
|
||||
tokio = "1.52.1"
|
||||
futures-util = { version = "0.3.32", features = ["io"] }
|
||||
tauri-plugin-decorum = "1.1.1"
|
||||
tauri-plugin-fs = "2.5.0"
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"decorum:allow-show-snap-overlay",
|
||||
"fs:default",
|
||||
"dialog:default",
|
||||
"dialog:allow-open",
|
||||
"notification:default",
|
||||
"clipboard-manager:default",
|
||||
"clipboard-manager:allow-write-text",
|
||||
|
||||
+164
-17
@@ -6,7 +6,7 @@ use openssl::sign::Verifier;
|
||||
use sha2::{Digest, Sha512};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::{OnceLock, RwLock};
|
||||
use std::time::Instant;
|
||||
use std::{
|
||||
fs::{File, create_dir_all},
|
||||
@@ -33,6 +33,19 @@ use std::os::unix::fs::PermissionsExt;
|
||||
#[cfg(not(debug_assertions))]
|
||||
use tauri_plugin_updater::UpdaterExt;
|
||||
|
||||
struct AppState {
|
||||
custom_data_dir: RwLock<Option<PathBuf>>,
|
||||
}
|
||||
|
||||
fn data_dir(app: &AppHandle) -> Result<PathBuf, String> {
|
||||
let state = app.state::<AppState>();
|
||||
let guard = state.custom_data_dir.read().unwrap();
|
||||
match &*guard {
|
||||
Some(p) => Ok(p.clone()),
|
||||
None => app.path().app_local_data_dir().map_err(|e| e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
static CANCEL_MAP: OnceLock<DashMap<String, bool>> = OnceLock::new();
|
||||
|
||||
fn cancel_map() -> &'static DashMap<String, bool> {
|
||||
@@ -120,7 +133,7 @@ async fn unzip_to_dir(app: AppHandle, zip_path: PathBuf, out_dir: PathBuf, name:
|
||||
|
||||
#[tauri::command]
|
||||
fn folder_size(app: AppHandle, version: String) -> String {
|
||||
let path = match app.path().app_local_data_dir() {
|
||||
let path = match data_dir(&app) {
|
||||
Ok(p) => p.join("game").join(&version),
|
||||
Err(_) => return "-1".to_string(),
|
||||
};
|
||||
@@ -160,20 +173,15 @@ async fn download(
|
||||
let _ = app.emit("download-start", format!("{}", name));
|
||||
let window = app.get_webview_window("main").expect("main window missing");
|
||||
|
||||
let downloads_path = match app.path().app_local_data_dir() {
|
||||
Ok(p) => p.join("downloads"),
|
||||
Err(_) => {
|
||||
let _ = &app.emit("download-stop", format!("{}", name));
|
||||
return "-1".to_string();
|
||||
}
|
||||
};
|
||||
let game_path = match app.path().app_local_data_dir() {
|
||||
Ok(p) => p.join("game"),
|
||||
let base_dir = match data_dir(&app) {
|
||||
Ok(p) => p,
|
||||
Err(_) => {
|
||||
let _ = &app.emit("download-stop", format!("{}", name));
|
||||
return "-1".to_string();
|
||||
}
|
||||
};
|
||||
let downloads_path = base_dir.join("downloads");
|
||||
let game_path = base_dir.join("game");
|
||||
|
||||
let download_part_path = downloads_path.join(format!("{}.part", name));
|
||||
let download_zip_path = downloads_path.join(format!("{}.zip", name));
|
||||
@@ -414,7 +422,7 @@ fn launch_game(
|
||||
use_wine: bool,
|
||||
wine_command: String,
|
||||
) {
|
||||
let game_folder = match app.path().app_local_data_dir() {
|
||||
let game_folder = match data_dir(&app) {
|
||||
Ok(p) => p.join("game").join(&name),
|
||||
Err(_) => return,
|
||||
};
|
||||
@@ -473,10 +481,7 @@ fn launch_game(
|
||||
}
|
||||
}
|
||||
|
||||
let bepinex_folder = match app.path().app_local_data_dir() {
|
||||
Ok(p) => p.join("game").join(&name).join("BepInEx"),
|
||||
Err(_) => return,
|
||||
};
|
||||
let bepinex_folder = game_folder.join("BepInEx");
|
||||
|
||||
if platform() == "macos" && !bepinex_folder.exists() && executable.ends_with(".app") {
|
||||
if let Err(_) = Command::new("open")
|
||||
@@ -530,6 +535,125 @@ async fn cancel_download(name: String) {
|
||||
cancel_map().insert(name.clone(), true);
|
||||
}
|
||||
|
||||
fn copy_dir_recursive(src: &Path, dst: &Path) -> std::io::Result<()> {
|
||||
fs::create_dir_all(dst)?;
|
||||
for entry in fs::read_dir(src)? {
|
||||
let entry = entry?;
|
||||
let src_path = entry.path();
|
||||
let dst_path = dst.join(entry.file_name());
|
||||
if src_path.is_dir() {
|
||||
copy_dir_recursive(&src_path, &dst_path)?;
|
||||
} else {
|
||||
fs::copy(&src_path, &dst_path)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn move_dir(src: &Path, dst: &Path) -> std::io::Result<()> {
|
||||
if !src.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
if let Some(parent) = dst.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
if dst.exists() {
|
||||
fs::remove_dir_all(dst)?;
|
||||
}
|
||||
match fs::rename(src, dst) {
|
||||
Ok(()) => Ok(()),
|
||||
Err(_) => {
|
||||
copy_dir_recursive(src, dst)?;
|
||||
fs::remove_dir_all(src)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn move_game_data(app: AppHandle, destination: String) -> Result<(), String> {
|
||||
let default_dir = app.path().app_local_data_dir().map_err(|e| e.to_string())?;
|
||||
let current_dir = data_dir(&app)?;
|
||||
|
||||
let new_dir = if destination.is_empty() {
|
||||
default_dir.clone()
|
||||
} else {
|
||||
PathBuf::from(&destination)
|
||||
};
|
||||
|
||||
if current_dir == new_dir {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let src_game = current_dir.join("game");
|
||||
let dst_game = new_dir.join("game");
|
||||
let src_downloads = current_dir.join("downloads");
|
||||
let dst_downloads = new_dir.join("downloads");
|
||||
|
||||
tauri::async_runtime::spawn_blocking(move || {
|
||||
fs::create_dir_all(&new_dir).map_err(|e| e.to_string())?;
|
||||
move_dir(&src_game, &dst_game).map_err(|e| e.to_string())?;
|
||||
move_dir(&src_downloads, &dst_downloads).map_err(|e| e.to_string())?;
|
||||
Ok::<(), String>(())
|
||||
})
|
||||
.await
|
||||
.map_err(|e| e.to_string())??;
|
||||
|
||||
let state = app.state::<AppState>();
|
||||
let mut guard = state.custom_data_dir.write().unwrap();
|
||||
if destination.is_empty() {
|
||||
*guard = None;
|
||||
} else {
|
||||
*guard = Some(PathBuf::from(&destination));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn restart_app(app: AppHandle) {
|
||||
app.restart();
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn open_game_folder(app: AppHandle, version: String) -> Result<(), String> {
|
||||
let dir = data_dir(&app)?;
|
||||
let path = dir.join("game").join(&version);
|
||||
if !path.exists() || !path.is_dir() {
|
||||
return Err(format!("Game folder \"{}\" not found.", path.display()));
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
Command::new("open")
|
||||
.arg(&path)
|
||||
.spawn()
|
||||
.map_err(|e| e.to_string())?;
|
||||
#[cfg(target_os = "windows")]
|
||||
Command::new("explorer")
|
||||
.arg(&path)
|
||||
.spawn()
|
||||
.map_err(|e| e.to_string())?;
|
||||
#[cfg(target_os = "linux")]
|
||||
Command::new("xdg-open")
|
||||
.arg(&path)
|
||||
.spawn()
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn remove_stale_executable(app: AppHandle, version: String, executable: String) -> bool {
|
||||
let dir = match data_dir(&app) {
|
||||
Ok(d) => d,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let path = dir.join("game").join(&version).join(&executable);
|
||||
if path.exists() {
|
||||
fs::remove_file(&path).is_ok()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn open_new_window(
|
||||
app: tauri::AppHandle,
|
||||
@@ -597,9 +721,32 @@ pub fn run() {
|
||||
folder_size,
|
||||
verify_signature,
|
||||
cancel_download,
|
||||
open_new_window
|
||||
open_new_window,
|
||||
move_game_data,
|
||||
restart_app,
|
||||
open_game_folder,
|
||||
remove_stale_executable
|
||||
])
|
||||
.setup(|app| {
|
||||
let custom_dir = app
|
||||
.path()
|
||||
.app_config_dir()
|
||||
.ok()
|
||||
.map(|d| d.join("settings.json"))
|
||||
.filter(|p| p.exists())
|
||||
.and_then(|p| fs::read_to_string(p).ok())
|
||||
.and_then(|c| serde_json::from_str::<serde_json::Value>(&c).ok())
|
||||
.and_then(|v| {
|
||||
v.get("customDataLocation")
|
||||
.and_then(|s| s.as_str())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(PathBuf::from)
|
||||
});
|
||||
|
||||
app.manage(AppState {
|
||||
custom_data_dir: RwLock::new(custom_dir),
|
||||
});
|
||||
|
||||
let window = app.get_webview_window("main").unwrap();
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Lncvrt Games Launcher",
|
||||
"version": "1.9.1",
|
||||
"version": "1.9.2",
|
||||
"identifier": "xyz.lncvrt.games-launcher",
|
||||
"build": {
|
||||
"beforeDevCommand": "next dev --webpack",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Lncvrt Games Launcher",
|
||||
"version": "1.9.1",
|
||||
"version": "1.9.2",
|
||||
"identifier": "xyz.lncvrt.games-launcher",
|
||||
"build": {
|
||||
"beforeDevCommand": "next dev --webpack",
|
||||
@@ -27,6 +27,8 @@
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"category": "Game",
|
||||
"shortDescription": "A launcher for downloading, managing, and launching games with built-in mod support.",
|
||||
"longDescription": "Lncvrt Games Launcher lets you download and manage multiple versions of games, install mods, and launch them directly. Linux users can run Windows exclusive games via Wine (or proton via a custom command).",
|
||||
"targets": ["deb", "rpm"],
|
||||
"icon": ["icons/icon.png"],
|
||||
"createUpdaterArtifacts": true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Lncvrt Games Launcher",
|
||||
"version": "1.9.1",
|
||||
"version": "1.9.2",
|
||||
"identifier": "xyz.lncvrt.games-launcher",
|
||||
"build": {
|
||||
"beforeDevCommand": "next dev --webpack",
|
||||
@@ -30,6 +30,8 @@
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"category": "Game",
|
||||
"shortDescription": "A launcher for downloading, managing, and launching games with built-in mod support.",
|
||||
"longDescription": "Lncvrt Games Launcher lets you download and manage multiple versions of games, install mods, and launch them directly. Linux users can run Windows exclusive games via Wine (or proton via a custom command).",
|
||||
"targets": ["dmg", "app"],
|
||||
"icon": ["icons/icon.icns"],
|
||||
"createUpdaterArtifacts": true,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Lncvrt Games Launcher",
|
||||
"version": "1.9.1",
|
||||
"version": "1.9.2",
|
||||
"identifier": "xyz.lncvrt.games-launcher",
|
||||
"build": {
|
||||
"beforeDevCommand": "next dev --webpack",
|
||||
@@ -30,6 +30,8 @@
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"category": "Game",
|
||||
"shortDescription": "A launcher for downloading, managing, and launching games with built-in mod support.",
|
||||
"longDescription": "Lncvrt Games Launcher lets you download and manage multiple versions of games, install mods, and launch them directly. Linux users can run Windows exclusive games via Wine (or proton via a custom command).",
|
||||
"targets": ["msi"],
|
||||
"icon": ["icons/icon.ico"],
|
||||
"createUpdaterArtifacts": true
|
||||
|
||||
+21
-12
@@ -89,11 +89,13 @@ export default function RootLayout ({
|
||||
const [linuxWineCommand, setLinuxWineCommand] =
|
||||
useState<string>('wine %path%')
|
||||
const [theme, setTheme] = useState<string>('dark')
|
||||
const [customDataLocation, setCustomDataLocation] = useState<string>('')
|
||||
|
||||
const [versionsList, setVersionsList] = useState<Record<string, number>>({})
|
||||
const [modsList, setModsList] = useState<
|
||||
Record<string, Record<string, number>>
|
||||
>({})
|
||||
const [movingData, setMovingData] = useState(false)
|
||||
|
||||
function getSpecialVersionsList (game?: number): GameVersion[] {
|
||||
if (!serverVersionList) return []
|
||||
@@ -117,7 +119,7 @@ export default function RootLayout ({
|
||||
}
|
||||
|
||||
const closePopup = useCallback(() => {
|
||||
if (popupMode == 0 && selectedGame && pathname === '/') {
|
||||
if (popupMode == 0 && selectedGame && pathname === '/main') {
|
||||
setSelectedGame(null)
|
||||
setSelectedVersionList([])
|
||||
} else if (viewingInfoFromDownloads) {
|
||||
@@ -312,7 +314,8 @@ export default function RootLayout ({
|
||||
sidebarAlwaysShowGames: true,
|
||||
linuxUseWine: false,
|
||||
linuxWineCommand: 'wine %path%',
|
||||
theme: 'dark'
|
||||
theme: 'dark',
|
||||
customDataLocation: ''
|
||||
}
|
||||
})
|
||||
const versionsLocal = await load('versions.json', {
|
||||
@@ -623,15 +626,10 @@ export default function RootLayout ({
|
||||
verInfo.lastRevision > 0 &&
|
||||
value / 1000 <= verInfo.lastRevision
|
||||
) {
|
||||
if (
|
||||
await exists('game/' + key + '/' + verInfo.executable, {
|
||||
baseDir: BaseDirectory.AppLocalData
|
||||
})
|
||||
)
|
||||
await remove('game/' + key + '/' + verInfo.executable, {
|
||||
baseDir: BaseDirectory.AppLocalData,
|
||||
recursive: true
|
||||
})
|
||||
await invoke('remove_stale_executable', {
|
||||
version: key,
|
||||
executable: verInfo.executable
|
||||
})
|
||||
}
|
||||
}
|
||||
})()
|
||||
@@ -688,6 +686,9 @@ export default function RootLayout ({
|
||||
watchSettings<string>('linuxWineCommand', v =>
|
||||
setLinuxWineCommand(v ?? 'wine %path%')
|
||||
)
|
||||
watchSettings<string>('customDataLocation', v =>
|
||||
setCustomDataLocation(v ?? '')
|
||||
)
|
||||
|
||||
watchVersions<Record<string, number>>('list', v => setVersionsList(v ?? {}))
|
||||
watchVersions<Record<string, Record<string, number>>>('mods', v =>
|
||||
@@ -756,8 +757,11 @@ export default function RootLayout ({
|
||||
linuxUseWine,
|
||||
linuxWineCommand,
|
||||
theme,
|
||||
customDataLocation,
|
||||
versionsList,
|
||||
modsList
|
||||
modsList,
|
||||
movingData,
|
||||
setMovingData
|
||||
}}
|
||||
>
|
||||
<div
|
||||
@@ -825,6 +829,11 @@ export default function RootLayout ({
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{movingData && (
|
||||
<div className='fixed inset-0 z-999999 bg-(--col0) flex items-center justify-center'>
|
||||
<p className='text-5xl text-center'>Moving data...</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</GlobalProvider>
|
||||
)}
|
||||
|
||||
@@ -4,6 +4,8 @@ import { Setting } from '@/components/Setting'
|
||||
import { useGlobal } from '@/providers/GlobalProvider'
|
||||
import { copyToClipboard } from '@/lib/clipboard'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { open } from '@tauri-apps/plugin-dialog'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import Dropdown from '@/components/Dropdown'
|
||||
|
||||
export default function Settings () {
|
||||
@@ -14,7 +16,10 @@ export default function Settings () {
|
||||
sidebarAlwaysShowGames,
|
||||
linuxUseWine,
|
||||
linuxWineCommand,
|
||||
theme
|
||||
theme,
|
||||
customDataLocation,
|
||||
downloadProgress,
|
||||
setMovingData
|
||||
} = useGlobal()
|
||||
|
||||
return (
|
||||
@@ -58,6 +63,45 @@ export default function Settings () {
|
||||
className='input-field my-1'
|
||||
hidden={!(platform() == 'linux' && linuxUseWine)}
|
||||
></input>
|
||||
<Setting
|
||||
label='Use custom data location'
|
||||
value={!!customDataLocation}
|
||||
disabled={downloadProgress.length > 0}
|
||||
onChange={async () => {
|
||||
if (customDataLocation) {
|
||||
try {
|
||||
setMovingData(true)
|
||||
await invoke('move_game_data', { destination: '' })
|
||||
await settings?.set('customDataLocation', '')
|
||||
await settings?.save()
|
||||
await invoke('restart_app')
|
||||
} catch {
|
||||
setMovingData(false)
|
||||
}
|
||||
} else {
|
||||
const selected = await open({
|
||||
directory: true,
|
||||
title: 'Select data location'
|
||||
})
|
||||
if (!selected || typeof selected !== 'string') return
|
||||
try {
|
||||
setMovingData(true)
|
||||
await invoke('move_game_data', { destination: selected })
|
||||
await settings?.set('customDataLocation', selected)
|
||||
await settings?.save()
|
||||
await invoke('restart_app')
|
||||
} catch {
|
||||
setMovingData(false)
|
||||
}
|
||||
}
|
||||
}}
|
||||
title='Move game data to a custom folder location. Disabled during downloads.'
|
||||
/>
|
||||
{customDataLocation && (
|
||||
<p className='text-sm opacity-50 ml-6 -mt-1 mb-2'>
|
||||
{customDataLocation}
|
||||
</p>
|
||||
)}
|
||||
<div className='flex flex-row gap-2 items-center'>
|
||||
<p
|
||||
title='The theme you want the launcher to use.'
|
||||
|
||||
@@ -8,16 +8,18 @@ export function Setting ({
|
||||
value,
|
||||
onChange,
|
||||
className,
|
||||
title
|
||||
title,
|
||||
disabled
|
||||
}: SettingProps) {
|
||||
return (
|
||||
<div className={`flex items-center gap-2 mb-2 ${className}`} title={title}>
|
||||
<div className={`flex items-center gap-2 mb-2 ${disabled ? 'opacity-50 pointer-events-none' : ''} ${className}`} title={title}>
|
||||
<label className='text-white text-lg'>{label}</label>
|
||||
<div className='setting-checkbox-wrapper'>
|
||||
<input
|
||||
type='checkbox'
|
||||
className='setting-checkbox'
|
||||
checked={value}
|
||||
disabled={disabled}
|
||||
onChange={() => onChange(!value)}
|
||||
/>
|
||||
{value && <FontAwesomeIcon icon={faCheck} className='fa-check-icon' />}
|
||||
|
||||
+4
-28
@@ -1,39 +1,15 @@
|
||||
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'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
|
||||
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.`, {
|
||||
try {
|
||||
await invoke('open_game_folder', { version: name })
|
||||
} catch (e) {
|
||||
await message(String(e), {
|
||||
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) => {
|
||||
|
||||
@@ -57,8 +57,11 @@ type GlobalCtxType = {
|
||||
linuxUseWine: boolean
|
||||
linuxWineCommand: string
|
||||
theme: string
|
||||
customDataLocation: string
|
||||
versionsList: Record<string, number>
|
||||
modsList: Record<string, Record<string, number>>
|
||||
movingData: boolean
|
||||
setMovingData: Dispatch<SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const GlobalCtx = createContext<GlobalCtxType | null>(null)
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
}
|
||||
|
||||
.dropdown-btn {
|
||||
@apply w-full flex items-center justify-between px-3 py-1.5 rounded-md cursor-pointer
|
||||
@apply w-full flex items-center justify-between px-2 py-1 rounded-md cursor-pointer
|
||||
bg-(--col2) hover:bg-(--col3)
|
||||
border border-(--col4) hover:border-(--col5)
|
||||
text-white;
|
||||
}
|
||||
|
||||
.dropdown-arrow {
|
||||
@apply w-4 h-4 transition-transform stroke-current stroke-2 fill-none;
|
||||
@apply w-3 h-3 transition-transform stroke-current stroke-2 fill-none;
|
||||
}
|
||||
|
||||
.dropdown-arrow.open {
|
||||
@@ -20,7 +20,7 @@
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
@apply absolute z-50 mt-1 w-full rounded-md shadow-lg overflow-hidden
|
||||
@apply absolute z-50 mt-1 w-full rounded-md shadow-2xl overflow-hidden
|
||||
bg-(--col2) border border-(--col4)
|
||||
origin-top
|
||||
opacity-0 scale-95 -translate-y-1 pointer-events-none
|
||||
@@ -32,7 +32,7 @@
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
@apply px-3 py-1.5 cursor-pointer text-white transition-colors;
|
||||
@apply px-2 py-1 cursor-pointer text-white transition-colors border-b border-(--col4) last:border-b-0;
|
||||
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
|
||||
@@ -4,4 +4,5 @@ export type SettingProps = {
|
||||
onChange: (val: boolean) => void
|
||||
className?: string
|
||||
title?: string
|
||||
disabled?: boolean
|
||||
}
|
||||
Reference in new issue
Block a user