Compare commits
33
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fde145f071
|
||
|
|
846fcc0af7
|
||
|
|
4601628a55
|
||
|
|
3a9e0b0358
|
||
|
|
c45e7fb47c
|
||
|
|
c7086fbc31
|
||
|
|
33a1e4e780
|
||
|
|
066f4aae8c
|
||
|
|
2ebe127def
|
||
|
|
e0300acb6d
|
||
|
|
d18dc5afb7
|
||
|
|
d20c99651c
|
||
|
|
86a5a7b744
|
||
|
|
18f8c2316f
|
||
|
|
12914e42dd
|
||
|
|
91ff7caaed
|
||
|
|
fad7073607
|
||
|
|
beb5ce175e
|
||
|
|
b8498d36e4
|
||
|
|
141d17fea0
|
||
|
|
138275d752
|
||
|
|
1f035882f7
|
||
|
|
68cd3c891d
|
||
|
|
65bd6cfe82
|
||
|
|
d91314112d
|
||
|
|
da27bcb32c
|
||
|
|
6c8dfd1200
|
||
|
|
e09d125980
|
||
|
|
35dd842576
|
||
|
|
55714c8edb
|
||
|
|
04d1f2822b
|
||
|
|
dfd99ab12e
|
||
|
|
837c4a8863
|
No files matched your search
@@ -11,32 +11,34 @@
|
|||||||
"@fortawesome/react-fontawesome": "3.3.0",
|
"@fortawesome/react-fontawesome": "3.3.0",
|
||||||
"@tauri-apps/api": "2.10.1",
|
"@tauri-apps/api": "2.10.1",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
||||||
"@tauri-apps/plugin-dialog": "2.6.0",
|
"@tauri-apps/plugin-dialog": "2.7.0",
|
||||||
"@tauri-apps/plugin-fs": "2.4.5",
|
"@tauri-apps/plugin-fs": "2.5.0",
|
||||||
"@tauri-apps/plugin-http": "2.5.7",
|
"@tauri-apps/plugin-http": "2.5.8",
|
||||||
"@tauri-apps/plugin-notification": "2.3.3",
|
"@tauri-apps/plugin-notification": "2.3.3",
|
||||||
"@tauri-apps/plugin-opener": "2.5.3",
|
"@tauri-apps/plugin-opener": "2.5.3",
|
||||||
"@tauri-apps/plugin-os": "2.3.2",
|
"@tauri-apps/plugin-os": "2.3.2",
|
||||||
"@tauri-apps/plugin-store": "2.4.2",
|
"@tauri-apps/plugin-store": "2.4.2",
|
||||||
|
"@tauri-apps/plugin-updater": "2.10.1",
|
||||||
"@tauri-apps/plugin-window-state": "2.4.1",
|
"@tauri-apps/plugin-window-state": "2.4.1",
|
||||||
"next": "16.2.1",
|
"dompurify": "3.3.3",
|
||||||
|
"next": "16.2.3",
|
||||||
"pretty-bytes": "7.1.0",
|
"pretty-bytes": "7.1.0",
|
||||||
"react": "19.2.4",
|
"react": "19.2.5",
|
||||||
"react-dom": "19.2.4",
|
"react-dom": "19.2.5",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "3.3.5",
|
"@eslint/eslintrc": "3.3.5",
|
||||||
"@tailwindcss/postcss": "4.2.2",
|
"@tailwindcss/postcss": "4.2.2",
|
||||||
"@tauri-apps/cli": "2.10.1",
|
"@tauri-apps/cli": "2.10.1",
|
||||||
"@types/crypto-js": "4.2.2",
|
"@types/crypto-js": "4.2.2",
|
||||||
"@types/node": "25.5.0",
|
"@types/node": "25.6.0",
|
||||||
"@types/react": "19.2.14",
|
"@types/react": "19.2.14",
|
||||||
"@types/react-dom": "19.2.3",
|
"@types/react-dom": "19.2.3",
|
||||||
"crypto-js": "4.2.0",
|
"crypto-js": "4.2.0",
|
||||||
"eslint": "9.39.4",
|
"eslint": "9.39.4",
|
||||||
"eslint-config-next": "16.2.1",
|
"eslint-config-next": "16.2.3",
|
||||||
"tailwindcss": "4.2.2",
|
"tailwindcss": "4.2.2",
|
||||||
"typescript": "5.9.3",
|
"typescript": "6.0.2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -75,11 +77,11 @@
|
|||||||
|
|
||||||
"@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=="],
|
"@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.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
|
"@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/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="],
|
"@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="],
|
||||||
|
|
||||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
|
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
|
||||||
|
|
||||||
"@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.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
|
||||||
|
|
||||||
@@ -179,25 +181,25 @@
|
|||||||
|
|
||||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
|
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
|
||||||
|
|
||||||
"@next/env": ["@next/env@16.2.1", "", {}, "sha512-n8P/HCkIWW+gVal2Z8XqXJ6aB3J0tuM29OcHpCsobWlChH/SITBs1DFBk/HajgrwDkqqBXPbuUuzgDvUekREPg=="],
|
"@next/env": ["@next/env@16.2.3", "", {}, "sha512-ZWXyj4uNu4GCWQw9cjRxWlbD+33mcDszIo9iQxFnBX3Wmgq9ulaSJcl6VhuWx5pCWqqD+9W6Wfz7N0lM5lYPMA=="],
|
||||||
|
|
||||||
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.2.1", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-r0epZGo24eT4g08jJlg2OEryBphXqO8aL18oajoTKLzHJ6jVr6P6FI58DLMug04MwD3j8Fj0YK0slyzneKVyzA=="],
|
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.2.3", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-nE/b9mht28XJxjTwKs/yk7w4XTaU3t40UHVAky6cjiijdP/SEy3hGsnQMPxmXPTpC7W4/97okm6fngKnvCqVaA=="],
|
||||||
|
|
||||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BwZ8w8YTaSEr2HIuXLMLxIdElNMPvY9fLqb20LX9A9OMGtJilhHLbCL3ggyd0TwjmMcTxi0XXt+ur1vWUoxj2Q=="],
|
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-u37KDKTKQ+OQLvY+z7SNXixwo4Q2/IAJFDzU1fYe66IbCE51aDSAzkNDkWmLN0yjTUh4BKBd+hb69jYn6qqqSg=="],
|
||||||
|
|
||||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/vrcE6iQSJq3uL3VGVHiXeaKbn8Es10DGTGRJnRZlkNQQk3kaNtAJg8Y6xuAlrx/6INKVjkfi5rY0iEXorZ6uA=="],
|
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-gHjL/qy6Q6CG3176FWbAKyKh9IfntKZTB3RY/YOJdDFpHGsUDXVH38U4mMNpHVGXmeYW4wj22dMp1lTfmu/bTQ=="],
|
||||||
|
|
||||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-uLn+0BK+C31LTVbQ/QU+UaVrV0rRSJQ8RfniQAHPghDdgE+SlroYqcmFnO5iNjNfVWCyKZHYrs3Nl0mUzWxbBw=="],
|
"@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-musl": ["@next/swc-linux-arm64-musl@16.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-ssKq6iMRnHdnycGp9hCuGnXJZ0YPr4/wNwrfE5DbmvEcgl9+yv97/Kq3TPVDfYome1SW5geciLB9aiEqKXQjlQ=="],
|
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-/YV0LgjHUmfhQpn9bVoGc4x4nan64pkhWR5wyEV8yCOfwwrH630KpvRg86olQHTwHIn1z59uh6JwKvHq1h4QEw=="],
|
||||||
|
|
||||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-HQm7SrHRELJ30T1TSmT706IWovFFSRGxfgUkyWJZF/RKBMdbdRWJuFrcpDdE5vy9UXjFOx6L3mRdqH04Mmx0hg=="],
|
"@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-musl": ["@next/swc-linux-x64-musl@16.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-aV2iUaC/5HGEpbBkE+4B8aHIudoOy5DYekAKOMSHoIYQ66y/wIVeaRx8MS2ZMdxe/HIXlMho4ubdZs/J8441Tg=="],
|
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Kt44hGJfZSefebhk/7nIdivoDr3Ugp5+oNz9VvF3GUtfxutucUIHfIO0ZYO8QlOPDQloUVQn4NVC/9JvHRk9hw=="],
|
||||||
|
|
||||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-IXdNgiDHaSk0ZUJ+xp0OQTdTgnpx1RCfRTalhn3cjOP+IddTMINwA7DXZrwTmGDO8SUr5q2hdP/du4DcrB1GxA=="],
|
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.2.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-O2NZ9ie3Tq6xj5Z5CSwBT3+aWAMW2PIZ4egUi9MaWLkwaehgtB7YZjPm+UpcNpKOme0IQuqDcor7BsW6QBiQBw=="],
|
||||||
|
|
||||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-qvU+3a39Hay+ieIztkGSbF7+mccbbg1Tk25hc4JDylf8IHjYmY/Zm64Qq1602yPyQqvie+vf5T/uPwNxDNIoeg=="],
|
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.2.3", "", { "os": "win32", "cpu": "x64" }, "sha512-Ibm29/GgB/ab5n7XKqlStkm54qqZE8v2FnijUPBgrd67FWrac45o/RsNlaOWjme/B5UqeWt/8KM4aWBwA1D2Kw=="],
|
||||||
|
|
||||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||||
|
|
||||||
@@ -269,11 +271,11 @@
|
|||||||
|
|
||||||
"@tauri-apps/plugin-clipboard-manager": ["@tauri-apps/plugin-clipboard-manager@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-CUlb5Hqi2oZbcZf4VUyUH53XWPPdtpw43EUpCza5HWZJwxEoDowFzNUDt1tRUXA8Uq+XPn17Ysfptip33sG4eQ=="],
|
"@tauri-apps/plugin-clipboard-manager": ["@tauri-apps/plugin-clipboard-manager@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-CUlb5Hqi2oZbcZf4VUyUH53XWPPdtpw43EUpCza5HWZJwxEoDowFzNUDt1tRUXA8Uq+XPn17Ysfptip33sG4eQ=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.6.0", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg=="],
|
"@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.7.0", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-4nS/hfGMGCXiAS3LtVjH9AgsSAPJeG/7R+q8agTFqytjnMa4Zq95Bq8WzVDkckpanX+yyRHXnRtrKXkANKDHvw=="],
|
||||||
|
|
||||||
"@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-fs": ["@tauri-apps/plugin-fs@2.5.0", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-c83kbz61AK+rKjhS+je9+stIO27nXj7p9cqeg36TwkIUtxpCFTttlHHtqon6h6FN54cXjyAjlMPOJcW3mwE5XQ=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-http": ["@tauri-apps/plugin-http@2.5.7", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-+F2lEH/c9b0zSsOXKq+5hZNcd9F4IIKCK1T17RqMwpCmVnx2aoqY8yIBccCd25HTYUb3j6NPVbRax/m00hKG8A=="],
|
"@tauri-apps/plugin-http": ["@tauri-apps/plugin-http@2.5.8", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-oxd7oypzQeu8kAfFCrw534Kq7Cw+NzozcnCY21O4rz3A+veJiIiuSCMIprgGcZOcLAXFP9GmDhKUbhuKWcunRw=="],
|
||||||
|
|
||||||
"@tauri-apps/plugin-notification": ["@tauri-apps/plugin-notification@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg=="],
|
"@tauri-apps/plugin-notification": ["@tauri-apps/plugin-notification@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg=="],
|
||||||
|
|
||||||
@@ -283,6 +285,8 @@
|
|||||||
|
|
||||||
"@tauri-apps/plugin-store": ["@tauri-apps/plugin-store@2.4.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-0ClHS50Oq9HEvLPhNzTNFxbWVOqoAp3dRvtewQBeqfIQ0z5m3JRnOISIn2ZVPCrQC0MyGyhTS9DWhHjpigQE7A=="],
|
"@tauri-apps/plugin-store": ["@tauri-apps/plugin-store@2.4.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-0ClHS50Oq9HEvLPhNzTNFxbWVOqoAp3dRvtewQBeqfIQ0z5m3JRnOISIn2ZVPCrQC0MyGyhTS9DWhHjpigQE7A=="],
|
||||||
|
|
||||||
|
"@tauri-apps/plugin-updater": ["@tauri-apps/plugin-updater@2.10.1", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-NFYMg+tWOZPJdzE/PpFj2qfqwAWwNS3kXrb1tm1gnBJ9mYzZ4WDRrwy8udzWoAnfGCHLuePNLY1WVCNHnh3eRA=="],
|
||||||
|
|
||||||
"@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-window-state": ["@tauri-apps/plugin-window-state@2.4.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-OuvdrzyY8Q5Dbzpj+GcrnV1iCeoZbcFdzMjanZMMcAEUNy/6PH5pxZPXpaZLOR7whlzXiuzx0L9EKZbH7zpdRw=="],
|
||||||
|
|
||||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
@@ -295,31 +299,33 @@
|
|||||||
|
|
||||||
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
|
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
|
"@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||||
|
|
||||||
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.57.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.57.2", "@typescript-eslint/type-utils": "8.57.2", "@typescript-eslint/utils": "8.57.2", "@typescript-eslint/visitor-keys": "8.57.2", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.57.2", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-NZZgp0Fm2IkD+La5PR81sd+g+8oS6JwJje+aRWsDocxHkjyRw0J5L5ZTlN3LI1LlOcGL7ph3eaIUmTXMIjLk0w=="],
|
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
||||||
|
|
||||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.57.2", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.57.2", "@typescript-eslint/types": "8.57.2", "@typescript-eslint/typescript-estree": "8.57.2", "@typescript-eslint/visitor-keys": "8.57.2", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-30ScMRHIAD33JJQkgfGW1t8CURZtjc2JpTrq5n2HFhOefbAhb7ucc7xJwdWcrEtqUIYJ73Nybpsggii6GtAHjA=="],
|
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.58.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/type-utils": "8.58.2", "@typescript-eslint/utils": "8.58.2", "@typescript-eslint/visitor-keys": "8.58.2", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.58.2", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw=="],
|
||||||
|
|
||||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.2", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.2", "@typescript-eslint/types": "^8.57.2", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-FuH0wipFywXRTHf+bTTjNyuNQQsQC3qh/dYzaM4I4W0jrCqjCVuUh99+xd9KamUfmCGPvbO8NDngo/vsnNVqgw=="],
|
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.58.2", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/types": "8.58.2", "@typescript-eslint/typescript-estree": "8.58.2", "@typescript-eslint/visitor-keys": "8.58.2", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg=="],
|
||||||
|
|
||||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.2", "", { "dependencies": { "@typescript-eslint/types": "8.57.2", "@typescript-eslint/visitor-keys": "8.57.2" } }, "sha512-snZKH+W4WbWkrBqj4gUNRIGb/jipDW3qMqVJ4C9rzdFc+wLwruxk+2a5D+uoFcKPAqyqEnSb4l2ULuZf95eSkw=="],
|
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.2", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.2", "@typescript-eslint/types": "^8.58.2", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg=="],
|
||||||
|
|
||||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.2", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-3Lm5DSM+DCowsUOJC+YqHHnKEfFh5CoGkj5Z31NQSNF4l5wdOwqGn99wmwN/LImhfY3KJnmordBq/4+VDe2eKw=="],
|
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.2", "", { "dependencies": { "@typescript-eslint/types": "8.58.2", "@typescript-eslint/visitor-keys": "8.58.2" } }, "sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q=="],
|
||||||
|
|
||||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.57.2", "", { "dependencies": { "@typescript-eslint/types": "8.57.2", "@typescript-eslint/typescript-estree": "8.57.2", "@typescript-eslint/utils": "8.57.2", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Co6ZCShm6kIbAM/s+oYVpKFfW7LBc6FXoPXjTRQ449PPNBY8U0KZXuevz5IFuuUj2H9ss40atTaf9dlGLzbWZg=="],
|
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.2", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A=="],
|
||||||
|
|
||||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.57.2", "", {}, "sha512-/iZM6FnM4tnx9csuTxspMW4BOSegshwX5oBDznJ7S4WggL7Vczz5d2W11ecc4vRrQMQHXRSxzrCsyG5EsPPTbA=="],
|
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.58.2", "", { "dependencies": { "@typescript-eslint/types": "8.58.2", "@typescript-eslint/typescript-estree": "8.58.2", "@typescript-eslint/utils": "8.58.2", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.2", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.2", "@typescript-eslint/tsconfig-utils": "8.57.2", "@typescript-eslint/types": "8.57.2", "@typescript-eslint/visitor-keys": "8.57.2", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-2MKM+I6g8tJxfSmFKOnHv2t8Sk3T6rF20A1Puk0svLK+uVapDZB/4pfAeB7nE83uAZrU6OxW+HmOd5wHVdXwXA=="],
|
"@typescript-eslint/types": ["@typescript-eslint/types@8.58.2", "", {}, "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.2", "@typescript-eslint/types": "8.57.2", "@typescript-eslint/typescript-estree": "8.57.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-krRIbvPK1ju1WBKIefiX+bngPs+odIQUtR7kymzPfo1POVw3jlF+nLkmexdSSd4UCbDcQn+wMBATOOmpBbqgKg=="],
|
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.2", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.2", "@typescript-eslint/tsconfig-utils": "8.58.2", "@typescript-eslint/types": "8.58.2", "@typescript-eslint/visitor-keys": "8.58.2", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw=="],
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.2", "", { "dependencies": { "@typescript-eslint/types": "8.57.2", "eslint-visitor-keys": "^5.0.0" } }, "sha512-zhahknjobV2FiD6Ee9iLbS7OV9zi10rG26odsQdfBO/hjSzUQbkIYgda+iNKK1zNiW2ey+Lf8MU5btN17V3dUw=="],
|
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/types": "8.58.2", "@typescript-eslint/typescript-estree": "8.58.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA=="],
|
||||||
|
|
||||||
|
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.2", "", { "dependencies": { "@typescript-eslint/types": "8.58.2", "eslint-visitor-keys": "^5.0.0" } }, "sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA=="],
|
||||||
|
|
||||||
"@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="],
|
"@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="],
|
||||||
|
|
||||||
@@ -393,21 +399,21 @@
|
|||||||
|
|
||||||
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
||||||
|
|
||||||
"axe-core": ["axe-core@4.11.1", "", {}, "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A=="],
|
"axe-core": ["axe-core@4.11.3", "", {}, "sha512-zBQouZixDTbo3jMGqHKyePxYxr1e5W8UdTmBQ7sNtaA9M2bE32daxxPLS/jojhKOHxQ7LWwPjfiwf/fhaJWzlg=="],
|
||||||
|
|
||||||
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
||||||
|
|
||||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||||
|
|
||||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.10", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-sUoJ3IMxx4AyRqO4MLeHlnGDkyXRoUG0/AI9fjK+vS72ekpV0yWVY7O0BVjmBcRtkNcsAO2QDZ4tdKKGoI6YaQ=="],
|
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.18", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-VSnGQAOLtP5mib/DPyg2/t+Tlv65NTBz83BJBJvmLVHHuKJVaDOBvJJykiT5TR++em5nfAySPccDZDa4oSrn8A=="],
|
||||||
|
|
||||||
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
"brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
|
||||||
|
|
||||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
"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=="],
|
"browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="],
|
||||||
|
|
||||||
"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": ["call-bind@1.0.9", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" } }, "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ=="],
|
||||||
|
|
||||||
"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=="],
|
"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=="],
|
||||||
|
|
||||||
@@ -415,7 +421,7 @@
|
|||||||
|
|
||||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||||
|
|
||||||
"caniuse-lite": ["caniuse-lite@1.0.30001781", "", {}, "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw=="],
|
"caniuse-lite": ["caniuse-lite@1.0.30001787", "", {}, "sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg=="],
|
||||||
|
|
||||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||||
|
|
||||||
@@ -455,21 +461,23 @@
|
|||||||
|
|
||||||
"doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
|
"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=="],
|
||||||
|
|
||||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||||
|
|
||||||
"electron-to-chromium": ["electron-to-chromium@1.5.322", "", {}, "sha512-vFU34OcrvMcH66T+dYC3G4nURmgfDVewMIu6Q2urXpumAPSMmzvcn04KVVV8Opikq8Vs5nUbO/8laNhNRqSzYw=="],
|
"electron-to-chromium": ["electron-to-chromium@1.5.336", "", {}, "sha512-AbH9q9J455r/nLmdNZes0G0ZKcRX73FicwowalLs6ijwOmCJSRRrLX63lcAlzy9ux3dWK1w1+1nsBJEWN11hcQ=="],
|
||||||
|
|
||||||
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||||
|
|
||||||
"enhanced-resolve": ["enhanced-resolve@5.20.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA=="],
|
"enhanced-resolve": ["enhanced-resolve@5.20.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA=="],
|
||||||
|
|
||||||
"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.2", "", { "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-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg=="],
|
||||||
|
|
||||||
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||||
|
|
||||||
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||||
|
|
||||||
"es-iterator-helpers": ["es-iterator-helpers@1.3.1", "", { "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", "math-intrinsics": "^1.1.0", "safe-array-concat": "^1.1.3" } }, "sha512-zWwRvqWiuBPr0muUG/78cW3aHROFCNIQ3zpmYDpwdbnt2m+xlNyRWpHBpa2lJjSBit7BQ+RXA1iwbSmu5yJ/EQ=="],
|
"es-iterator-helpers": ["es-iterator-helpers@1.3.2", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "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", "math-intrinsics": "^1.1.0" } }, "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw=="],
|
||||||
|
|
||||||
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||||
|
|
||||||
@@ -485,9 +493,9 @@
|
|||||||
|
|
||||||
"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": ["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.1", "", { "dependencies": { "@next/eslint-plugin-next": "16.2.1", "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-qhabwjQZ1Mk53XzXvmogf8KQ0tG0CQXF0CZ56+2/lVhmObgmaqj7x5A1DSrWdZd3kwI7GTPGUjFne+krRxYmFg=="],
|
"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-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="],
|
"eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.10", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.16.1", "resolve": "^2.0.0-next.6" } }, "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ=="],
|
||||||
|
|
||||||
"eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import", "eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="],
|
"eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import", "eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="],
|
||||||
|
|
||||||
@@ -729,11 +737,11 @@
|
|||||||
|
|
||||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||||
|
|
||||||
"next": ["next@16.2.1", "", { "dependencies": { "@next/env": "16.2.1", "@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.1", "@next/swc-darwin-x64": "16.2.1", "@next/swc-linux-arm64-gnu": "16.2.1", "@next/swc-linux-arm64-musl": "16.2.1", "@next/swc-linux-x64-gnu": "16.2.1", "@next/swc-linux-x64-musl": "16.2.1", "@next/swc-win32-arm64-msvc": "16.2.1", "@next/swc-win32-x64-msvc": "16.2.1", "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-VaChzNL7o9rbfdt60HUj8tev4m6d7iC1igAy157526+cJlXOQu5LzsBXNT+xaJnTP/k+utSX5vMv7m0G+zKH+Q=="],
|
"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=="],
|
||||||
|
|
||||||
"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=="],
|
"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=="],
|
||||||
|
|
||||||
"node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="],
|
"node-releases": ["node-releases@2.0.37", "", {}, "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg=="],
|
||||||
|
|
||||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||||
|
|
||||||
@@ -773,7 +781,7 @@
|
|||||||
|
|
||||||
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
||||||
|
|
||||||
"postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="],
|
"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=="],
|
||||||
|
|
||||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||||
|
|
||||||
@@ -785,9 +793,9 @@
|
|||||||
|
|
||||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||||
|
|
||||||
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
"react": ["react@19.2.5", "", {}, "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA=="],
|
||||||
|
|
||||||
"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.5", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.5" } }, "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag=="],
|
||||||
|
|
||||||
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||||
|
|
||||||
@@ -795,7 +803,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=="],
|
"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@2.0.0-next.6", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA=="],
|
||||||
|
|
||||||
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||||
|
|
||||||
@@ -829,7 +837,7 @@
|
|||||||
|
|
||||||
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
|
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
|
||||||
|
|
||||||
"side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
|
"side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="],
|
||||||
|
|
||||||
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
|
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
|
||||||
|
|
||||||
@@ -867,7 +875,7 @@
|
|||||||
|
|
||||||
"tapable": ["tapable@2.3.2", "", {}, "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA=="],
|
"tapable": ["tapable@2.3.2", "", {}, "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA=="],
|
||||||
|
|
||||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
"tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="],
|
||||||
|
|
||||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||||
|
|
||||||
@@ -887,13 +895,13 @@
|
|||||||
|
|
||||||
"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=="],
|
"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@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
"typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
|
||||||
|
|
||||||
"typescript-eslint": ["typescript-eslint@8.57.2", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.57.2", "@typescript-eslint/parser": "8.57.2", "@typescript-eslint/typescript-estree": "8.57.2", "@typescript-eslint/utils": "8.57.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-VEPQ0iPgWO/sBaZOU1xo4nuNdODVOajPnTIbog2GKYr31nIlZ0fWPoCQgGfF3ETyBl1vn63F/p50Um9Z4J8O8A=="],
|
"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=="],
|
||||||
|
|
||||||
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
|
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
"undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||||
|
|
||||||
"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=="],
|
"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=="],
|
||||||
|
|
||||||
@@ -925,13 +933,13 @@
|
|||||||
|
|
||||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
|
"@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/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="],
|
"@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/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
|
"@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.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.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/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
|
|
||||||
@@ -939,7 +947,7 @@
|
|||||||
|
|
||||||
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
|
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|
||||||
@@ -953,8 +961,6 @@
|
|||||||
|
|
||||||
"eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
"eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||||
|
|
||||||
"eslint-plugin-react/resolve": ["resolve@2.0.0-next.6", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA=="],
|
|
||||||
|
|
||||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
"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.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|||||||
+12
-10
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "lncvrt-games-launcher",
|
"name": "lncvrt-games-launcher",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.8.1",
|
"version": "1.9.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
@@ -17,31 +17,33 @@
|
|||||||
"@fortawesome/react-fontawesome": "3.3.0",
|
"@fortawesome/react-fontawesome": "3.3.0",
|
||||||
"@tauri-apps/api": "2.10.1",
|
"@tauri-apps/api": "2.10.1",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
||||||
"@tauri-apps/plugin-dialog": "2.6.0",
|
"@tauri-apps/plugin-dialog": "2.7.0",
|
||||||
"@tauri-apps/plugin-fs": "2.4.5",
|
"@tauri-apps/plugin-fs": "2.5.0",
|
||||||
"@tauri-apps/plugin-http": "2.5.7",
|
"@tauri-apps/plugin-http": "2.5.8",
|
||||||
"@tauri-apps/plugin-notification": "2.3.3",
|
"@tauri-apps/plugin-notification": "2.3.3",
|
||||||
"@tauri-apps/plugin-opener": "2.5.3",
|
"@tauri-apps/plugin-opener": "2.5.3",
|
||||||
"@tauri-apps/plugin-os": "2.3.2",
|
"@tauri-apps/plugin-os": "2.3.2",
|
||||||
"@tauri-apps/plugin-store": "2.4.2",
|
"@tauri-apps/plugin-store": "2.4.2",
|
||||||
|
"@tauri-apps/plugin-updater": "2.10.1",
|
||||||
"@tauri-apps/plugin-window-state": "2.4.1",
|
"@tauri-apps/plugin-window-state": "2.4.1",
|
||||||
"next": "16.2.1",
|
"dompurify": "3.3.3",
|
||||||
|
"next": "16.2.3",
|
||||||
"pretty-bytes": "7.1.0",
|
"pretty-bytes": "7.1.0",
|
||||||
"react": "19.2.4",
|
"react": "19.2.5",
|
||||||
"react-dom": "19.2.4"
|
"react-dom": "19.2.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "3.3.5",
|
"@eslint/eslintrc": "3.3.5",
|
||||||
"@tailwindcss/postcss": "4.2.2",
|
"@tailwindcss/postcss": "4.2.2",
|
||||||
"@tauri-apps/cli": "2.10.1",
|
"@tauri-apps/cli": "2.10.1",
|
||||||
"@types/crypto-js": "4.2.2",
|
"@types/crypto-js": "4.2.2",
|
||||||
"@types/node": "25.5.0",
|
"@types/node": "25.6.0",
|
||||||
"@types/react": "19.2.14",
|
"@types/react": "19.2.14",
|
||||||
"@types/react-dom": "19.2.3",
|
"@types/react-dom": "19.2.3",
|
||||||
"crypto-js": "4.2.0",
|
"crypto-js": "4.2.0",
|
||||||
"eslint": "9.39.4",
|
"eslint": "9.39.4",
|
||||||
"eslint-config-next": "16.2.1",
|
"eslint-config-next": "16.2.3",
|
||||||
"tailwindcss": "4.2.2",
|
"tailwindcss": "4.2.2",
|
||||||
"typescript": "5.9.3"
|
"typescript": "6.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+15
-10
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lncvrt-games-launcher"
|
name = "lncvrt-games-launcher"
|
||||||
version = "1.8.1"
|
version = "1.9.1"
|
||||||
authors = ["Lncvrt"]
|
authors = ["Lncvrt"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
@@ -17,29 +17,33 @@ tauri-plugin-opener = "2.5.3"
|
|||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
serde_json = "1.0.149"
|
serde_json = "1.0.149"
|
||||||
tauri-plugin-os = "2.3.2"
|
tauri-plugin-os = "2.3.2"
|
||||||
reqwest = { version = "0.13.2", default-features = false, features = ["stream", "rustls"] }
|
reqwest = { version = "0.13.2", default-features = false, features = [
|
||||||
tokio = "1.50.0"
|
"stream",
|
||||||
|
"rustls",
|
||||||
|
] }
|
||||||
|
tokio = "1.51.1"
|
||||||
futures-util = { version = "0.3.32", features = ["io"] }
|
futures-util = { version = "0.3.32", features = ["io"] }
|
||||||
tauri-plugin-decorum = "1.1.1"
|
tauri-plugin-decorum = "1.1.1"
|
||||||
tauri-plugin-fs = "2.4.5"
|
tauri-plugin-fs = "2.5.0"
|
||||||
zip = "8.4.0"
|
zip = "8.5.1"
|
||||||
tauri-plugin-dialog = "2.6.0"
|
tauri-plugin-dialog = "2.7.0"
|
||||||
tauri-plugin-notification = "2.3.3"
|
tauri-plugin-notification = "2.3.3"
|
||||||
sha2 = "0.11.0"
|
sha2 = "0.11.0"
|
||||||
tauri-plugin-clipboard-manager = "2.3.2"
|
tauri-plugin-clipboard-manager = "2.3.2"
|
||||||
tauri-plugin-prevent-default = "4.0.4"
|
tauri-plugin-prevent-default = "4.0.4"
|
||||||
openssl = { version = "0.10.76", features = ["v110", "vendored"] }
|
openssl = { version = "0.10.77", features = ["v111", "vendored"] }
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
tauri-plugin-http = "2.5.7"
|
tauri-plugin-http = "2.5.8"
|
||||||
dashmap = "6.1.0"
|
dashmap = "6.1.0"
|
||||||
tauri-plugin-store = "2.4.2"
|
tauri-plugin-store = "2.4.2"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
|
window-vibrancy = "0.7.1"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "windows", target_os = "linux"))'.dependencies]
|
[target.'cfg(any(target_os = "windows", target_os = "linux"))'.dependencies]
|
||||||
sysinfo = "0.38.4"
|
sysinfo = "0.38.4"
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
tauri-plugin-single-instance = "2.4.0"
|
tauri-plugin-single-instance = "2.4.1"
|
||||||
tauri-plugin-window-state = "2.4.1"
|
tauri-plugin-window-state = "2.4.1"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
@@ -47,6 +51,7 @@ tauri-plugin-decorum = "1.1.1"
|
|||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
lto = true
|
lto = "fat"
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
strip = true
|
strip = true
|
||||||
|
panic = "abort"
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
"decorum:allow-show-snap-overlay",
|
"decorum:allow-show-snap-overlay",
|
||||||
"fs:default",
|
"fs:default",
|
||||||
"dialog:default",
|
"dialog:default",
|
||||||
|
"dialog:allow-open",
|
||||||
"notification:default",
|
"notification:default",
|
||||||
"clipboard-manager:default",
|
"clipboard-manager:default",
|
||||||
"clipboard-manager:allow-write-text",
|
"clipboard-manager:allow-write-text",
|
||||||
@@ -31,7 +32,7 @@
|
|||||||
"fs:allow-applocaldata-write",
|
"fs:allow-applocaldata-write",
|
||||||
{
|
{
|
||||||
"identifier": "fs:scope",
|
"identifier": "fs:scope",
|
||||||
"allow": [{ "path": "$APPLOCALDATA/game/**" }]
|
"allow": [{ "path": "$APPLOCALDATA/game/**" }, { "path": "$APPCONFIG/versions.json" }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identifier": "opener:allow-open-path",
|
"identifier": "opener:allow-open-path",
|
||||||
|
|||||||
@@ -1,14 +1,6 @@
|
|||||||
{
|
{
|
||||||
"identifier": "desktop-capability",
|
"identifier": "desktop-capability",
|
||||||
"platforms": [
|
"platforms": ["macOS", "windows", "linux"],
|
||||||
"macOS",
|
"windows": ["main"],
|
||||||
"windows",
|
"permissions": ["window-state:default"]
|
||||||
"linux"
|
}
|
||||||
],
|
|
||||||
"windows": [
|
|
||||||
"main"
|
|
||||||
],
|
|
||||||
"permissions": [
|
|
||||||
"window-state:default"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
+221
-30
@@ -6,7 +6,7 @@ use openssl::sign::Verifier;
|
|||||||
use sha2::{Digest, Sha512};
|
use sha2::{Digest, Sha512};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::OnceLock;
|
use std::sync::{OnceLock, RwLock};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::{
|
use std::{
|
||||||
fs::{File, create_dir_all},
|
fs::{File, create_dir_all},
|
||||||
@@ -21,6 +21,8 @@ use tauri_plugin_os::platform;
|
|||||||
use tauri_plugin_prevent_default::Flags;
|
use tauri_plugin_prevent_default::Flags;
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
use tokio::{io::AsyncWriteExt, time::timeout};
|
use tokio::{io::AsyncWriteExt, time::timeout};
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
use window_vibrancy::{NSVisualEffectMaterial, apply_vibrancy};
|
||||||
use zip::ZipArchive;
|
use zip::ZipArchive;
|
||||||
use zip::result::ZipError;
|
use zip::result::ZipError;
|
||||||
|
|
||||||
@@ -30,6 +32,19 @@ use sysinfo::System;
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
|
||||||
|
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();
|
static CANCEL_MAP: OnceLock<DashMap<String, bool>> = OnceLock::new();
|
||||||
|
|
||||||
fn cancel_map() -> &'static DashMap<String, bool> {
|
fn cancel_map() -> &'static DashMap<String, bool> {
|
||||||
@@ -117,7 +132,7 @@ async fn unzip_to_dir(app: AppHandle, zip_path: PathBuf, out_dir: PathBuf, name:
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn folder_size(app: AppHandle, version: String) -> String {
|
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),
|
Ok(p) => p.join("game").join(&version),
|
||||||
Err(_) => return "-1".to_string(),
|
Err(_) => return "-1".to_string(),
|
||||||
};
|
};
|
||||||
@@ -157,20 +172,15 @@ async fn download(
|
|||||||
let _ = app.emit("download-start", format!("{}", name));
|
let _ = app.emit("download-start", format!("{}", name));
|
||||||
let window = app.get_webview_window("main").expect("main window missing");
|
let window = app.get_webview_window("main").expect("main window missing");
|
||||||
|
|
||||||
let downloads_path = match app.path().app_local_data_dir() {
|
let base_dir = match data_dir(&app) {
|
||||||
Ok(p) => p.join("downloads"),
|
Ok(p) => p,
|
||||||
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"),
|
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let _ = &app.emit("download-stop", format!("{}", name));
|
let _ = &app.emit("download-stop", format!("{}", name));
|
||||||
return "-1".to_string();
|
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_part_path = downloads_path.join(format!("{}.part", name));
|
||||||
let download_zip_path = downloads_path.join(format!("{}.zip", name));
|
let download_zip_path = downloads_path.join(format!("{}.zip", name));
|
||||||
@@ -411,7 +421,7 @@ fn launch_game(
|
|||||||
use_wine: bool,
|
use_wine: bool,
|
||||||
wine_command: String,
|
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),
|
Ok(p) => p.join("game").join(&name),
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
@@ -424,8 +434,7 @@ fn launch_game(
|
|||||||
//if already running on macos, it'll auto take the user to that proccess
|
//if already running on macos, it'll auto take the user to that proccess
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||||
{
|
{
|
||||||
use tauri_plugin_dialog::DialogExt;
|
use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
|
||||||
use tauri_plugin_dialog::MessageDialogKind;
|
|
||||||
|
|
||||||
if !use_wine && is_running_by_path(&exe_path) {
|
if !use_wine && is_running_by_path(&exe_path) {
|
||||||
app.dialog()
|
app.dialog()
|
||||||
@@ -446,25 +455,34 @@ fn launch_game(
|
|||||||
let quoted_path = format!("\"{}\"", exe_path.to_string_lossy());
|
let quoted_path = format!("\"{}\"", exe_path.to_string_lossy());
|
||||||
let cmd = wine_command.replace("%path%", "ed_path);
|
let cmd = wine_command.replace("%path%", "ed_path);
|
||||||
|
|
||||||
if let Err(_) = Command::new("bash")
|
if let Err(e) =
|
||||||
.arg("-c")
|
Command::new(&std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string()))
|
||||||
.arg(cmd)
|
.arg("-c")
|
||||||
.current_dir(&game_folder)
|
.arg(cmd)
|
||||||
.spawn()
|
.current_dir(&game_folder)
|
||||||
|
.spawn()
|
||||||
{
|
{
|
||||||
eprintln!("Failed to launch game with Wine");
|
use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
|
||||||
|
|
||||||
|
eprintln!("Failed to launch game with Wine: {}", e);
|
||||||
|
|
||||||
|
app.dialog()
|
||||||
|
.message(format!(
|
||||||
|
"{} failed to launch with Wine\n\n{}",
|
||||||
|
display_name, e
|
||||||
|
))
|
||||||
|
.kind(MessageDialogKind::Error)
|
||||||
|
.title("Game already running")
|
||||||
|
.show(|_| {});
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let bepinex_folder = match app.path().app_local_data_dir() {
|
let bepinex_folder = game_folder.join("BepInEx");
|
||||||
Ok(p) => p.join("game").join(&name).join("BepInEx"),
|
|
||||||
Err(_) => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
if platform() == "macos" && !bepinex_folder.exists() {
|
if platform() == "macos" && !bepinex_folder.exists() && executable.ends_with(".app") {
|
||||||
if let Err(_) = Command::new("open")
|
if let Err(_) = Command::new("open")
|
||||||
.arg(&executable)
|
.arg(&executable)
|
||||||
.current_dir(&game_folder)
|
.current_dir(&game_folder)
|
||||||
@@ -516,6 +534,150 @@ async fn cancel_download(name: String) {
|
|||||||
cancel_map().insert(name.clone(), true);
|
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,
|
||||||
|
title: String,
|
||||||
|
name: String,
|
||||||
|
url: String,
|
||||||
|
width: f64,
|
||||||
|
height: f64,
|
||||||
|
) {
|
||||||
|
if let Some(window) = app.get_webview_window(&name) {
|
||||||
|
let _ = window.show();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
tauri::WebviewWindowBuilder::new(
|
||||||
|
&app,
|
||||||
|
name,
|
||||||
|
tauri::WebviewUrl::External(url.parse().unwrap()),
|
||||||
|
)
|
||||||
|
.inner_size(width, height)
|
||||||
|
.title(title)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
@@ -556,18 +718,47 @@ pub fn run() {
|
|||||||
launch_game,
|
launch_game,
|
||||||
folder_size,
|
folder_size,
|
||||||
verify_signature,
|
verify_signature,
|
||||||
cancel_download
|
cancel_download,
|
||||||
|
open_new_window,
|
||||||
|
move_game_data,
|
||||||
|
restart_app,
|
||||||
|
open_game_folder,
|
||||||
|
remove_stale_executable
|
||||||
])
|
])
|
||||||
.setup(|app| {
|
.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 = "macos")]
|
||||||
|
apply_vibrancy(&window, NSVisualEffectMaterial::HudWindow, None, None)
|
||||||
|
.expect("Unable to apply window blur");
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
||||||
use tauri_plugin_decorum::WebviewWindowExt;
|
use tauri_plugin_decorum::WebviewWindowExt;
|
||||||
if let Some(main_window) = app.get_webview_window("main") {
|
if let Err(e) = window.create_overlay_titlebar() {
|
||||||
if let Err(e) = main_window.create_overlay_titlebar() {
|
eprintln!("Failed to create overlay titlebar: {:?}", e);
|
||||||
eprintln!("Failed to create overlay titlebar: {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.8.1",
|
"version": "1.9.1",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev --webpack",
|
"beforeDevCommand": "next dev --webpack",
|
||||||
@@ -10,15 +10,7 @@
|
|||||||
"frontendDist": "../out"
|
"frontendDist": "../out"
|
||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"windows": [
|
"windows": [],
|
||||||
{
|
|
||||||
"title": "Lncvrt Games Launcher",
|
|
||||||
"width": 1000,
|
|
||||||
"height": 600,
|
|
||||||
"minWidth": 875,
|
|
||||||
"minHeight": 500
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"security": {
|
"security": {
|
||||||
"csp": null
|
"csp": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.8.1",
|
"version": "1.9.1",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev --webpack",
|
"beforeDevCommand": "next dev --webpack",
|
||||||
@@ -13,9 +13,10 @@
|
|||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
"title": "Lncvrt Games Launcher",
|
"title": "Lncvrt Games Launcher",
|
||||||
|
"url": "/main",
|
||||||
"width": 1000,
|
"width": 1000,
|
||||||
"height": 600,
|
"height": 600,
|
||||||
"minWidth": 875,
|
"minWidth": 1000,
|
||||||
"minHeight": 500
|
"minHeight": 500
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -24,6 +25,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bundle": {
|
"bundle": {
|
||||||
"active": false
|
"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
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
"updater": {
|
||||||
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IERFODI3MTAwQkNBMjE4REEKUldUYUdLSzhBSEdDM3J0N1NvbENsdDQ3c3BOdWlFajErVnlLZitSc2l5WVI0VjQ1ZHNMWjYzaUwK",
|
||||||
|
"endpoints": [
|
||||||
|
"https://games.lncvrt.xyz/api/launcher/update?target={{target}}&arch={{arch}}¤tVersion={{current_version}}"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.8.1",
|
"version": "1.9.1",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev --webpack",
|
"beforeDevCommand": "next dev --webpack",
|
||||||
@@ -14,12 +14,14 @@
|
|||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
"title": "Lncvrt Games Launcher",
|
"title": "Lncvrt Games Launcher",
|
||||||
|
"url": "/main",
|
||||||
"width": 1000,
|
"width": 1000,
|
||||||
"height": 600,
|
"height": 600,
|
||||||
"minWidth": 875,
|
"minWidth": 1000,
|
||||||
"minHeight": 500,
|
"minHeight": 500,
|
||||||
"titleBarStyle": "Overlay",
|
"titleBarStyle": "Overlay",
|
||||||
"hiddenTitle": true
|
"hiddenTitle": true,
|
||||||
|
"transparent": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"security": {
|
"security": {
|
||||||
@@ -28,10 +30,22 @@
|
|||||||
},
|
},
|
||||||
"bundle": {
|
"bundle": {
|
||||||
"active": true,
|
"active": true,
|
||||||
"targets": ["app"],
|
"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,
|
||||||
"macOS": {
|
"macOS": {
|
||||||
"minimumSystemVersion": "13.0"
|
"minimumSystemVersion": "13.0"
|
||||||
},
|
}
|
||||||
"icon": ["icons/icon.icns"]
|
},
|
||||||
|
"plugins": {
|
||||||
|
"updater": {
|
||||||
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IERFODI3MTAwQkNBMjE4REEKUldUYUdLSzhBSEdDM3J0N1NvbENsdDQ3c3BOdWlFajErVnlLZitSc2l5WVI0VjQ1ZHNMWjYzaUwK",
|
||||||
|
"endpoints": [
|
||||||
|
"https://games.lncvrt.xyz/api/launcher/update?target={{target}}&arch={{arch}}¤tVersion={{current_version}}"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Lncvrt Games Launcher",
|
"productName": "Lncvrt Games Launcher",
|
||||||
"version": "1.8.1",
|
"version": "1.9.1",
|
||||||
"identifier": "xyz.lncvrt.games-launcher",
|
"identifier": "xyz.lncvrt.games-launcher",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "next dev --webpack",
|
"beforeDevCommand": "next dev --webpack",
|
||||||
@@ -14,12 +14,11 @@
|
|||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
"title": "Lncvrt Games Launcher",
|
"title": "Lncvrt Games Launcher",
|
||||||
|
"url": "/main",
|
||||||
"width": 1000,
|
"width": 1000,
|
||||||
"height": 632,
|
"height": 632,
|
||||||
"minWidth": 875,
|
"minWidth": 1000,
|
||||||
"minHeight": 532,
|
"minHeight": 532,
|
||||||
"titleBarStyle": "Overlay",
|
|
||||||
"hiddenTitle": true,
|
|
||||||
"decorations": false,
|
"decorations": false,
|
||||||
"shadow": true
|
"shadow": true
|
||||||
}
|
}
|
||||||
@@ -29,7 +28,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bundle": {
|
"bundle": {
|
||||||
"active": false,
|
"active": true,
|
||||||
"icon": ["icons/icon.ico"]
|
"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
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
"updater": {
|
||||||
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IERFODI3MTAwQkNBMjE4REEKUldUYUdLSzhBSEdDM3J0N1NvbENsdDQ3c3BOdWlFajErVnlLZitSc2l5WVI0VjQ1ZHNMWjYzaUwK",
|
||||||
|
"endpoints": [
|
||||||
|
"https://games.lncvrt.xyz/api/launcher/update?target={{target}}&arch={{arch}}¤tVersion={{current_version}}"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
@import "tailwindcss";
|
|
||||||
|
|
||||||
html {
|
|
||||||
overscroll-behavior: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
--col9: rgb(144, 144, 144);
|
|
||||||
}
|
|
||||||
|
|
||||||
.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);
|
|
||||||
--col9: rgb(168, 144, 144);
|
|
||||||
}
|
|
||||||
|
|
||||||
.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);
|
|
||||||
--col9: rgb(144, 144, 168);
|
|
||||||
}
|
|
||||||
|
|
||||||
.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);
|
|
||||||
--col9: rgb(156, 144, 168);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
@apply rounded-md cursor-pointer text-[16px] py-1 px-2 transition-colors border;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
@apply w-2;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
@apply bg-(--col2) rounded-lg;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
@apply bg-(--col4) w-1 rounded-lg active:bg-(--col5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeOut {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.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)];
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-overlay.fade-out {
|
|
||||||
@apply animate-[fadeOut_0.2s_ease-out_forwards];
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-box {
|
|
||||||
@apply relative w-150 h-120 rounded-lg bg-(--col1) border border-(--col3) flex flex-col p-6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-content {
|
|
||||||
@apply flex-1 overflow-auto bg-(--col2) border border-(--col4) rounded-lg mt-4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-entry {
|
|
||||||
@apply relative h-fit bg-(--col3) m-2 p-2 rounded-lg border border-(--col5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-entry button {
|
|
||||||
@apply absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-top-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 top-2 transition-colors border;
|
|
||||||
}
|
|
||||||
|
|
||||||
*:focus {
|
|
||||||
@apply outline-none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
@import "tailwindcss";
|
|
||||||
|
|
||||||
.downloads-container {
|
|
||||||
@apply flex justify-center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.downloads-scroll {
|
|
||||||
@apply bg-(--col1) border border-(--col3) 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;
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
@import "tailwindcss";
|
|
||||||
|
|
||||||
.box {
|
|
||||||
@apply bg-(--col1) border border-(--col3) rounded-lg w-auto p-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-button {
|
|
||||||
@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;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
.downloads-container {
|
||||||
|
@apply flex justify-center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.downloads-scroll {
|
||||||
|
@apply bg-(--col1)/50 border border-(--col3)/50 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)/50 hover:bg-(--col3)/50 border border-(--col4)/50 hover:border-(--col5)/50 cursor-pointer;
|
||||||
|
}
|
||||||
+32
-28
@@ -1,14 +1,15 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import './styles.css'
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { BirdColor } from '@/types/BerryDash/BirdColor'
|
import { BirdColor } from '@/types/BerryDash/BirdColor'
|
||||||
import { GetIconForUser } from '@/lib/BerryDash'
|
import { GetIconForUser } from '@/lib/berrydashutil'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import './styles.css'
|
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { platform } from '@tauri-apps/plugin-os'
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
import { fetch } from '@tauri-apps/plugin-http'
|
import { fetch } from '@tauri-apps/plugin-http'
|
||||||
import { verifySignature } from '@/lib/Util'
|
import { verifySignature } from '@/lib/util'
|
||||||
|
import Dropdown from '@/components/Dropdown'
|
||||||
|
|
||||||
interface BaseEntry {
|
interface BaseEntry {
|
||||||
id: number
|
id: number
|
||||||
@@ -85,10 +86,12 @@ export default function BerryDashLeaderboards () {
|
|||||||
const [selected, setSelected] = useState<number>(-1)
|
const [selected, setSelected] = useState<number>(-1)
|
||||||
const [selectedBerryOption, setSelectedBerryOption] = useState<number>(0)
|
const [selectedBerryOption, setSelectedBerryOption] = useState<number>(0)
|
||||||
const [entries, setEntries] = useState<(LeaderboardEntry | Account)[]>([])
|
const [entries, setEntries] = useState<(LeaderboardEntry | Account)[]>([])
|
||||||
|
const [loading, setLoading] = useState<boolean>(false)
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const Refresh = useCallback(async () => {
|
const Refresh = useCallback(async () => {
|
||||||
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
if (selected == 3 || selected == 4) {
|
if (selected == 3 || selected == 4) {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
@@ -145,6 +148,7 @@ export default function BerryDashLeaderboards () {
|
|||||||
} catch {
|
} catch {
|
||||||
setEntries([])
|
setEntries([])
|
||||||
}
|
}
|
||||||
|
setLoading(false)
|
||||||
}, [selected, selectedBerryOption])
|
}, [selected, selectedBerryOption])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -160,6 +164,25 @@ export default function BerryDashLeaderboards () {
|
|||||||
<div className='flex justify-between items-center mb-4'>
|
<div className='flex justify-between items-center mb-4'>
|
||||||
<p className='text-3xl'>Berry Dash Leaderboards</p>
|
<p className='text-3xl'>Berry Dash Leaderboards</p>
|
||||||
<div className='flex gap-2'>
|
<div className='flex gap-2'>
|
||||||
|
{selected == 1 && (
|
||||||
|
<div className='flex justify-center'>
|
||||||
|
<Dropdown
|
||||||
|
value={selectedBerryOption}
|
||||||
|
options={[
|
||||||
|
{ label: 'Normal Berry', value: 0 },
|
||||||
|
{ label: 'Poison Berry', value: 1 },
|
||||||
|
{ label: 'Slow Berry', value: 2 },
|
||||||
|
{ label: 'Ultra Berry', value: 3 },
|
||||||
|
{ label: 'Speedy Berry', value: 4 },
|
||||||
|
{ label: 'Coin Berry', value: 5 },
|
||||||
|
{ label: 'Random Berry', value: 6 },
|
||||||
|
{ label: 'Anti Berry', value: 7 },
|
||||||
|
{ label: 'Golden Berry', value: 8 }
|
||||||
|
]}
|
||||||
|
onChange={e => setSelectedBerryOption(Number(e))}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
className='button btntheme1'
|
className='button btntheme1'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -174,7 +197,7 @@ export default function BerryDashLeaderboards () {
|
|||||||
<button
|
<button
|
||||||
className='button btntheme1'
|
className='button btntheme1'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (selected == -1) router.push('/game?id=1')
|
if (selected == -1) router.push('/main/game?id=1')
|
||||||
else {
|
else {
|
||||||
setSelected(-1)
|
setSelected(-1)
|
||||||
setSelectedBerryOption(0)
|
setSelectedBerryOption(0)
|
||||||
@@ -242,15 +265,15 @@ export default function BerryDashLeaderboards () {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
) : loading ? (
|
||||||
|
<p className='flex justify-center items-center text-6xl h-full'>
|
||||||
|
Loading
|
||||||
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className={`flex flex-col gap-2 overflow-y-auto ${
|
className={`flex flex-col gap-2 overflow-y-auto ${
|
||||||
selected == 1
|
platform() == 'windows'
|
||||||
? platform() == 'windows'
|
|
||||||
? 'h-[calc(100vh-156px)]'
|
|
||||||
: 'h-[calc(100vh-124px)]'
|
|
||||||
: platform() == 'windows'
|
|
||||||
? 'h-[calc(100vh-128px)]'
|
? 'h-[calc(100vh-128px)]'
|
||||||
: 'h-[calc(100vh-96px)]'
|
: 'h-[calc(100vh-96px)]'
|
||||||
} px-1`}
|
} px-1`}
|
||||||
@@ -312,25 +335,6 @@ export default function BerryDashLeaderboards () {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{selected == 1 && (
|
|
||||||
<div className='flex justify-center'>
|
|
||||||
<select
|
|
||||||
className='mt-1.25 bg-(--col2) border border-(--col4) rounded-md'
|
|
||||||
value={selectedBerryOption}
|
|
||||||
onChange={e => setSelectedBerryOption(Number(e.target.value))}
|
|
||||||
>
|
|
||||||
<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>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
.box {
|
||||||
|
@apply bg-(--col1)/50 border border-(--col3)/50 rounded-lg w-auto p-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard-button {
|
||||||
|
@apply bg-(--col2)/50 hover:bg-(--col4)/50 border border-(--col4)/50 hover:border-(--col6)/50 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)/50 hover:bg-(--col3)/50 border border-(--col4)/50 hover:border-(--col5)/50 cursor-pointer;
|
||||||
|
}
|
||||||
@@ -1,38 +1,35 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import '../Installs.css'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import '@/app/Installs.css'
|
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { useGlobal } from '@/app/GlobalProvider'
|
import { useGlobal } from '@/providers/GlobalProvider'
|
||||||
import { useRouter, useSearchParams } from 'next/navigation'
|
import { useRouter, useSearchParams } from 'next/navigation'
|
||||||
import { platform } from '@tauri-apps/plugin-os'
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
import { faWarning } from '@fortawesome/free-solid-svg-icons'
|
import { faWarning } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import { ask } from '@tauri-apps/plugin-dialog'
|
import { ask } from '@tauri-apps/plugin-dialog'
|
||||||
import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs'
|
import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs'
|
||||||
import { writeVersionsConfig } from '@/lib/BazookaManager'
|
import { openFolder } from '@/lib/util'
|
||||||
import { openFolder } from '@/lib/Util'
|
|
||||||
|
|
||||||
export default function Installs () {
|
export default function Installs () {
|
||||||
const {
|
const {
|
||||||
|
versionsList,
|
||||||
|
serverVersionList,
|
||||||
showPopup,
|
showPopup,
|
||||||
setShowPopup,
|
setShowPopup,
|
||||||
setPopupMode,
|
setPopupMode,
|
||||||
setFadeOut,
|
setFadeOut,
|
||||||
setSelectedVersionList,
|
setSelectedVersionList,
|
||||||
downloadedVersionsConfig,
|
|
||||||
setManagingVersion,
|
setManagingVersion,
|
||||||
getVersionInfo,
|
|
||||||
getGameInfo,
|
|
||||||
setSelectedGame,
|
setSelectedGame,
|
||||||
serverVersionList,
|
|
||||||
category,
|
category,
|
||||||
setCategory,
|
setCategory,
|
||||||
setDownloadedVersionsConfig,
|
|
||||||
downloadVersions,
|
downloadVersions,
|
||||||
downloadProgress,
|
downloadProgress,
|
||||||
linuxUseWine,
|
linuxUseWine,
|
||||||
linuxWineCommand
|
linuxWineCommand,
|
||||||
|
versions
|
||||||
} = useGlobal()
|
} = useGlobal()
|
||||||
|
|
||||||
const params = useSearchParams()
|
const params = useSearchParams()
|
||||||
@@ -55,14 +52,21 @@ export default function Installs () {
|
|||||||
if (!lastRevision) return false
|
if (!lastRevision) return false
|
||||||
return (
|
return (
|
||||||
lastRevision > 0 &&
|
lastRevision > 0 &&
|
||||||
(downloadedVersionsConfig == undefined
|
(versionsList == undefined ? 0 : versionsList[version]) / 1000 <=
|
||||||
? 0
|
|
||||||
: downloadedVersionsConfig?.list[version]) /
|
|
||||||
1000 <=
|
|
||||||
lastRevision
|
lastRevision
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const filteredVersions = Object.keys(versionsList).filter(v => {
|
||||||
|
const info = serverVersionList?.versions.find(vf => vf.id == v)
|
||||||
|
if (!info) return false
|
||||||
|
if (platform() == 'linux' && info.wine && !linuxUseWine) return false
|
||||||
|
return (
|
||||||
|
info.game === id &&
|
||||||
|
(category == -1 ? info.category == -1 : info.category == category)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mx-4 mt-4'>
|
<div className='mx-4 mt-4'>
|
||||||
<div className='flex justify-between items-center mb-4'>
|
<div className='flex justify-between items-center mb-4'>
|
||||||
@@ -70,7 +74,7 @@ export default function Installs () {
|
|||||||
className={`text-3xl truncate ${
|
className={`text-3xl truncate ${
|
||||||
category != -1
|
category != -1
|
||||||
? 'w-[calc(100vw-495px)]'
|
? 'w-[calc(100vw-495px)]'
|
||||||
: game.id == 1
|
: game.id == 1 || game.id == 9
|
||||||
? 'w-[calc(100vw-560px)]'
|
? 'w-[calc(100vw-560px)]'
|
||||||
: 'w-[calc(100vw-440px)]'
|
: 'w-[calc(100vw-440px)]'
|
||||||
}`}
|
}`}
|
||||||
@@ -81,13 +85,29 @@ export default function Installs () {
|
|||||||
<button
|
<button
|
||||||
className='button btntheme1'
|
className='button btntheme1'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
router.push('/game/berrydash/leaderboards')
|
router.push('/main/game/berrydash/leaderboards')
|
||||||
}}
|
}}
|
||||||
title='View the leaderboards for this game.'
|
title='View the leaderboards for this game.'
|
||||||
hidden={game.id != 1}
|
hidden={game.id != 1}
|
||||||
>
|
>
|
||||||
Leaderboards
|
Leaderboards
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
className='button btntheme1'
|
||||||
|
onClick={() =>
|
||||||
|
invoke('open_new_window', {
|
||||||
|
title: 'XPS Dashboard',
|
||||||
|
name: 'xpsdashboard',
|
||||||
|
url: 'https://xps.lncvrt.xyz/dashboard/',
|
||||||
|
width: 1280,
|
||||||
|
height: 720
|
||||||
|
})
|
||||||
|
}
|
||||||
|
title='Open the GDPS Dashboard!'
|
||||||
|
hidden={game.id != 9 || category != -1}
|
||||||
|
>
|
||||||
|
Dashboard
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
className='button btntheme1'
|
className='button btntheme1'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -122,12 +142,11 @@ export default function Installs () {
|
|||||||
>
|
>
|
||||||
{category == -1 &&
|
{category == -1 &&
|
||||||
Object.entries(game.categoryNames)
|
Object.entries(game.categoryNames)
|
||||||
.sort(([a], [b]) => Number(b) - Number(a))
|
|
||||||
.filter(([key]) => {
|
.filter(([key]) => {
|
||||||
const count = Object.keys(
|
const count = Object.keys(versionsList).filter(v => {
|
||||||
downloadedVersionsConfig?.list ?? {}
|
const info = serverVersionList?.versions.find(
|
||||||
).filter(v => {
|
vf => vf.id == v
|
||||||
const info = getVersionInfo(v)
|
)
|
||||||
if (!info) return false
|
if (!info) return false
|
||||||
|
|
||||||
if (platform() == 'linux' && info.wine && !linuxUseWine)
|
if (platform() == 'linux' && info.wine && !linuxUseWine)
|
||||||
@@ -138,6 +157,7 @@ export default function Installs () {
|
|||||||
|
|
||||||
return count >= 1
|
return count >= 1
|
||||||
})
|
})
|
||||||
|
.sort(([a], [b]) => Number(b) - Number(a))
|
||||||
.map(([key, value]) => {
|
.map(([key, value]) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -157,10 +177,10 @@ export default function Installs () {
|
|||||||
<p>
|
<p>
|
||||||
{(() => {
|
{(() => {
|
||||||
const count =
|
const count =
|
||||||
Object.keys(
|
Object.keys(versionsList).filter(v => {
|
||||||
downloadedVersionsConfig?.list ?? []
|
const info = serverVersionList?.versions.find(
|
||||||
).filter(v => {
|
vf => vf.id == v
|
||||||
const info = getVersionInfo(v)
|
)
|
||||||
if (!info) return false
|
if (!info) return false
|
||||||
if (
|
if (
|
||||||
platform() == 'linux' &&
|
platform() == 'linux' &&
|
||||||
@@ -181,44 +201,43 @@ export default function Installs () {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
{Object.keys(downloadedVersionsConfig?.list ?? []).filter(v => {
|
{filteredVersions.length === 0 &&
|
||||||
const info = getVersionInfo(v)
|
(category !== -1 ||
|
||||||
if (!info) return false
|
Object.keys(versionsList).filter(v => {
|
||||||
return info.game === id
|
const info = serverVersionList?.versions.find(vf => vf.id == v)
|
||||||
}).length != 0 ? (
|
|
||||||
Object.keys(downloadedVersionsConfig?.list ?? [])
|
|
||||||
.sort((a, b) => {
|
|
||||||
const infoA = getVersionInfo(a)
|
|
||||||
const infoB = getVersionInfo(b)
|
|
||||||
if (!infoA || !infoB) return 0
|
|
||||||
return infoB.place - infoA.place
|
|
||||||
})
|
|
||||||
.filter(v => {
|
|
||||||
const info = getVersionInfo(v)
|
|
||||||
if (!info) return false
|
if (!info) return false
|
||||||
|
|
||||||
if (platform() == 'linux' && info.wine && !linuxUseWine)
|
if (platform() == 'linux' && info.wine && !linuxUseWine)
|
||||||
return false
|
return false
|
||||||
return (
|
|
||||||
info.game === id &&
|
return info.game === id
|
||||||
(category == -1
|
}).length === 0) && (
|
||||||
? info.category == -1
|
<div className='flex justify-center items-center h-full'>
|
||||||
: info.category == category)
|
<p className='text-3xl'>No versions installed</p>
|
||||||
)
|
</div>
|
||||||
})
|
)}
|
||||||
.map(entry => (
|
{filteredVersions
|
||||||
|
.sort((a, b) => {
|
||||||
|
const infoA = serverVersionList?.versions.find(vf => vf.id == a)
|
||||||
|
const infoB = serverVersionList?.versions.find(vf => vf.id == b)
|
||||||
|
if (!infoA || !infoB) return 0
|
||||||
|
return infoB.place - infoA.place
|
||||||
|
})
|
||||||
|
.map(v => {
|
||||||
|
const versionInfo = serverVersionList?.versions.find(
|
||||||
|
vf => vf.id == v
|
||||||
|
)
|
||||||
|
if (!versionInfo) return
|
||||||
|
|
||||||
|
return (
|
||||||
<div
|
<div
|
||||||
key={entry}
|
key={v}
|
||||||
className={'downloads-entry'}
|
className={'downloads-entry'}
|
||||||
title={
|
title={
|
||||||
'Click to launch game. Right-click to manage this version install'
|
'Click to launch game. Right-click to manage this version install'
|
||||||
}
|
}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (
|
if (needsRevisionUpdate(versionInfo.lastRevision, v)) {
|
||||||
needsRevisionUpdate(
|
|
||||||
getVersionInfo(entry)?.lastRevision,
|
|
||||||
entry
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
const answer = await ask(
|
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.',
|
'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.',
|
||||||
{
|
{
|
||||||
@@ -242,55 +261,45 @@ export default function Installs () {
|
|||||||
setFadeOut(false)
|
setFadeOut(false)
|
||||||
|
|
||||||
//uninstall
|
//uninstall
|
||||||
setDownloadedVersionsConfig(prev => {
|
versions?.set(
|
||||||
if (!prev) return prev
|
'list',
|
||||||
const updatedList = Object.fromEntries(
|
Object.fromEntries(
|
||||||
Object.entries(prev.list).filter(
|
Object.entries(versionsList).filter(
|
||||||
([k]) => k !== entry
|
([k]) => k !== v
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
const updatedConfig = {
|
)
|
||||||
...prev,
|
|
||||||
list: updatedList
|
|
||||||
}
|
|
||||||
writeVersionsConfig(updatedConfig)
|
|
||||||
return updatedConfig
|
|
||||||
})
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
await exists('game/' + entry, {
|
await exists('game/' + v, {
|
||||||
baseDir: BaseDirectory.AppLocalData
|
baseDir: BaseDirectory.AppLocalData
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
await remove('game/' + entry, {
|
await remove('game/' + v, {
|
||||||
baseDir: BaseDirectory.AppLocalData,
|
baseDir: BaseDirectory.AppLocalData,
|
||||||
recursive: true
|
recursive: true
|
||||||
})
|
})
|
||||||
|
|
||||||
//reinstall
|
//reinstall
|
||||||
setSelectedVersionList([entry])
|
setSelectedVersionList([v])
|
||||||
downloadVersions([
|
downloadVersions([
|
||||||
{
|
{
|
||||||
id: entry,
|
id: v,
|
||||||
type: 0
|
type: 0
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
} else {
|
} else {
|
||||||
openFolder(entry)
|
openFolder(v)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const verInfo = getVersionInfo(entry)
|
|
||||||
if (verInfo == undefined) return
|
|
||||||
const gameInfo = getGameInfo(verInfo.game)
|
|
||||||
if (gameInfo == undefined) return
|
|
||||||
invoke('launch_game', {
|
invoke('launch_game', {
|
||||||
name: verInfo.id,
|
name: versionInfo.id,
|
||||||
executable: verInfo.executable,
|
executable: versionInfo.executable,
|
||||||
displayName: verInfo.displayName,
|
displayName: versionInfo.displayName,
|
||||||
useWine: !!(
|
useWine: !!(
|
||||||
platform() == 'linux' &&
|
platform() == 'linux' &&
|
||||||
verInfo.wine &&
|
versionInfo.wine &&
|
||||||
linuxUseWine
|
linuxUseWine
|
||||||
),
|
),
|
||||||
wineCommand: linuxWineCommand
|
wineCommand: linuxWineCommand
|
||||||
@@ -298,16 +307,14 @@ export default function Installs () {
|
|||||||
}}
|
}}
|
||||||
onContextMenu={e => {
|
onContextMenu={e => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setManagingVersion(entry)
|
setManagingVersion(v)
|
||||||
setPopupMode(2)
|
setPopupMode(2)
|
||||||
setShowPopup(true)
|
setShowPopup(true)
|
||||||
setFadeOut(false)
|
setFadeOut(false)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='h-18 w-screen relative'>
|
<div className='h-18 w-screen relative'>
|
||||||
<p className='text-2xl'>
|
<p className='text-2xl'>{versionInfo.displayName}</p>
|
||||||
{getVersionInfo(entry)?.displayName}{' '}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className='flex gap-2 absolute left-0 bottom-0'>
|
<div className='flex gap-2 absolute left-0 bottom-0'>
|
||||||
<div
|
<div
|
||||||
@@ -317,7 +324,7 @@ export default function Installs () {
|
|||||||
<p>
|
<p>
|
||||||
Installed{' '}
|
Installed{' '}
|
||||||
{new Intl.DateTimeFormat(undefined).format(
|
{new Intl.DateTimeFormat(undefined).format(
|
||||||
downloadedVersionsConfig?.list[entry]
|
versionsList[v]
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -325,13 +332,8 @@ export default function Installs () {
|
|||||||
className='entry-info-item'
|
className='entry-info-item'
|
||||||
title='This version is using wine. It cannot be guarenteed to work fully and might not work at all.'
|
title='This version is using wine. It cannot be guarenteed to work fully and might not work at all.'
|
||||||
hidden={
|
hidden={
|
||||||
!(
|
!(platform() == 'linux' && versionInfo.wine) ||
|
||||||
platform() == 'linux' && getVersionInfo(entry)?.wine
|
needsRevisionUpdate(versionInfo.lastRevision, v)
|
||||||
) ||
|
|
||||||
needsRevisionUpdate(
|
|
||||||
getVersionInfo(entry)?.lastRevision,
|
|
||||||
entry
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
|
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
|
||||||
@@ -340,10 +342,7 @@ export default function Installs () {
|
|||||||
<div
|
<div
|
||||||
className='entry-info-item'
|
className='entry-info-item'
|
||||||
hidden={
|
hidden={
|
||||||
!needsRevisionUpdate(
|
!needsRevisionUpdate(versionInfo.lastRevision, v)
|
||||||
getVersionInfo(entry)?.lastRevision,
|
|
||||||
entry
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
|
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
|
||||||
@@ -357,45 +356,41 @@ export default function Installs () {
|
|||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!(await exists('game/' + entry + '/BepInEx', {
|
!(await exists('game/' + v + '/BepInEx', {
|
||||||
baseDir: BaseDirectory.AppLocalData
|
baseDir: BaseDirectory.AppLocalData
|
||||||
}))
|
}))
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
(await ask(
|
(await ask(
|
||||||
"You don't have BepInEx (the mod loader for Unity Games), would you like to install it now? It is about 1MB in size. If you choose yes, it will download the recommended BepInEx version for " +
|
"You don't have BepInEx (the mod loader for Unity Games), would you like to install it now? It is about 1MB in size. If you choose yes, it will download the recommended BepInEx version for " +
|
||||||
getVersionInfo(entry)?.displayName +
|
versionInfo.displayName +
|
||||||
'.',
|
'.',
|
||||||
{ title: 'BepInEx not found!', kind: 'error' }
|
{ title: 'BepInEx not found!', kind: 'error' }
|
||||||
)) &&
|
)) &&
|
||||||
!downloadProgress.find(d => d.version == entry)
|
!downloadProgress.find(d => d.version == v)
|
||||||
) {
|
) {
|
||||||
downloadVersions([
|
downloadVersions([
|
||||||
{
|
{
|
||||||
id: entry,
|
id: v,
|
||||||
type: 1
|
type: 1
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setManagingVersion(entry)
|
setManagingVersion(v)
|
||||||
setPopupMode(3)
|
setPopupMode(3)
|
||||||
setShowPopup(true)
|
setShowPopup(true)
|
||||||
setFadeOut(false)
|
setFadeOut(false)
|
||||||
}}
|
}}
|
||||||
hidden={!getVersionInfo(entry)?.modSupportDownload}
|
hidden={!versionInfo.modSupportDownload}
|
||||||
>
|
>
|
||||||
Mod Manager
|
Mod Manager
|
||||||
</button>
|
</button>
|
||||||
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,21 +1,13 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import './Globals.css'
|
import '@/styles/globals.css'
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import Sidebar from '@/components/Sidebar'
|
import Sidebar from '@/components/Sidebar'
|
||||||
import { DownloadProgress } from '@/types/DownloadProgress'
|
import { DownloadProgress } from '@/types/DownloadProgress'
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
||||||
import { faChevronLeft, faXmark } from '@fortawesome/free-solid-svg-icons'
|
|
||||||
import { readVersionsConfig, writeVersionsConfig } from '@/lib/BazookaManager'
|
|
||||||
import { VersionsConfig } from '@/types/VersionsConfig'
|
|
||||||
import { app } from '@tauri-apps/api'
|
import { app } from '@tauri-apps/api'
|
||||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
import { GlobalProvider } from '@/providers/GlobalProvider'
|
||||||
import { GlobalProvider } from './GlobalProvider'
|
|
||||||
import { Roboto } from 'next/font/google'
|
import { Roboto } from 'next/font/google'
|
||||||
import { ServerVersionsResponse } from '@/types/ServerVersionsResponse'
|
import { ServerVersionsResponse } from '@/types/ServerVersionsResponse'
|
||||||
import { GameVersion } from '@/types/GameVersion'
|
|
||||||
import { Game } from '@/types/Game'
|
|
||||||
import { listen } from '@tauri-apps/api/event'
|
import { listen } from '@tauri-apps/api/event'
|
||||||
import { usePathname } from 'next/navigation'
|
import { usePathname } from 'next/navigation'
|
||||||
import { arch, platform } from '@tauri-apps/plugin-os'
|
import { arch, platform } from '@tauri-apps/plugin-os'
|
||||||
@@ -25,22 +17,28 @@ import {
|
|||||||
} from '@tauri-apps/plugin-notification'
|
} from '@tauri-apps/plugin-notification'
|
||||||
import {
|
import {
|
||||||
BaseDirectory,
|
BaseDirectory,
|
||||||
|
copyFile,
|
||||||
exists,
|
exists,
|
||||||
readTextFile,
|
readTextFile,
|
||||||
remove
|
remove
|
||||||
} from '@tauri-apps/plugin-fs'
|
} from '@tauri-apps/plugin-fs'
|
||||||
import { fetch } from '@tauri-apps/plugin-http'
|
import { fetch } from '@tauri-apps/plugin-http'
|
||||||
import { verifySignature } from '@/lib/Util'
|
import { verifySignature } from '@/lib/util'
|
||||||
import { getCurrentWindow, UserAttentionType } from '@tauri-apps/api/window'
|
import { getCurrentWindow, UserAttentionType } from '@tauri-apps/api/window'
|
||||||
|
|
||||||
import VersionsDownloadPopup from '@/components/popups/VersionsDownload'
|
|
||||||
import GamesDownloadPopup from '@/components/popups/GamesDownload'
|
|
||||||
import DownloadsPopup from '@/components/popups/Downloads'
|
|
||||||
import ManageVersionPopup from '@/components/popups/ManageVersion'
|
|
||||||
import ModDownloadsPopup from '@/components/popups/ModDownloads'
|
|
||||||
import { Mod } from '@/types/Mod'
|
import { Mod } from '@/types/Mod'
|
||||||
import { load, Store } from '@tauri-apps/plugin-store'
|
import { load, Store } from '@tauri-apps/plugin-store'
|
||||||
import { notifyUser } from '@/lib/Notifications'
|
import { notifyUser } from '@/lib/notifications'
|
||||||
|
import { GameVersion } from '@/types/GameVersion'
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
import { faChevronLeft, faXmark } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
|
import VersionsDownloadPopup from '@/popups/VersionsDownload'
|
||||||
|
import GamesDownloadPopup from '@/popups/GamesDownload'
|
||||||
|
import DownloadsPopup from '@/popups/Downloads'
|
||||||
|
import ManageVersionPopup from '@/popups/ManageVersion'
|
||||||
|
import ModDownloadsPopup from '@/popups/ModDownloads'
|
||||||
|
import VersionChangelogPopup from '@/popups/VersionChangelog'
|
||||||
|
|
||||||
const roboto = Roboto({
|
const roboto = Roboto({
|
||||||
subsets: ['latin']
|
subsets: ['latin']
|
||||||
@@ -53,7 +51,6 @@ export default function RootLayout ({
|
|||||||
}) {
|
}) {
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
const [loadingText, setLoadingText] = useState('Loading...')
|
const [loadingText, setLoadingText] = useState('Loading...')
|
||||||
const [outdated, setOutdated] = useState(false)
|
|
||||||
const [version, setVersion] = useState<string | null>(null)
|
const [version, setVersion] = useState<string | null>(null)
|
||||||
const [platformName, setPlatformName] = useState<string | null>(null)
|
const [platformName, setPlatformName] = useState<string | null>(null)
|
||||||
|
|
||||||
@@ -61,9 +58,6 @@ export default function RootLayout ({
|
|||||||
useState<null | ServerVersionsResponse>(null)
|
useState<null | ServerVersionsResponse>(null)
|
||||||
const [selectedVersionList, setSelectedVersionList] = useState<string[]>([])
|
const [selectedVersionList, setSelectedVersionList] = useState<string[]>([])
|
||||||
|
|
||||||
const [downloadedVersionsConfig, setDownloadedVersionsConfig] =
|
|
||||||
useState<VersionsConfig | null>(null)
|
|
||||||
|
|
||||||
const [showPopup, setShowPopup] = useState(false)
|
const [showPopup, setShowPopup] = useState(false)
|
||||||
const [popupMode, setPopupMode] = useState<null | number>(null)
|
const [popupMode, setPopupMode] = useState<null | number>(null)
|
||||||
const [fadeOut, setFadeOut] = useState(false)
|
const [fadeOut, setFadeOut] = useState(false)
|
||||||
@@ -85,6 +79,7 @@ export default function RootLayout ({
|
|||||||
const revisionCheck = useRef(false)
|
const revisionCheck = useRef(false)
|
||||||
|
|
||||||
const [settings, setSettings] = useState<Store | null>(null)
|
const [settings, setSettings] = useState<Store | null>(null)
|
||||||
|
const [versions, setVersions] = useState<Store | null>(null)
|
||||||
|
|
||||||
const [notificationsAllowed, setNotificationsAllowed] =
|
const [notificationsAllowed, setNotificationsAllowed] =
|
||||||
useState<boolean>(false)
|
useState<boolean>(false)
|
||||||
@@ -93,17 +88,21 @@ export default function RootLayout ({
|
|||||||
const [linuxUseWine, setLinuxUseWine] = useState<boolean>(false)
|
const [linuxUseWine, setLinuxUseWine] = useState<boolean>(false)
|
||||||
const [linuxWineCommand, setLinuxWineCommand] =
|
const [linuxWineCommand, setLinuxWineCommand] =
|
||||||
useState<string>('wine %path%')
|
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[] {
|
function getSpecialVersionsList (game?: number): GameVersion[] {
|
||||||
if (!serverVersionList) return []
|
if (!serverVersionList) return []
|
||||||
|
|
||||||
return serverVersionList.versions
|
return serverVersionList.versions
|
||||||
.filter(
|
.filter(v => !Object.keys(versionsList).includes(v.id))
|
||||||
v => !Object.keys(downloadedVersionsConfig?.list ?? []).includes(v.id)
|
|
||||||
)
|
|
||||||
.filter(v => {
|
.filter(v => {
|
||||||
if (platformName == 'linux' && v.wine && linuxUseWine) return false
|
if (platformName == 'linux' && v.wine && !linuxUseWine) return false
|
||||||
|
|
||||||
if (game && v.game != game) return false
|
if (game && v.game != game) return false
|
||||||
if (category != -1 && v.category != category) return false
|
if (category != -1 && v.category != category) return false
|
||||||
@@ -118,64 +117,8 @@ export default function RootLayout ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const getVersionInfo = useCallback(
|
|
||||||
(id: string | undefined): GameVersion | undefined => {
|
|
||||||
if (!id) return undefined
|
|
||||||
return serverVersionList?.versions.find(v => v.id === id)
|
|
||||||
},
|
|
||||||
[serverVersionList]
|
|
||||||
)
|
|
||||||
|
|
||||||
const getGameInfo = useCallback(
|
|
||||||
(game: number | undefined): Game | undefined => {
|
|
||||||
if (!game) return undefined
|
|
||||||
return serverVersionList?.games.find(g => g.id === game)
|
|
||||||
},
|
|
||||||
[serverVersionList]
|
|
||||||
)
|
|
||||||
|
|
||||||
function getListOfGames (): Game[] {
|
|
||||||
if (!downloadedVersionsConfig?.list) return []
|
|
||||||
|
|
||||||
const gamesMap = new Map<number, Game>()
|
|
||||||
|
|
||||||
Object.keys(downloadedVersionsConfig.list).forEach(i => {
|
|
||||||
const version = getVersionInfo(i)
|
|
||||||
if (!version) return
|
|
||||||
const game = getGameInfo(version.game)
|
|
||||||
if (!game) return
|
|
||||||
gamesMap.set(game.id, game)
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.from(gamesMap.values())
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVersionsAmountData (gameId: number): {
|
|
||||||
installed: number
|
|
||||||
total: number
|
|
||||||
} | null {
|
|
||||||
if (!downloadedVersionsConfig || !serverVersionList) return null
|
|
||||||
|
|
||||||
const allowWine = platformName !== 'linux' || linuxUseWine
|
|
||||||
|
|
||||||
const installed = Object.keys(downloadedVersionsConfig.list).filter(v => {
|
|
||||||
const info = getVersionInfo(v)
|
|
||||||
if (!info) return false
|
|
||||||
if (info.wine && !allowWine) return false
|
|
||||||
return getGameInfo(info.game)?.id === gameId
|
|
||||||
}).length
|
|
||||||
|
|
||||||
const total = serverVersionList.versions.filter(v => {
|
|
||||||
if (!v) return false
|
|
||||||
if (v.wine && !allowWine) return false
|
|
||||||
return getGameInfo(v.game)?.id === gameId
|
|
||||||
}).length
|
|
||||||
|
|
||||||
return { installed, total }
|
|
||||||
}
|
|
||||||
|
|
||||||
const closePopup = useCallback(() => {
|
const closePopup = useCallback(() => {
|
||||||
if (popupMode == 0 && selectedGame && pathname === '/') {
|
if (popupMode == 0 && selectedGame && pathname === '/main') {
|
||||||
setSelectedGame(null)
|
setSelectedGame(null)
|
||||||
setSelectedVersionList([])
|
setSelectedVersionList([])
|
||||||
} else if (viewingInfoFromDownloads) {
|
} else if (viewingInfoFromDownloads) {
|
||||||
@@ -183,6 +126,8 @@ export default function RootLayout ({
|
|||||||
setPopupMode(0)
|
setPopupMode(0)
|
||||||
} else if (popupMode == 3 && showModInfo) {
|
} else if (popupMode == 3 && showModInfo) {
|
||||||
setShowModInfo(null)
|
setShowModInfo(null)
|
||||||
|
} else if (popupMode == 4) {
|
||||||
|
setPopupMode(2)
|
||||||
} else {
|
} else {
|
||||||
setFadeOut(true)
|
setFadeOut(true)
|
||||||
setTimeout(() => setShowPopup(false), 200)
|
setTimeout(() => setShowPopup(false), 200)
|
||||||
@@ -321,27 +266,6 @@ export default function RootLayout ({
|
|||||||
setPlatformName(platform())
|
setPlatformName(platform())
|
||||||
const client = await app.getVersion()
|
const client = await app.getVersion()
|
||||||
setVersion(client)
|
setVersion(client)
|
||||||
if (process.env.NODE_ENV === 'production') {
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
'https://games.lncvrt.xyz/api/launcher/latest'
|
|
||||||
)
|
|
||||||
const signature = response.headers.get('x-signature') ?? ''
|
|
||||||
const data = await response.text()
|
|
||||||
if (await verifySignature(data, signature)) {
|
|
||||||
if (data !== client) {
|
|
||||||
setOutdated(true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setLoadingText('Failed to check latest version.')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
setLoadingText('Failed to check latest version.')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`https://games.lncvrt.xyz/api/launcher/versions?platform=${platform()}&arch=${arch()}`
|
`https://games.lncvrt.xyz/api/launcher/versions?platform=${platform()}&arch=${arch()}`
|
||||||
@@ -358,6 +282,29 @@ export default function RootLayout ({
|
|||||||
setLoadingText('Failed to download versions list.')
|
setLoadingText('Failed to download versions list.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const legacyOptions = {
|
||||||
|
baseDir: BaseDirectory.AppLocalData
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
platform() == 'windows' &&
|
||||||
|
(await exists('versions.json', legacyOptions))
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
await exists('versions.json', {
|
||||||
|
baseDir: BaseDirectory.AppConfig
|
||||||
|
})
|
||||||
|
)
|
||||||
|
await remove('versions.json', {
|
||||||
|
baseDir: BaseDirectory.AppConfig
|
||||||
|
})
|
||||||
|
|
||||||
|
await copyFile('versions.json', 'versions.json', {
|
||||||
|
fromPathBaseDir: BaseDirectory.AppLocalData,
|
||||||
|
toPathBaseDir: BaseDirectory.AppConfig
|
||||||
|
})
|
||||||
|
await remove('versions.json', legacyOptions)
|
||||||
|
}
|
||||||
|
|
||||||
const settingsLocal = await load('settings.json', {
|
const settingsLocal = await load('settings.json', {
|
||||||
autoSave: true,
|
autoSave: true,
|
||||||
defaults: {
|
defaults: {
|
||||||
@@ -366,15 +313,22 @@ export default function RootLayout ({
|
|||||||
sidebarAlwaysShowGames: true,
|
sidebarAlwaysShowGames: true,
|
||||||
linuxUseWine: false,
|
linuxUseWine: false,
|
||||||
linuxWineCommand: 'wine %path%',
|
linuxWineCommand: 'wine %path%',
|
||||||
theme: 'dark'
|
theme: 'dark',
|
||||||
|
customDataLocation: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const versionsLocal = await load('versions.json', {
|
||||||
|
autoSave: true,
|
||||||
|
defaults: {
|
||||||
|
version: client,
|
||||||
|
list: {},
|
||||||
|
mods: {}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
settingsLocal.set('version', client)
|
settingsLocal.set('version', client)
|
||||||
const oldSettingsOptions = {
|
versionsLocal.set('version', client)
|
||||||
baseDir: BaseDirectory.AppLocalData
|
if (await exists('config.json', legacyOptions)) {
|
||||||
}
|
const config = await readTextFile('config.json', legacyOptions)
|
||||||
if (await exists('config.json', oldSettingsOptions)) {
|
|
||||||
const config = await readTextFile('config.json', oldSettingsOptions)
|
|
||||||
const raw = JSON.parse(config)
|
const raw = JSON.parse(config)
|
||||||
if (
|
if (
|
||||||
raw.settings &&
|
raw.settings &&
|
||||||
@@ -432,11 +386,10 @@ export default function RootLayout ({
|
|||||||
})()
|
})()
|
||||||
settingsLocal?.set('theme', tempTheme)
|
settingsLocal?.set('theme', tempTheme)
|
||||||
}
|
}
|
||||||
await remove('config.json', oldSettingsOptions)
|
await remove('config.json', legacyOptions)
|
||||||
}
|
}
|
||||||
const versionsConfig = await readVersionsConfig()
|
|
||||||
setDownloadedVersionsConfig(versionsConfig)
|
|
||||||
setSettings(settingsLocal)
|
setSettings(settingsLocal)
|
||||||
|
setVersions(versionsLocal)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
||||||
if (!(await isPermissionGranted())) {
|
if (!(await isPermissionGranted())) {
|
||||||
@@ -510,8 +463,13 @@ export default function RootLayout ({
|
|||||||
|
|
||||||
const versionId = downloadQueue[0]
|
const versionId = downloadQueue[0]
|
||||||
const downloadInfo = downloadProgress.find(d => d.version == versionId)
|
const downloadInfo = downloadProgress.find(d => d.version == versionId)
|
||||||
if (!downloadInfo) return
|
if (!downloadInfo) {
|
||||||
const info = getVersionInfo(versionId)
|
setDownloadProgress(prev => prev.filter(d => d.version !== versionId))
|
||||||
|
setDownloadQueue(prev => prev.slice(1))
|
||||||
|
setIsProcessingQueue(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const info = serverVersionList?.versions.find(vf => vf.id == versionId)
|
||||||
|
|
||||||
if (!info) {
|
if (!info) {
|
||||||
setDownloadProgress(prev => prev.filter(d => d.version !== versionId))
|
setDownloadProgress(prev => prev.filter(d => d.version !== versionId))
|
||||||
@@ -520,7 +478,7 @@ export default function RootLayout ({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const gameInfo = getGameInfo(info.game)
|
const gameInfo = serverVersionList?.games.find(vf => vf.id == info.game)
|
||||||
if (!gameInfo) {
|
if (!gameInfo) {
|
||||||
setDownloadProgress(prev => prev.filter(d => d.version !== versionId))
|
setDownloadProgress(prev => prev.filter(d => d.version !== versionId))
|
||||||
setDownloadQueue(prev => prev.slice(1))
|
setDownloadQueue(prev => prev.slice(1))
|
||||||
@@ -555,7 +513,7 @@ export default function RootLayout ({
|
|||||||
: d
|
: d
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (await settings?.get<boolean>('notifications-allowed'))
|
if (await settings?.get<boolean>('notificationsAllowed'))
|
||||||
await notifyUser(
|
await notifyUser(
|
||||||
'Download Failed',
|
'Download Failed',
|
||||||
`The download for version ${info.displayName} has failed.`
|
`The download for version ${info.displayName} has failed.`
|
||||||
@@ -590,31 +548,19 @@ export default function RootLayout ({
|
|||||||
if (res === '1') {
|
if (res === '1') {
|
||||||
setDownloadProgress(prev => prev.filter(d => d.version !== versionId))
|
setDownloadProgress(prev => prev.filter(d => d.version !== versionId))
|
||||||
if (downloadInfo.type != 1) {
|
if (downloadInfo.type != 1) {
|
||||||
setDownloadedVersionsConfig(prev => {
|
if (downloadInfo.type == 2) {
|
||||||
if (!prev) return prev
|
versions?.set('mods', {
|
||||||
|
...modsList,
|
||||||
const updated =
|
[downloadInfo.modGame! + '-' + downloadInfo.modId!]: {
|
||||||
downloadInfo.type == 2
|
[downloadInfo.modVersion!]: Date.now()
|
||||||
? {
|
}
|
||||||
...prev,
|
})
|
||||||
mods: {
|
} else {
|
||||||
...prev.mods,
|
versions?.set('list', {
|
||||||
[downloadInfo.modGame! + '-' + downloadInfo.modId!]: {
|
...versionsList,
|
||||||
[downloadInfo.modVersion!]: Date.now()
|
[versionId]: Date.now()
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
: {
|
|
||||||
...prev,
|
|
||||||
list: {
|
|
||||||
...prev.list,
|
|
||||||
[versionId]: Date.now()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writeVersionsConfig(updated)
|
|
||||||
return updated
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} else if (res == '0') {
|
} else if (res == '0') {
|
||||||
setDownloadProgress(prev => {
|
setDownloadProgress(prev => {
|
||||||
@@ -640,7 +586,7 @@ export default function RootLayout ({
|
|||||||
: d
|
: d
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (await settings?.get<boolean>('notifications-allowed'))
|
if (await settings?.get<boolean>('notificationsAllowed'))
|
||||||
await notifyUser(
|
await notifyUser(
|
||||||
'Download Failed',
|
'Download Failed',
|
||||||
`The download for version ${info.displayName} has failed.`
|
`The download for version ${info.displayName} has failed.`
|
||||||
@@ -658,39 +604,35 @@ export default function RootLayout ({
|
|||||||
}, [
|
}, [
|
||||||
downloadQueue,
|
downloadQueue,
|
||||||
isProcessingQueue,
|
isProcessingQueue,
|
||||||
getVersionInfo,
|
|
||||||
getGameInfo,
|
|
||||||
downloadProgress,
|
downloadProgress,
|
||||||
settings
|
serverVersionList,
|
||||||
|
settings,
|
||||||
|
versions,
|
||||||
|
versionsList,
|
||||||
|
modsList
|
||||||
])
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (revisionCheck.current) return
|
if (revisionCheck.current) return
|
||||||
if (!serverVersionList || !downloadedVersionsConfig) return
|
if (!serverVersionList) return
|
||||||
revisionCheck.current = true
|
revisionCheck.current = true
|
||||||
;(async () => {
|
;(async () => {
|
||||||
for (const [key, value] of Object.entries(
|
for (const [key, value] of Object.entries(versionsList)) {
|
||||||
downloadedVersionsConfig.list
|
|
||||||
)) {
|
|
||||||
const verInfo = serverVersionList.versions.find(item => item.id === key)
|
const verInfo = serverVersionList.versions.find(item => item.id === key)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!verInfo ||
|
verInfo &&
|
||||||
(verInfo.lastRevision > 0 && value / 1000 <= verInfo.lastRevision)
|
verInfo.lastRevision > 0 &&
|
||||||
|
value / 1000 <= verInfo.lastRevision
|
||||||
) {
|
) {
|
||||||
if (
|
await invoke('remove_stale_executable', {
|
||||||
await exists('game/' + key + '/' + verInfo?.executable, {
|
version: key,
|
||||||
baseDir: BaseDirectory.AppLocalData
|
executable: verInfo.executable
|
||||||
})
|
})
|
||||||
)
|
|
||||||
await remove('game/' + key + '/' + verInfo?.executable, {
|
|
||||||
baseDir: BaseDirectory.AppLocalData,
|
|
||||||
recursive: true
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
}, [serverVersionList, downloadedVersionsConfig, downloadVersions])
|
}, [serverVersionList, versionsList])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
@@ -719,35 +661,47 @@ export default function RootLayout ({
|
|||||||
])
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!settings) return
|
if (!settings || !versions) return
|
||||||
const unlisteners: Promise<() => void>[] = []
|
const unlisteners: Promise<() => void>[] = []
|
||||||
|
|
||||||
function watch<T> (key: string, fn: (v: T | undefined) => void) {
|
function watchSettings<T> (key: string, fn: (v: T | undefined) => void) {
|
||||||
settings!.get<T>(key).then(fn)
|
settings!.get<T>(key).then(fn)
|
||||||
unlisteners.push(settings!.onKeyChange<T>(key, fn))
|
unlisteners.push(settings!.onKeyChange<T>(key, fn))
|
||||||
}
|
}
|
||||||
|
|
||||||
watch<string>('theme', v => setTheme(v ?? 'dark'))
|
function watchVersions<T> (key: string, fn: (v: T | undefined) => void) {
|
||||||
watch<boolean>('notificationsAllowed', v =>
|
versions!.get<T>(key).then(fn)
|
||||||
|
unlisteners.push(versions!.onKeyChange<T>(key, fn))
|
||||||
|
}
|
||||||
|
|
||||||
|
watchSettings<boolean>('notificationsAllowed', v =>
|
||||||
setNotificationsAllowed(v ?? true)
|
setNotificationsAllowed(v ?? true)
|
||||||
)
|
)
|
||||||
watch<boolean>('sidebarAlwaysShowGames', v =>
|
watchSettings<boolean>('sidebarAlwaysShowGames', v =>
|
||||||
setSidebarAlwaysShowGames(v ?? true)
|
setSidebarAlwaysShowGames(v ?? true)
|
||||||
)
|
)
|
||||||
watch<boolean>('linuxUseWine', v => setLinuxUseWine(v ?? false))
|
watchSettings<boolean>('linuxUseWine', v => setLinuxUseWine(v ?? false))
|
||||||
watch<string>('linuxWineCommand', v =>
|
watchSettings<string>('linuxWineCommand', v =>
|
||||||
setLinuxWineCommand(v ?? 'wine %path%')
|
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 =>
|
||||||
|
setModsList(v ?? {})
|
||||||
|
)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unlisteners.forEach(u => u.then(fn => fn()))
|
unlisteners.forEach(u => u.then(fn => fn()))
|
||||||
}
|
}
|
||||||
}, [settings])
|
}, [settings, versions])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<html lang='en' className={roboto.className}>
|
<html lang='en' className={roboto.className}>
|
||||||
<body className={theme + '-theme'}>
|
<body>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
@@ -761,24 +715,7 @@ export default function RootLayout ({
|
|||||||
: 'h-screen'
|
: 'h-screen'
|
||||||
} flex items-center justify-center`}
|
} flex items-center justify-center`}
|
||||||
>
|
>
|
||||||
{outdated ? (
|
<p className='text-7xl text-center'>{loadingText}</p>
|
||||||
<div className='text-center'>
|
|
||||||
<p className='text-6xl mb-4'>Outdated Launcher!</p>
|
|
||||||
<p className='text-2xl mb-4'>
|
|
||||||
Please update to the latest version to continue.
|
|
||||||
</p>
|
|
||||||
<button
|
|
||||||
className='button btntheme1'
|
|
||||||
onClick={() =>
|
|
||||||
openUrl('https://games.lncvrt.xyz/download')
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Download latest version!
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<p className='text-7xl text-center'>{loadingText}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
@@ -795,15 +732,9 @@ export default function RootLayout ({
|
|||||||
setPopupMode,
|
setPopupMode,
|
||||||
fadeOut,
|
fadeOut,
|
||||||
setFadeOut,
|
setFadeOut,
|
||||||
downloadedVersionsConfig,
|
|
||||||
setDownloadedVersionsConfig,
|
|
||||||
managingVersion,
|
managingVersion,
|
||||||
setManagingVersion,
|
setManagingVersion,
|
||||||
getVersionInfo,
|
|
||||||
getGameInfo,
|
|
||||||
getListOfGames,
|
|
||||||
setSelectedGame,
|
setSelectedGame,
|
||||||
getVersionsAmountData,
|
|
||||||
viewingInfoFromDownloads,
|
viewingInfoFromDownloads,
|
||||||
version,
|
version,
|
||||||
downloadVersions,
|
downloadVersions,
|
||||||
@@ -812,17 +743,22 @@ export default function RootLayout ({
|
|||||||
downloadQueue,
|
downloadQueue,
|
||||||
setDownloadQueue,
|
setDownloadQueue,
|
||||||
closePopup,
|
closePopup,
|
||||||
getSpecialVersionsList,
|
|
||||||
selectedGame,
|
selectedGame,
|
||||||
setViewingInfoFromDownloads,
|
setViewingInfoFromDownloads,
|
||||||
showModInfo,
|
showModInfo,
|
||||||
setShowModInfo,
|
setShowModInfo,
|
||||||
|
getSpecialVersionsList,
|
||||||
settings,
|
settings,
|
||||||
|
versions,
|
||||||
notificationsAllowed,
|
notificationsAllowed,
|
||||||
sidebarAlwaysShowGames,
|
sidebarAlwaysShowGames,
|
||||||
linuxUseWine,
|
linuxUseWine,
|
||||||
linuxWineCommand,
|
linuxWineCommand,
|
||||||
theme
|
customDataLocation,
|
||||||
|
versionsList,
|
||||||
|
modsList,
|
||||||
|
movingData,
|
||||||
|
setMovingData
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -867,7 +803,8 @@ export default function RootLayout ({
|
|||||||
selectedGame &&
|
selectedGame &&
|
||||||
pathname === '/') ||
|
pathname === '/') ||
|
||||||
viewingInfoFromDownloads ||
|
viewingInfoFromDownloads ||
|
||||||
(popupMode == 3 && showModInfo)
|
(popupMode == 3 && showModInfo) ||
|
||||||
|
popupMode == 4
|
||||||
? faChevronLeft
|
? faChevronLeft
|
||||||
: faXmark
|
: faXmark
|
||||||
}
|
}
|
||||||
@@ -883,10 +820,17 @@ export default function RootLayout ({
|
|||||||
<ManageVersionPopup />
|
<ManageVersionPopup />
|
||||||
) : popupMode === 3 ? (
|
) : popupMode === 3 ? (
|
||||||
<ModDownloadsPopup />
|
<ModDownloadsPopup />
|
||||||
|
) : popupMode === 4 ? (
|
||||||
|
<VersionChangelogPopup />
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
</GlobalProvider>
|
</GlobalProvider>
|
||||||
)}
|
)}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import './Installs.css'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
import { useGlobal } from '@/providers/GlobalProvider'
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
import {
|
||||||
|
faCheck,
|
||||||
|
faShieldHalved,
|
||||||
|
faWarning
|
||||||
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
|
import { useRouter } from 'next/navigation'
|
||||||
|
|
||||||
|
export default function Installs () {
|
||||||
|
const {
|
||||||
|
versionsList,
|
||||||
|
serverVersionList,
|
||||||
|
showPopup,
|
||||||
|
setShowPopup,
|
||||||
|
setPopupMode,
|
||||||
|
setFadeOut,
|
||||||
|
setSelectedVersionList,
|
||||||
|
setSelectedGame,
|
||||||
|
setCategory
|
||||||
|
} = useGlobal()
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!showPopup) return
|
||||||
|
setSelectedVersionList([])
|
||||||
|
}, [setSelectedVersionList, showPopup])
|
||||||
|
|
||||||
|
const filteredGames =
|
||||||
|
serverVersionList?.games.filter(g =>
|
||||||
|
serverVersionList.versions
|
||||||
|
.filter(v => v.game === g.id)
|
||||||
|
.some(v => Object.keys(versionsList).includes(v.id))
|
||||||
|
) ?? []
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mx-4 mt-4'>
|
||||||
|
<div className='flex justify-between items-center mb-4'>
|
||||||
|
<p className='text-3xl'>Games</p>
|
||||||
|
<button
|
||||||
|
className='button btntheme1'
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedGame(null)
|
||||||
|
setPopupMode(0)
|
||||||
|
setShowPopup(true)
|
||||||
|
setFadeOut(false)
|
||||||
|
}}
|
||||||
|
title='Click to download more games.'
|
||||||
|
>
|
||||||
|
Download game
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className='downloads-container'>
|
||||||
|
<div
|
||||||
|
className={`downloads-scroll ${
|
||||||
|
platform() == 'windows'
|
||||||
|
? 'h-[calc(100vh-116px)]'
|
||||||
|
: 'h-[calc(100vh-84px)]'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{filteredGames.length == 0 ? (
|
||||||
|
<div className='flex justify-center items-center h-full'>
|
||||||
|
<p className='text-3xl'>No games installed</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
filteredGames.map(i => (
|
||||||
|
<div
|
||||||
|
key={i.id}
|
||||||
|
className={'downloads-entry'}
|
||||||
|
title={'Click to view game installs'}
|
||||||
|
onClick={() => {
|
||||||
|
setCategory(-1)
|
||||||
|
router.push('/main/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 gameVersions = (
|
||||||
|
serverVersionList?.versions ?? []
|
||||||
|
).filter(v => v.game === i.id)
|
||||||
|
const installed = gameVersions.filter(v =>
|
||||||
|
Object.keys(versionsList).includes(v.id)
|
||||||
|
).length
|
||||||
|
return gameVersions.length
|
||||||
|
? `${installed}/${gameVersions.length}`
|
||||||
|
: 'N/A'
|
||||||
|
})()}{' '}
|
||||||
|
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.'
|
||||||
|
}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon={i.verified ? faShieldHalved : faWarning}
|
||||||
|
color={i.verified ? '#19c84b' : '#ffc800'}
|
||||||
|
/>
|
||||||
|
<p>{i.verified ? 'Verified' : 'Unverified'}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { Setting } from '@/components/Setting'
|
import { Setting } from '@/components/Setting'
|
||||||
import { useGlobal } from '@/app/GlobalProvider'
|
import { useGlobal } from '@/providers/GlobalProvider'
|
||||||
import { copyToClipboard } from '@/lib/Clipboard'
|
import { copyToClipboard } from '@/lib/clipboard'
|
||||||
import { platform } from '@tauri-apps/plugin-os'
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export default function Settings () {
|
export default function Settings () {
|
||||||
const {
|
const {
|
||||||
@@ -13,13 +15,15 @@ export default function Settings () {
|
|||||||
sidebarAlwaysShowGames,
|
sidebarAlwaysShowGames,
|
||||||
linuxUseWine,
|
linuxUseWine,
|
||||||
linuxWineCommand,
|
linuxWineCommand,
|
||||||
theme
|
customDataLocation,
|
||||||
|
downloadProgress,
|
||||||
|
setMovingData
|
||||||
} = useGlobal()
|
} = useGlobal()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p className='text-3xl ml-4 mt-4'>Settings</p>
|
<p className='text-3xl ml-4 mt-4'>Settings</p>
|
||||||
<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-(--col1)/50 border border-(--col3)/50 rounded-lg p-4 w-fit h-fit'>
|
||||||
<Setting
|
<Setting
|
||||||
label='Allow sending notifications'
|
label='Allow sending notifications'
|
||||||
value={notificationsAllowed}
|
value={notificationsAllowed}
|
||||||
@@ -51,28 +55,51 @@ export default function Settings () {
|
|||||||
<input
|
<input
|
||||||
type='text'
|
type='text'
|
||||||
value={linuxWineCommand}
|
value={linuxWineCommand}
|
||||||
onChange={async e => {
|
onChange={async e =>
|
||||||
await settings?.set('linuxWineCommand', e.target.value)
|
await settings?.set('linuxWineCommand', e.target.value)
|
||||||
}}
|
}
|
||||||
className={`input-field my-1 ${
|
className='input-field my-1'
|
||||||
platform() == 'linux' && linuxWineCommand ? '' : 'hidden'
|
hidden={!(platform() == 'linux' && linuxUseWine)}
|
||||||
}`}
|
|
||||||
></input>
|
></input>
|
||||||
<div title='The theme you want the launcher to use.'>
|
<Setting
|
||||||
<label className='text-lg'>Theme:</label>
|
label='Use custom data location'
|
||||||
<select
|
value={!!customDataLocation}
|
||||||
className='ml-2 bg-(--col2) border border-(--col4) rounded-md'
|
disabled={downloadProgress.length > 0}
|
||||||
value={theme}
|
onChange={async () => {
|
||||||
onChange={async e => {
|
if (customDataLocation) {
|
||||||
await settings?.set('theme', e.target.value)
|
try {
|
||||||
}}
|
setMovingData(true)
|
||||||
>
|
await invoke('move_game_data', { destination: '' })
|
||||||
<option value={'dark'}>Dark (default)</option>
|
await settings?.set('customDataLocation', '')
|
||||||
<option value={'red'}>Red</option>
|
await settings?.save()
|
||||||
<option value={'blue'}>Blue</option>
|
await invoke('restart_app')
|
||||||
<option value={'purple'}>Purple</option>
|
} catch {
|
||||||
</select>
|
setMovingData(false)
|
||||||
</div>
|
}
|
||||||
|
} 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>
|
</div>
|
||||||
<p
|
<p
|
||||||
className='fixed bottom-1.5 right-1.5 rounded-md cursor-pointer px-1 border z-100 transition-colors btntheme1'
|
className='fixed bottom-1.5 right-1.5 rounded-md cursor-pointer px-1 border z-100 transition-colors btntheme1'
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
'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 { platform } from '@tauri-apps/plugin-os'
|
|
||||||
import { useRouter } from 'next/navigation'
|
|
||||||
|
|
||||||
export default function Installs () {
|
|
||||||
const {
|
|
||||||
showPopup,
|
|
||||||
setShowPopup,
|
|
||||||
setPopupMode,
|
|
||||||
setFadeOut,
|
|
||||||
setSelectedVersionList,
|
|
||||||
downloadedVersionsConfig,
|
|
||||||
setSelectedGame,
|
|
||||||
getListOfGames,
|
|
||||||
getVersionsAmountData,
|
|
||||||
setCategory
|
|
||||||
} = useGlobal()
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!showPopup) return
|
|
||||||
setSelectedVersionList([])
|
|
||||||
}, [setSelectedVersionList, showPopup])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='mx-4 mt-4'>
|
|
||||||
<div className='flex justify-between items-center mb-4'>
|
|
||||||
<p className='text-3xl'>Games</p>
|
|
||||||
<button
|
|
||||||
className='button btntheme1'
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedGame(null)
|
|
||||||
setPopupMode(0)
|
|
||||||
setShowPopup(true)
|
|
||||||
setFadeOut(false)
|
|
||||||
}}
|
|
||||||
title='Click to download more games.'
|
|
||||||
>
|
|
||||||
Download game
|
|
||||||
</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.'
|
|
||||||
}
|
|
||||||
onClick={e => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon
|
|
||||||
icon={i.verified ? faShieldHalved : faWarning}
|
|
||||||
color={i.verified ? '#19c84b' : '#ffc800'}
|
|
||||||
/>
|
|
||||||
<p>{i.verified ? 'Verified' : 'Unverified'}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<div className='flex justify-center items-center h-full'>
|
|
||||||
<p className='text-3xl'>No games installed</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import { useState, useRef, useEffect } from 'react'
|
||||||
|
import '@/styles/dropdown.css'
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
import { faChevronDown } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
type Option = {
|
||||||
|
label: string
|
||||||
|
value: string | number
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
value: string | number
|
||||||
|
options: Option[]
|
||||||
|
onChange: (value: string | number) => void | Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Dropdown ({ value, options, onChange }: Props) {
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const ref = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
|
const selected = options.find(o => o.value === value)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleClick = (e: MouseEvent) => {
|
||||||
|
if (!ref.current?.contains(e.target as Node)) {
|
||||||
|
setOpen(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener('mousedown', handleClick)
|
||||||
|
return () => window.removeEventListener('mousedown', handleClick)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={ref} className='dropdown'>
|
||||||
|
<button className='dropdown-btn' onClick={() => setOpen(o => !o)}>
|
||||||
|
<span>{selected?.label ?? 'Select...'}</span>
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon={faChevronDown}
|
||||||
|
className={`dropdown-arrow ${open ? 'open' : ''}`}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<div className={`dropdown-menu ${open ? 'open' : ''}`}>
|
||||||
|
{options.map((option, i) => (
|
||||||
|
<div
|
||||||
|
key={option.value}
|
||||||
|
className={`dropdown-item ${
|
||||||
|
option.value === value ? 'active' : ''
|
||||||
|
}`}
|
||||||
|
style={{ ['--i']: i } as React.CSSProperties}
|
||||||
|
onClick={async () => {
|
||||||
|
await onChange(option.value)
|
||||||
|
setOpen(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{option.label}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import './Setting.css'
|
import '@/styles/setting.css'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import { faCheck } from '@fortawesome/free-solid-svg-icons'
|
import { faCheck } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { SettingProps } from '@/types/SettingProps'
|
import { SettingProps } from '@/types/SettingProps'
|
||||||
@@ -8,16 +8,18 @@ export function Setting ({
|
|||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
className,
|
className,
|
||||||
title
|
title,
|
||||||
|
disabled
|
||||||
}: SettingProps) {
|
}: SettingProps) {
|
||||||
return (
|
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>
|
<label className='text-white text-lg'>{label}</label>
|
||||||
<div className='setting-checkbox-wrapper'>
|
<div className='setting-checkbox-wrapper'>
|
||||||
<input
|
<input
|
||||||
type='checkbox'
|
type='checkbox'
|
||||||
className='setting-checkbox'
|
className='setting-checkbox'
|
||||||
checked={value}
|
checked={value}
|
||||||
|
disabled={disabled}
|
||||||
onChange={() => onChange(!value)}
|
onChange={() => onChange(!value)}
|
||||||
/>
|
/>
|
||||||
{value && <FontAwesomeIcon icon={faCheck} className='fa-check-icon' />}
|
{value && <FontAwesomeIcon icon={faCheck} className='fa-check-icon' />}
|
||||||
|
|||||||
+32
-27
@@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import './Sidebar.css'
|
import '@/styles/sidebar.css'
|
||||||
import Icon from '@/assets/Icon.png'
|
import Icon from '@/assets/Icon.png'
|
||||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
import { faDiscord } from '@fortawesome/free-brands-svg-icons'
|
import { faDiscord } from '@fortawesome/free-brands-svg-icons'
|
||||||
import { platform } from '@tauri-apps/plugin-os'
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
import { useGlobal } from '@/app/GlobalProvider'
|
import { useGlobal } from '@/providers/GlobalProvider'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
||||||
@@ -27,13 +27,12 @@ const lexend = Lexend({
|
|||||||
|
|
||||||
export default function Sidebar () {
|
export default function Sidebar () {
|
||||||
const {
|
const {
|
||||||
getListOfGames,
|
serverVersionList,
|
||||||
|
versionsList,
|
||||||
setShowPopup,
|
setShowPopup,
|
||||||
setPopupMode,
|
setPopupMode,
|
||||||
setFadeOut,
|
setFadeOut,
|
||||||
downloadProgress,
|
downloadProgress,
|
||||||
downloadedVersionsConfig,
|
|
||||||
getVersionInfo,
|
|
||||||
category,
|
category,
|
||||||
setCategory,
|
setCategory,
|
||||||
sidebarAlwaysShowGames,
|
sidebarAlwaysShowGames,
|
||||||
@@ -60,10 +59,11 @@ export default function Sidebar () {
|
|||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
className={`flex items-center h-10 w-60 ${
|
className={
|
||||||
|
'flex items-center h-10 w-60 ' +
|
||||||
(platform() == 'windows' ? 'pl-1 pt-1' : 'pl-2 pt-2') +
|
(platform() == 'windows' ? 'pl-1 pt-1' : 'pl-2 pt-2') +
|
||||||
(platform() == 'macos' ? ' mt-7' : '')
|
(platform() == 'macos' ? ' mt-7' : '')
|
||||||
}`}
|
}
|
||||||
onMouseDown={e => {
|
onMouseDown={e => {
|
||||||
if (platform() != 'macos') return
|
if (platform() != 'macos') return
|
||||||
if (e.buttons === 1) {
|
if (e.buttons === 1) {
|
||||||
@@ -83,37 +83,42 @@ export default function Sidebar () {
|
|||||||
<nav className='nav-links overflow-auto pt-2'>
|
<nav className='nav-links overflow-auto pt-2'>
|
||||||
<Link
|
<Link
|
||||||
draggable={false}
|
draggable={false}
|
||||||
href='/'
|
href='/main'
|
||||||
className={`link relative flex items-center ${
|
className={`link relative flex items-center ${
|
||||||
pathname === '/' || pathname.startsWith('/game') ? 'active' : ''
|
pathname === '/main' || pathname.startsWith('/main/game')
|
||||||
|
? 'active'
|
||||||
|
: ''
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faHexagonNodes} className='mr-2' /> Games
|
<FontAwesomeIcon icon={faHexagonNodes} className='mr-2' /> Games
|
||||||
</Link>
|
</Link>
|
||||||
{getListOfGames()
|
{serverVersionList?.games
|
||||||
.sort((a, b) => {
|
.filter(g =>
|
||||||
return a.id - b.id
|
serverVersionList.versions
|
||||||
})
|
.filter(v => v.game === g.id)
|
||||||
|
.some(v => Object.keys(versionsList).includes(v.id))
|
||||||
|
)
|
||||||
.map(i => (
|
.map(i => (
|
||||||
<React.Fragment key={i.id}>
|
<React.Fragment key={i.id}>
|
||||||
<div
|
<div
|
||||||
draggable={false}
|
draggable={false}
|
||||||
className={`link ${
|
className={`link ${
|
||||||
(pathname === '/game' &&
|
(pathname === '/main/game' &&
|
||||||
Number(params.get('id') || 0) == i.id) ||
|
Number(params.get('id') || 0) == i.id) ||
|
||||||
(i.id == 1 && pathname === '/game/berrydash/leaderboards')
|
(i.id == 1 &&
|
||||||
|
pathname === '/main/game/berrydash/leaderboards')
|
||||||
? 'active'
|
? 'active'
|
||||||
: ''
|
: ''
|
||||||
} ml-auto w-50 ${
|
} ml-auto w-50 ${
|
||||||
sidebarAlwaysShowGames ||
|
sidebarAlwaysShowGames ||
|
||||||
pathname === '/' ||
|
pathname === '/' ||
|
||||||
pathname.startsWith('/game')
|
pathname.startsWith('/main/game')
|
||||||
? ''
|
? ''
|
||||||
: 'hidden'
|
: 'hidden'
|
||||||
}`}
|
}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCategory(-1)
|
setCategory(-1)
|
||||||
router.push('/game?id=' + i.id)
|
router.push('/main/game?id=' + i.id)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='flex items-center'>
|
<div className='flex items-center'>
|
||||||
@@ -131,10 +136,10 @@ export default function Sidebar () {
|
|||||||
{Object.entries(i.categoryNames)
|
{Object.entries(i.categoryNames)
|
||||||
.sort(([a], [b]) => Number(b) - Number(a))
|
.sort(([a], [b]) => Number(b) - Number(a))
|
||||||
.filter(([key]) => {
|
.filter(([key]) => {
|
||||||
const count = Object.keys(
|
const count = Object.keys(versionsList).filter(v => {
|
||||||
downloadedVersionsConfig?.list ?? {}
|
const info = serverVersionList.versions.find(
|
||||||
).filter(v => {
|
vf => vf.id == v
|
||||||
const info = getVersionInfo(v)
|
)
|
||||||
if (!info) return false
|
if (!info) return false
|
||||||
|
|
||||||
if (platform() == 'linux' && info.wine && !linuxUseWine)
|
if (platform() == 'linux' && info.wine && !linuxUseWine)
|
||||||
@@ -150,23 +155,23 @@ export default function Sidebar () {
|
|||||||
key={`${i.id}-${key}`}
|
key={`${i.id}-${key}`}
|
||||||
draggable={false}
|
draggable={false}
|
||||||
className={`link ${
|
className={`link ${
|
||||||
((pathname === '/game' &&
|
((pathname === '/main/game' &&
|
||||||
Number(params.get('id') || 0) == i.id) ||
|
Number(params.get('id') || 0) == i.id) ||
|
||||||
(i.id == 1 &&
|
(i.id == 1 &&
|
||||||
pathname === '/game/berrydash/leaderboards')) &&
|
pathname === '/main/game/berrydash/leaderboards')) &&
|
||||||
category == Number(key)
|
category == Number(key)
|
||||||
? 'active'
|
? 'active'
|
||||||
: ''
|
: ''
|
||||||
} ml-auto w-47.5 ${
|
} ml-auto w-47.5 ${
|
||||||
sidebarAlwaysShowGames ||
|
sidebarAlwaysShowGames ||
|
||||||
pathname === '/' ||
|
pathname === '/' ||
|
||||||
pathname.startsWith('/game')
|
pathname.startsWith('/main/game')
|
||||||
? ''
|
? ''
|
||||||
: 'hidden'
|
: 'hidden'
|
||||||
}`}
|
}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCategory(Number(key))
|
setCategory(Number(key))
|
||||||
router.push('/game?id=' + i.id)
|
router.push('/main/game?id=' + i.id)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='flex items-center'>
|
<div className='flex items-center'>
|
||||||
@@ -179,8 +184,8 @@ export default function Sidebar () {
|
|||||||
))}
|
))}
|
||||||
<Link
|
<Link
|
||||||
draggable={false}
|
draggable={false}
|
||||||
href='/settings'
|
href='/main/settings'
|
||||||
className={`link ${pathname === '/settings' ? 'active' : ''}`}
|
className={`link ${pathname === '/main/settings' ? 'active' : ''}`}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faCog} className='mr-1' /> Settings
|
<FontAwesomeIcon icon={faCog} className='mr-1' /> Settings
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
import { app } from '@tauri-apps/api'
|
|
||||||
import {
|
|
||||||
BaseDirectory,
|
|
||||||
create,
|
|
||||||
exists,
|
|
||||||
mkdir,
|
|
||||||
readTextFile,
|
|
||||||
writeFile
|
|
||||||
} from '@tauri-apps/plugin-fs'
|
|
||||||
import { VersionsConfig } from '@/types/VersionsConfig'
|
|
||||||
|
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File renamed without changes.
@@ -1,5 +1,5 @@
|
|||||||
import { writeText } from '@tauri-apps/plugin-clipboard-manager'
|
import { writeText } from '@tauri-apps/plugin-clipboard-manager'
|
||||||
import { notifyUser } from './Notifications'
|
import { notifyUser } from './notifications'
|
||||||
|
|
||||||
export async function copyToClipboard (
|
export async function copyToClipboard (
|
||||||
text: string,
|
text: string,
|
||||||
File renamed without changes.
@@ -1,39 +1,15 @@
|
|||||||
import { message } from '@tauri-apps/plugin-dialog'
|
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'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export const openFolder = async (name: string) => {
|
export const openFolder = async (name: string) => {
|
||||||
const relativePath = await join('game', name)
|
try {
|
||||||
const basePath = await appLocalDataDir()
|
await invoke('open_game_folder', { version: name })
|
||||||
const absolutePath = await join(basePath, relativePath)
|
} catch (e) {
|
||||||
|
await message(String(e), {
|
||||||
const folderExists = await exists(relativePath, {
|
|
||||||
baseDir: BaseDirectory.AppLocalData
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!folderExists) {
|
|
||||||
await message(`Game folder "${absolutePath}" not found.`, {
|
|
||||||
title: 'Folder not found',
|
title: 'Folder not found',
|
||||||
kind: 'error'
|
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) => {
|
export const formatEtaSmart = (seconds: number) => {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useGlobal } from '@/app/GlobalProvider'
|
import { useGlobal } from '@/providers/GlobalProvider'
|
||||||
import prettyBytes from 'pretty-bytes'
|
import prettyBytes from 'pretty-bytes'
|
||||||
import ProgressBar from '../ProgressBar'
|
import ProgressBar from '@/components/ProgressBar'
|
||||||
import { formatEtaSmart } from '@/lib/Util'
|
import { formatEtaSmart } from '@/lib/util'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import {
|
import {
|
||||||
faCancel,
|
faCancel,
|
||||||
@@ -10,19 +10,20 @@ import {
|
|||||||
faTrash
|
faTrash
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { writeVersionsConfig } from '@/lib/BazookaManager'
|
import { notifyUser } from '@/lib/notifications'
|
||||||
import { notifyUser } from '@/lib/Notifications'
|
|
||||||
import { getCurrentWindow, UserAttentionType } from '@tauri-apps/api/window'
|
import { getCurrentWindow, UserAttentionType } from '@tauri-apps/api/window'
|
||||||
|
|
||||||
export default function DownloadsPopup () {
|
export default function DownloadsPopup () {
|
||||||
const {
|
const {
|
||||||
downloadProgress,
|
downloadProgress,
|
||||||
getVersionInfo,
|
|
||||||
setDownloadProgress,
|
setDownloadProgress,
|
||||||
downloadQueue,
|
downloadQueue,
|
||||||
setDownloadQueue,
|
setDownloadQueue,
|
||||||
setDownloadedVersionsConfig,
|
notificationsAllowed,
|
||||||
notificationsAllowed
|
versionsList,
|
||||||
|
modsList,
|
||||||
|
versions,
|
||||||
|
serverVersionList
|
||||||
} = useGlobal()
|
} = useGlobal()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -68,31 +69,19 @@ export default function DownloadsPopup () {
|
|||||||
prev.filter(d => d.version !== v.version)
|
prev.filter(d => d.version !== v.version)
|
||||||
)
|
)
|
||||||
if (v.type != 1) {
|
if (v.type != 1) {
|
||||||
setDownloadedVersionsConfig(prev => {
|
if (v.type == 2) {
|
||||||
if (!prev) return prev
|
versions?.set('mods', {
|
||||||
|
...modsList,
|
||||||
const updated =
|
[v.modGame! + '-' + v.modId!]: {
|
||||||
v.type == 2
|
[v.modVersion!]: Date.now()
|
||||||
? {
|
}
|
||||||
...prev,
|
})
|
||||||
mods: {
|
} else {
|
||||||
...prev.mods,
|
versions?.set('list', {
|
||||||
[v.modGame! + '-' + v.modId!]: {
|
...versionsList,
|
||||||
[v.modVersion!]: Date.now()
|
[v.version]: Date.now()
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
: {
|
|
||||||
...prev,
|
|
||||||
list: {
|
|
||||||
...prev.list,
|
|
||||||
[v.version]: Date.now()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writeVersionsConfig(updated)
|
|
||||||
return updated
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} else if (res == '0') {
|
} else if (res == '0') {
|
||||||
setDownloadProgress(prev => {
|
setDownloadProgress(prev => {
|
||||||
@@ -127,7 +116,9 @@ export default function DownloadsPopup () {
|
|||||||
await notifyUser(
|
await notifyUser(
|
||||||
'Download Failed',
|
'Download Failed',
|
||||||
`The download for version ${
|
`The download for version ${
|
||||||
getVersionInfo(v.version)?.displayName
|
serverVersionList?.versions.find(
|
||||||
|
vf => vf.id == v.version
|
||||||
|
)?.displayName
|
||||||
} has failed.`
|
} has failed.`
|
||||||
)
|
)
|
||||||
await getCurrentWindow().requestUserAttention(
|
await getCurrentWindow().requestUserAttention(
|
||||||
@@ -186,11 +177,14 @@ export default function DownloadsPopup () {
|
|||||||
</div>
|
</div>
|
||||||
<p className='text-2xl text-center'>
|
<p className='text-2xl text-center'>
|
||||||
{v.type == 1
|
{v.type == 1
|
||||||
? 'Mod Manager for '
|
? 'Mod loader for '
|
||||||
: v.type == 2
|
: v.type == 2
|
||||||
? 'Mod for '
|
? 'Mod for '
|
||||||
: null}{' '}
|
: null}{' '}
|
||||||
{getVersionInfo(v.version)?.displayName}
|
{
|
||||||
|
serverVersionList?.versions.find(vf => vf.id == v.version)
|
||||||
|
?.displayName
|
||||||
|
}
|
||||||
</p>
|
</p>
|
||||||
<div className='mt-6.25 flex items-center justify-between'>
|
<div className='mt-6.25 flex items-center justify-between'>
|
||||||
{v.failed || v.queued ? (
|
{v.failed || v.queued ? (
|
||||||
@@ -209,7 +203,7 @@ export default function DownloadsPopup () {
|
|||||||
</div>
|
</div>
|
||||||
) : v.hash_checking ? (
|
) : v.hash_checking ? (
|
||||||
<span className='text-blue-300 inline-block w-full text-center'>
|
<span className='text-blue-300 inline-block w-full text-center'>
|
||||||
Verifying file integerty...
|
Verifying file integrity...
|
||||||
</span>
|
</span>
|
||||||
) : v.unzipping ? (
|
) : v.unzipping ? (
|
||||||
<div className='flex flex-col gap-1 w-full'>
|
<div className='flex flex-col gap-1 w-full'>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useGlobal } from '@/app/GlobalProvider'
|
import { useGlobal } from '@/providers/GlobalProvider'
|
||||||
import {
|
import {
|
||||||
faCheck,
|
faCheck,
|
||||||
faCode,
|
faCode,
|
||||||
@@ -9,18 +9,18 @@ import {
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
|
||||||
export default function GamesDownloadPopup () {
|
export default function GamesDownloadPopup () {
|
||||||
const { serverVersionList, getVersionsAmountData, setSelectedGame } =
|
const { serverVersionList, setSelectedGame, versionsList } = useGlobal()
|
||||||
useGlobal()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p className='text-xl text-center'>Select a game to download</p>
|
<p className='text-xl text-center'>Select a game to download</p>
|
||||||
<div className='popup-content'>
|
<div className='popup-content'>
|
||||||
{serverVersionList?.games
|
{serverVersionList?.games
|
||||||
.filter(v => {
|
.filter(i => {
|
||||||
const data = getVersionsAmountData(v.id)
|
const gameVersions = serverVersionList.versions.filter(
|
||||||
if (!data) return false
|
vf => vf.game === i.id
|
||||||
if (data.total > 0) return true
|
)
|
||||||
|
if (gameVersions.length > 0) return true
|
||||||
})
|
})
|
||||||
.map((v, i) => (
|
.map((v, i) => (
|
||||||
<div key={i} className='popup-entry'>
|
<div key={i} className='popup-entry'>
|
||||||
@@ -32,9 +32,15 @@ export default function GamesDownloadPopup () {
|
|||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
{(() => {
|
{(() => {
|
||||||
const data = getVersionsAmountData(v.id)
|
const gameVersions = serverVersionList.versions.filter(
|
||||||
if (!data) return 'N/A'
|
vf => vf.game === v.id
|
||||||
return `${data.installed}/${data.total}`
|
)
|
||||||
|
const installed = gameVersions.filter(v =>
|
||||||
|
Object.keys(versionsList).includes(v.id)
|
||||||
|
).length
|
||||||
|
return gameVersions.length
|
||||||
|
? `${installed}/${gameVersions.length}`
|
||||||
|
: 'N/A'
|
||||||
})()}{' '}
|
})()}{' '}
|
||||||
versions installed
|
versions installed
|
||||||
</p>
|
</p>
|
||||||
@@ -74,11 +80,7 @@ export default function GamesDownloadPopup () {
|
|||||||
<button
|
<button
|
||||||
className='button btntheme3 right-2 bottom-2'
|
className='button btntheme3 right-2 bottom-2'
|
||||||
onClick={() => setSelectedGame(v.id)}
|
onClick={() => setSelectedGame(v.id)}
|
||||||
title={`Click to download specific versions of the game. You have ${(() => {
|
title='Click to download more versions of the game.'
|
||||||
const data = getVersionsAmountData(v.id)
|
|
||||||
if (!data) return 'N/A'
|
|
||||||
return `${data.installed} of ${data.total}`
|
|
||||||
})()} versions downloaded.`}
|
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
<FontAwesomeIcon icon={faDownload} /> Download
|
<FontAwesomeIcon icon={faDownload} /> Download
|
||||||
@@ -9,28 +9,25 @@ import {
|
|||||||
faWarning
|
faWarning
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import { useGlobal } from '@/app/GlobalProvider'
|
import { useGlobal } from '@/providers/GlobalProvider'
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import prettyBytes from 'pretty-bytes'
|
import prettyBytes from 'pretty-bytes'
|
||||||
import { message } from '@tauri-apps/plugin-dialog'
|
|
||||||
import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs'
|
import { BaseDirectory, exists, remove } from '@tauri-apps/plugin-fs'
|
||||||
import { writeVersionsConfig } from '@/lib/BazookaManager'
|
import { openFolder } from '@/lib/util'
|
||||||
import { openFolder } from '@/lib/Util'
|
|
||||||
|
|
||||||
export default function ManageVersionPopup () {
|
export default function ManageVersionPopup () {
|
||||||
const {
|
const {
|
||||||
getGameInfo,
|
versionsList,
|
||||||
getVersionInfo,
|
serverVersionList,
|
||||||
managingVersion,
|
managingVersion,
|
||||||
downloadedVersionsConfig,
|
|
||||||
viewingInfoFromDownloads,
|
viewingInfoFromDownloads,
|
||||||
setManagingVersion,
|
setManagingVersion,
|
||||||
closePopup,
|
closePopup,
|
||||||
setDownloadedVersionsConfig,
|
|
||||||
setPopupMode,
|
setPopupMode,
|
||||||
setSelectedVersionList,
|
setSelectedVersionList,
|
||||||
downloadVersions
|
downloadVersions,
|
||||||
|
versions
|
||||||
} = useGlobal()
|
} = useGlobal()
|
||||||
const [versionSize, setVersionSize] = useState<number>(0)
|
const [versionSize, setVersionSize] = useState<number>(0)
|
||||||
|
|
||||||
@@ -43,10 +40,14 @@ export default function ManageVersionPopup () {
|
|||||||
})
|
})
|
||||||
}, [managingVersion, setVersionSize, viewingInfoFromDownloads])
|
}, [managingVersion, setVersionSize, viewingInfoFromDownloads])
|
||||||
|
|
||||||
if (!managingVersion || !downloadedVersionsConfig) return <></>
|
if (!managingVersion) return <></>
|
||||||
|
|
||||||
const versionInfo = getVersionInfo(managingVersion)
|
const versionInfo = serverVersionList?.versions.find(
|
||||||
const gameInfo = getGameInfo(versionInfo?.game)
|
vf => vf.id == managingVersion
|
||||||
|
)
|
||||||
|
const gameInfo = serverVersionList?.games.find(
|
||||||
|
vf => vf.id == versionInfo?.game
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -59,7 +60,7 @@ export default function ManageVersionPopup () {
|
|||||||
<p>
|
<p>
|
||||||
Installed{' '}
|
Installed{' '}
|
||||||
{new Intl.DateTimeFormat(undefined).format(
|
{new Intl.DateTimeFormat(undefined).format(
|
||||||
downloadedVersionsConfig.list[managingVersion] ?? 0
|
versionsList[managingVersion] ?? 0
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -109,13 +110,7 @@ export default function ManageVersionPopup () {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className='entry-info-item btntheme2'
|
className='entry-info-item btntheme2'
|
||||||
onClick={async () => {
|
onClick={() => setPopupMode(4)}
|
||||||
if (!versionInfo) return
|
|
||||||
await message(atob(versionInfo.changelog), {
|
|
||||||
title: 'Changelog for ' + versionInfo.displayName,
|
|
||||||
kind: 'info'
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
hidden={!versionInfo?.changelog}
|
hidden={!versionInfo?.changelog}
|
||||||
>
|
>
|
||||||
<p>View Changelog</p>
|
<p>View Changelog</p>
|
||||||
@@ -135,18 +130,14 @@ export default function ManageVersionPopup () {
|
|||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
closePopup()
|
closePopup()
|
||||||
|
|
||||||
setDownloadedVersionsConfig(prev => {
|
versions?.set(
|
||||||
if (!prev) return prev
|
'list',
|
||||||
const updatedList = Object.fromEntries(
|
Object.fromEntries(
|
||||||
Object.entries(prev.list).filter(([k]) => k !== managingVersion)
|
Object.entries(versionsList).filter(
|
||||||
|
([k]) => k !== managingVersion
|
||||||
|
)
|
||||||
)
|
)
|
||||||
const updatedConfig = {
|
)
|
||||||
...prev,
|
|
||||||
list: updatedList
|
|
||||||
}
|
|
||||||
writeVersionsConfig(updatedConfig)
|
|
||||||
return updatedConfig
|
|
||||||
})
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
await exists('game/' + managingVersion, {
|
await exists('game/' + managingVersion, {
|
||||||
@@ -171,18 +162,14 @@ export default function ManageVersionPopup () {
|
|||||||
setPopupMode(1)
|
setPopupMode(1)
|
||||||
|
|
||||||
//uninstall
|
//uninstall
|
||||||
setDownloadedVersionsConfig(prev => {
|
versions?.set(
|
||||||
if (!prev) return prev
|
'list',
|
||||||
const updatedList = Object.fromEntries(
|
Object.fromEntries(
|
||||||
Object.entries(prev.list).filter(([k]) => k !== managingVersion)
|
Object.entries(versionsList).filter(
|
||||||
|
([k]) => k !== managingVersion
|
||||||
|
)
|
||||||
)
|
)
|
||||||
const updatedConfig = {
|
)
|
||||||
...prev,
|
|
||||||
list: updatedList
|
|
||||||
}
|
|
||||||
writeVersionsConfig(updatedConfig)
|
|
||||||
return updatedConfig
|
|
||||||
})
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
await exists('game/' + managingVersion, {
|
await exists('game/' + managingVersion, {
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useGlobal } from '@/app/GlobalProvider'
|
import { useGlobal } from '@/providers/GlobalProvider'
|
||||||
import { writeVersionsConfig } from '@/lib/BazookaManager'
|
import { verifySignature } from '@/lib/util'
|
||||||
import { verifySignature } from '@/lib/Util'
|
|
||||||
import { Mod } from '@/types/Mod'
|
import { Mod } from '@/types/Mod'
|
||||||
import {
|
import {
|
||||||
faArrowUpRightFromSquare,
|
faArrowUpRightFromSquare,
|
||||||
@@ -23,14 +22,14 @@ import { useEffect, useState } from 'react'
|
|||||||
|
|
||||||
export default function ModDownloadsPopup () {
|
export default function ModDownloadsPopup () {
|
||||||
const {
|
const {
|
||||||
getVersionInfo,
|
modsList,
|
||||||
|
serverVersionList,
|
||||||
managingVersion,
|
managingVersion,
|
||||||
downloadedVersionsConfig,
|
|
||||||
showModInfo,
|
showModInfo,
|
||||||
setShowModInfo,
|
setShowModInfo,
|
||||||
downloadVersions,
|
downloadVersions,
|
||||||
downloadProgress,
|
downloadProgress,
|
||||||
setDownloadedVersionsConfig
|
versions
|
||||||
} = useGlobal()
|
} = useGlobal()
|
||||||
|
|
||||||
const [mods, setMods] = useState<Mod[] | 0 | 1>(0)
|
const [mods, setMods] = useState<Mod[] | 0 | 1>(0)
|
||||||
@@ -52,9 +51,11 @@ export default function ModDownloadsPopup () {
|
|||||||
})()
|
})()
|
||||||
}, [managingVersion])
|
}, [managingVersion])
|
||||||
|
|
||||||
if (!managingVersion) return <></>
|
if (!managingVersion || !serverVersionList) return <></>
|
||||||
|
|
||||||
const versionInfo = getVersionInfo(managingVersion)
|
const versionInfo = serverVersionList.versions.find(
|
||||||
|
v => v.id == managingVersion
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -110,10 +111,10 @@ export default function ModDownloadsPopup () {
|
|||||||
(!showModInfo &&
|
(!showModInfo &&
|
||||||
mods.filter(v =>
|
mods.filter(v =>
|
||||||
tab == 0
|
tab == 0
|
||||||
? Object.keys(downloadedVersionsConfig?.mods ?? []).includes(
|
? Object.keys(modsList).includes(
|
||||||
String(versionInfo?.game + '-' + v.id)
|
String(versionInfo?.game + '-' + v.id)
|
||||||
)
|
)
|
||||||
: !Object.keys(downloadedVersionsConfig?.mods ?? []).includes(
|
: !Object.keys(modsList).includes(
|
||||||
String(versionInfo?.game + '-' + v.id)
|
String(versionInfo?.game + '-' + v.id)
|
||||||
)
|
)
|
||||||
).length == 0) ? (
|
).length == 0) ? (
|
||||||
@@ -131,10 +132,10 @@ export default function ModDownloadsPopup () {
|
|||||||
{mods
|
{mods
|
||||||
.filter(v =>
|
.filter(v =>
|
||||||
tab == 0
|
tab == 0
|
||||||
? Object.keys(downloadedVersionsConfig?.mods ?? []).includes(
|
? Object.keys(modsList).includes(
|
||||||
String(versionInfo?.game + '-' + v.id)
|
String(versionInfo?.game + '-' + v.id)
|
||||||
)
|
)
|
||||||
: !Object.keys(downloadedVersionsConfig?.mods ?? []).includes(
|
: !Object.keys(modsList).includes(
|
||||||
String(versionInfo?.game + '-' + v.id)
|
String(versionInfo?.game + '-' + v.id)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -142,9 +143,7 @@ export default function ModDownloadsPopup () {
|
|||||||
const localVersion =
|
const localVersion =
|
||||||
tab == 0
|
tab == 0
|
||||||
? Object.keys(
|
? Object.keys(
|
||||||
downloadedVersionsConfig?.mods?.[
|
modsList[versionInfo?.game + '-' + v.id] ?? {}
|
||||||
versionInfo?.game + '-' + v.id
|
|
||||||
] ?? {}
|
|
||||||
)[0]
|
)[0]
|
||||||
: null
|
: null
|
||||||
return (
|
return (
|
||||||
@@ -201,20 +200,14 @@ export default function ModDownloadsPopup () {
|
|||||||
baseDir: BaseDirectory.AppLocalData,
|
baseDir: BaseDirectory.AppLocalData,
|
||||||
recursive: true
|
recursive: true
|
||||||
})
|
})
|
||||||
setDownloadedVersionsConfig(prev => {
|
versions?.set(
|
||||||
if (!prev) return prev
|
'mods',
|
||||||
const updatedMods = Object.fromEntries(
|
Object.fromEntries(
|
||||||
Object.entries(prev.mods).filter(
|
Object.entries(modsList).filter(
|
||||||
([k]) => k !== versionInfo?.game + '-' + v.id
|
([k]) => k !== versionInfo?.game + '-' + v.id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
const updatedConfig = {
|
)
|
||||||
...prev,
|
|
||||||
mods: updatedMods
|
|
||||||
}
|
|
||||||
writeVersionsConfig(updatedConfig)
|
|
||||||
return updatedConfig
|
|
||||||
})
|
|
||||||
|
|
||||||
downloadVersions([
|
downloadVersions([
|
||||||
{
|
{
|
||||||
@@ -273,7 +266,7 @@ export default function ModDownloadsPopup () {
|
|||||||
: '(No description added)'}
|
: '(No description added)'}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-row h-fit w-full gap-2 justify-center my-2'>
|
<div className='flex flex-row h-fit w-full gap-2 justify-center my-2'>
|
||||||
{Object.keys(downloadedVersionsConfig?.mods ?? []).includes(
|
{Object.keys(modsList).includes(
|
||||||
String(versionInfo?.game + '-' + showModInfo.id)
|
String(versionInfo?.game + '-' + showModInfo.id)
|
||||||
) ? (
|
) ? (
|
||||||
<button
|
<button
|
||||||
@@ -294,21 +287,15 @@ export default function ModDownloadsPopup () {
|
|||||||
baseDir: BaseDirectory.AppLocalData,
|
baseDir: BaseDirectory.AppLocalData,
|
||||||
recursive: true
|
recursive: true
|
||||||
})
|
})
|
||||||
setDownloadedVersionsConfig(prev => {
|
versions?.set(
|
||||||
if (!prev) return prev
|
'mods',
|
||||||
const updatedMods = Object.fromEntries(
|
Object.fromEntries(
|
||||||
Object.entries(prev.mods).filter(
|
Object.entries(modsList).filter(
|
||||||
([k]) =>
|
([k]) =>
|
||||||
k !== versionInfo?.game + '-' + showModInfo.id
|
k !== versionInfo?.game + '-' + showModInfo.id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
const updatedConfig = {
|
)
|
||||||
...prev,
|
|
||||||
mods: updatedMods
|
|
||||||
}
|
|
||||||
writeVersionsConfig(updatedConfig)
|
|
||||||
return updatedConfig
|
|
||||||
})
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faTrash} className='text-red-400' />{' '}
|
<FontAwesomeIcon icon={faTrash} className='text-red-400' />{' '}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useGlobal } from '@/providers/GlobalProvider'
|
||||||
|
import DOMPurify from 'dompurify'
|
||||||
|
|
||||||
|
export default function VersionChangelogPopup () {
|
||||||
|
const { serverVersionList, managingVersion } = useGlobal()
|
||||||
|
|
||||||
|
if (!managingVersion) return <></>
|
||||||
|
|
||||||
|
const versionInfo = serverVersionList?.versions.find(
|
||||||
|
vf => vf.id == managingVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p className='text-xl text-center'>
|
||||||
|
Viewing changelog {versionInfo?.displayName}
|
||||||
|
</p>
|
||||||
|
<div className='popup-content h-full w-full p-2'>
|
||||||
|
<p
|
||||||
|
className='whitespace-pre-line'
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: DOMPurify.sanitize(
|
||||||
|
atob(versionInfo?.changelog ?? '')
|
||||||
|
.replace(/^- /gm, '• ')
|
||||||
|
.replaceAll(/`([^`]+)`/g, '<code>$1</code>')
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
></p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,22 +1,23 @@
|
|||||||
import { useGlobal } from '@/app/GlobalProvider'
|
import { useGlobal } from '@/providers/GlobalProvider'
|
||||||
import { faAdd, faInfo, faRemove } from '@fortawesome/free-solid-svg-icons'
|
import { faAdd, faInfo, faRemove } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
|
||||||
export default function VersionsDownloadPopup () {
|
export default function VersionsDownloadPopup () {
|
||||||
const {
|
const {
|
||||||
|
serverVersionList,
|
||||||
|
getSpecialVersionsList,
|
||||||
selectedVersionList,
|
selectedVersionList,
|
||||||
setSelectedVersionList,
|
setSelectedVersionList,
|
||||||
setManagingVersion,
|
setManagingVersion,
|
||||||
setPopupMode,
|
setPopupMode,
|
||||||
getSpecialVersionsList,
|
|
||||||
selectedGame,
|
selectedGame,
|
||||||
setViewingInfoFromDownloads,
|
setViewingInfoFromDownloads,
|
||||||
downloadedVersionsConfig,
|
downloadVersions
|
||||||
downloadVersions,
|
|
||||||
getGameInfo
|
|
||||||
} = useGlobal()
|
} = useGlobal()
|
||||||
|
|
||||||
if (!selectedGame) return <></>
|
const game = serverVersionList?.games.find(g => g.id === selectedGame)
|
||||||
|
|
||||||
|
if (!selectedGame || !game) return <></>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -78,24 +79,18 @@ export default function VersionsDownloadPopup () {
|
|||||||
<button
|
<button
|
||||||
className='button btntheme1 w-fit mt-2 -mb-4'
|
className='button btntheme1 w-fit mt-2 -mb-4'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (downloadedVersionsConfig) {
|
downloadVersions(
|
||||||
downloadVersions(
|
selectedVersionList.map(versionId => ({
|
||||||
selectedVersionList.map(versionId => ({
|
id: versionId,
|
||||||
id: versionId,
|
type: 0
|
||||||
type: 0
|
}))
|
||||||
}))
|
)
|
||||||
)
|
setPopupMode(1)
|
||||||
setPopupMode(1)
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
disabled={selectedVersionList.length == 0}
|
disabled={selectedVersionList.length == 0}
|
||||||
title={
|
title={`Download ${selectedVersionList.length} version${
|
||||||
selectedVersionList.length == 0
|
selectedVersionList.length == 1 ? '' : 's'
|
||||||
? 'Select at least one version to download'
|
} of ${game.name}`}
|
||||||
: `Download ${selectedVersionList.length} version${
|
|
||||||
selectedVersionList.length == 1 ? '' : 's'
|
|
||||||
} of ${getGameInfo(selectedGame)?.name}`
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
Download {selectedVersionList.length} version
|
Download {selectedVersionList.length} version
|
||||||
{selectedVersionList.length == 1 ? '' : 's'}
|
{selectedVersionList.length == 1 ? '' : 's'}
|
||||||
@@ -8,12 +8,10 @@ import {
|
|||||||
SetStateAction
|
SetStateAction
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import { DownloadProgress } from '@/types/DownloadProgress'
|
import { DownloadProgress } from '@/types/DownloadProgress'
|
||||||
import { VersionsConfig } from '@/types/VersionsConfig'
|
|
||||||
import { ServerVersionsResponse } from '@/types/ServerVersionsResponse'
|
import { ServerVersionsResponse } from '@/types/ServerVersionsResponse'
|
||||||
import { GameVersion } from '@/types/GameVersion'
|
|
||||||
import { Game } from '@/types/Game'
|
|
||||||
import { Mod } from '@/types/Mod'
|
import { Mod } from '@/types/Mod'
|
||||||
import { Store } from '@tauri-apps/plugin-store'
|
import { Store } from '@tauri-apps/plugin-store'
|
||||||
|
import { GameVersion } from '@/types/GameVersion'
|
||||||
|
|
||||||
type GlobalCtxType = {
|
type GlobalCtxType = {
|
||||||
serverVersionList: ServerVersionsResponse | null
|
serverVersionList: ServerVersionsResponse | null
|
||||||
@@ -27,18 +25,9 @@ type GlobalCtxType = {
|
|||||||
setPopupMode: Dispatch<SetStateAction<number | null>>
|
setPopupMode: Dispatch<SetStateAction<number | null>>
|
||||||
fadeOut: boolean
|
fadeOut: boolean
|
||||||
setFadeOut: Dispatch<SetStateAction<boolean>>
|
setFadeOut: Dispatch<SetStateAction<boolean>>
|
||||||
downloadedVersionsConfig: VersionsConfig | null
|
|
||||||
setDownloadedVersionsConfig: Dispatch<SetStateAction<VersionsConfig | null>>
|
|
||||||
managingVersion: string | null
|
managingVersion: string | null
|
||||||
setManagingVersion: Dispatch<SetStateAction<string | null>>
|
setManagingVersion: Dispatch<SetStateAction<string | null>>
|
||||||
setSelectedGame: Dispatch<SetStateAction<number | 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
|
viewingInfoFromDownloads: boolean
|
||||||
version: string | null
|
version: string | null
|
||||||
downloadVersions: (
|
downloadVersions: (
|
||||||
@@ -56,17 +45,22 @@ type GlobalCtxType = {
|
|||||||
downloadQueue: string[]
|
downloadQueue: string[]
|
||||||
setDownloadQueue: Dispatch<SetStateAction<string[]>>
|
setDownloadQueue: Dispatch<SetStateAction<string[]>>
|
||||||
closePopup: () => void
|
closePopup: () => void
|
||||||
getSpecialVersionsList(game?: number | undefined): GameVersion[]
|
|
||||||
selectedGame: number | null
|
selectedGame: number | null
|
||||||
setViewingInfoFromDownloads: Dispatch<SetStateAction<boolean>>
|
setViewingInfoFromDownloads: Dispatch<SetStateAction<boolean>>
|
||||||
showModInfo: Mod | null
|
showModInfo: Mod | null
|
||||||
setShowModInfo: Dispatch<SetStateAction<Mod | null>>
|
setShowModInfo: Dispatch<SetStateAction<Mod | null>>
|
||||||
|
getSpecialVersionsList: (game?: number) => GameVersion[]
|
||||||
settings: Store | null
|
settings: Store | null
|
||||||
|
versions: Store | null
|
||||||
notificationsAllowed: boolean
|
notificationsAllowed: boolean
|
||||||
sidebarAlwaysShowGames: boolean
|
sidebarAlwaysShowGames: boolean
|
||||||
linuxUseWine: boolean
|
linuxUseWine: boolean
|
||||||
linuxWineCommand: string
|
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)
|
const GlobalCtx = createContext<GlobalCtxType | null>(null)
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
.dropdown {
|
||||||
|
@apply relative w-40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-btn {
|
||||||
|
@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-3 h-3 transition-transform stroke-current stroke-2 fill-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-arrow.open {
|
||||||
|
@apply rotate-180;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
@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
|
||||||
|
transition-[opacity,transform] duration-150 ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu.open {
|
||||||
|
@apply opacity-100 scale-100 translate-y-0 pointer-events-auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
@apply px-2 py-1 cursor-pointer text-white transition-colors border-b border-(--col4) last:border-b-0;
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item:hover,
|
||||||
|
.dropdown-item.active {
|
||||||
|
@apply bg-(--col3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu.open .dropdown-item {
|
||||||
|
animation: dropIn 220ms ease-out forwards;
|
||||||
|
animation-delay: calc(var(--i) * 40ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes dropIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
html {
|
||||||
|
overscroll-behavior: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
@apply bg-transparent text-white select-none;
|
||||||
|
|
||||||
|
--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);
|
||||||
|
--col9: rgb(144, 144, 144);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
@apply rounded-md cursor-pointer text-[16px] py-1 px-2 transition-colors border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btntheme1 {
|
||||||
|
@apply bg-(--col2)/50 border-(--col4)/50 hover:bg-(--col4)/50 hover:border-(--col6)/50 disabled:text-gray-300 disabled:bg-(--col1)/50 disabled:border-(--col5)/50 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)/50 border-(--col5)/50 hover:bg-(--col5)/50 hover:border-(--col7)/50 disabled:text-gray-300 disabled:bg-(--col2)/50 disabled:border-(--col6)/50 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)/50 border-(--col6)/50 hover:bg-(--col6)/50 hover:border-(--col8)/50 disabled:text-gray-300 disabled:bg-(--col2)/50 disabled:border-(--col7)/50 disabled:hover:text-gray-100 disabled:hover:bg-(--col4) disabled:hover:border-(--col8);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
@apply w-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
@apply bg-(--col2) rounded-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
@apply bg-(--col4) w-1 rounded-lg active:bg-(--col5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeOut {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.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)];
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-overlay.fade-out {
|
||||||
|
@apply animate-[fadeOut_0.2s_ease-out_forwards];
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-box {
|
||||||
|
@apply relative w-150 h-120 rounded-lg bg-(--col1)/50 border border-(--col3)/50 flex flex-col p-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-content {
|
||||||
|
@apply flex-1 overflow-auto bg-(--col2)/50 border border-(--col4)/50 rounded-lg mt-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-entry {
|
||||||
|
@apply relative h-fit bg-(--col3)/50 m-2 p-2 rounded-lg border border-(--col5)/50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-entry button {
|
||||||
|
@apply absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-top-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 top-2 transition-colors border;
|
||||||
|
}
|
||||||
|
|
||||||
|
*:focus {
|
||||||
|
@apply outline-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-field {
|
||||||
|
@apply border-2 border-(--col4)/50 rounded-md bg-(--col2)/50 py-1 px-2 focus:bg-(--col3)/50 focus:border-(--col6)/50 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
@apply bg-(--col4) border border-(--col6) rounded-lg px-1 py-0.5 text-sm;
|
||||||
|
}
|
||||||
@@ -5,11 +5,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.setting-checkbox {
|
.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-(--col4)/50 rounded-md bg-(--col2)/50 transition-colors cursor-pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-checkbox:checked {
|
.setting-checkbox:checked {
|
||||||
@apply bg-(--col4) border-(--col6);
|
@apply bg-(--col4)/50 border-(--col6)/50;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fa-check-icon {
|
.fa-check-icon {
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
@apply fixed top-0 left-0 w-60 h-screen bg-(--col1) flex flex-col border-e border-(--col2) z-1;
|
@apply fixed top-0 left-0 w-60 h-screen bg-(--col1)/50 flex flex-col border-e border-(--col2)/50 z-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-downloads {
|
.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;
|
@apply text-[#bdbdbd] fixed bottom-2 left-2 bg-(--col2)/50 rounded-lg border border-(--col3)/50 px-4 py-3 text-xl cursor-pointer transition-colors duration-[0.25s] opacity-75;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-downloads:hover {
|
.sidebar-downloads:hover {
|
||||||
@apply text-white opacity-100;
|
@apply text-white opacity-100;
|
||||||
@apply bg-(--col3) border-(--col4);
|
@apply bg-(--col3)/50 border-(--col4)/50;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-links {
|
.nav-links {
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.link.active {
|
.link.active {
|
||||||
@apply bg-(--col2) border-(--col3);
|
@apply bg-(--col2)/50 border-(--col3)/50;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link.active,
|
.link.active,
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.link.active:hover {
|
.link.active:hover {
|
||||||
@apply bg-(--col3) border-(--col4);
|
@apply bg-(--col3)/50 border-(--col4)/50;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar ::-webkit-scrollbar {
|
.sidebar ::-webkit-scrollbar {
|
||||||
@@ -4,4 +4,5 @@ export type SettingProps = {
|
|||||||
onChange: (val: boolean) => void
|
onChange: (val: boolean) => void
|
||||||
className?: string
|
className?: string
|
||||||
title?: string
|
title?: string
|
||||||
|
disabled?: boolean
|
||||||
}
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
export type VersionsConfigData = {
|
|
||||||
version: string
|
|
||||||
list: Record<string, number>
|
|
||||||
mods: Record<string, Record<string, number>>
|
|
||||||
}
|
|
||||||
|
|
||||||
export class VersionsConfig {
|
|
||||||
constructor (
|
|
||||||
public version: string,
|
|
||||||
public list: Record<string, number> = {},
|
|
||||||
public mods: Record<string, Record<string, number>> = {}
|
|
||||||
) {}
|
|
||||||
|
|
||||||
static import (data: VersionsConfigData) {
|
|
||||||
const cfg = new VersionsConfig(data.version)
|
|
||||||
cfg.list = { ...data.list }
|
|
||||||
cfg.mods = { ...data.mods }
|
|
||||||
return cfg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user