chore: add custom cursor, add config system
This commit is contained in:
parent
60e3102257
commit
807ad60d62
16
bun.lock
16
bun.lock
@ -13,6 +13,9 @@
|
|||||||
"@tauri-apps/plugin-shell": "2.3.0",
|
"@tauri-apps/plugin-shell": "2.3.0",
|
||||||
"@tauri-apps/plugin-sql": "2.3.0",
|
"@tauri-apps/plugin-sql": "2.3.0",
|
||||||
"animejs": "^4.0.2",
|
"animejs": "^4.0.2",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
|
"crypto": "^1.0.1",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"ky": "1.8.1",
|
"ky": "1.8.1",
|
||||||
"lucide-svelte": "0.523.0",
|
"lucide-svelte": "0.523.0",
|
||||||
"osu-classes": "3.1.0",
|
"osu-classes": "3.1.0",
|
||||||
@ -25,6 +28,7 @@
|
|||||||
"@sveltejs/kit": "2.22.2",
|
"@sveltejs/kit": "2.22.2",
|
||||||
"@sveltejs/vite-plugin-svelte": "5.1.0",
|
"@sveltejs/vite-plugin-svelte": "5.1.0",
|
||||||
"@tauri-apps/cli": "2.6.1",
|
"@tauri-apps/cli": "2.6.1",
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
"autoprefixer": "10.4.21",
|
"autoprefixer": "10.4.21",
|
||||||
"bits-ui": "^1.4.7",
|
"bits-ui": "^1.4.7",
|
||||||
"clsx": "2.1.1",
|
"clsx": "2.1.1",
|
||||||
@ -227,6 +231,8 @@
|
|||||||
|
|
||||||
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
||||||
|
|
||||||
|
"@types/crypto-js": ["@types/crypto-js@4.2.2", "", {}, "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ=="],
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@20.19.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA=="],
|
"@types/node": ["@types/node@20.19.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA=="],
|
||||||
@ -253,6 +259,8 @@
|
|||||||
|
|
||||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||||
|
|
||||||
|
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||||
|
|
||||||
"binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
|
"binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
|
||||||
|
|
||||||
"bits-ui": ["bits-ui@1.8.0", "", { "dependencies": { "@floating-ui/core": "^1.6.4", "@floating-ui/dom": "^1.6.7", "@internationalized/date": "^3.5.6", "css.escape": "^1.5.1", "esm-env": "^1.1.2", "runed": "^0.23.2", "svelte-toolbelt": "^0.7.1", "tabbable": "^6.2.0" }, "peerDependencies": { "svelte": "^5.11.0" } }, "sha512-CXD6Orp7l8QevNDcRPLXc/b8iMVgxDWT2LyTwsdLzJKh9CxesOmPuNePSPqAxKoT59FIdU4aFPS1k7eBdbaCxg=="],
|
"bits-ui": ["bits-ui@1.8.0", "", { "dependencies": { "@floating-ui/core": "^1.6.4", "@floating-ui/dom": "^1.6.7", "@internationalized/date": "^3.5.6", "css.escape": "^1.5.1", "esm-env": "^1.1.2", "runed": "^0.23.2", "svelte-toolbelt": "^0.7.1", "tabbable": "^6.2.0" }, "peerDependencies": { "svelte": "^5.11.0" } }, "sha512-CXD6Orp7l8QevNDcRPLXc/b8iMVgxDWT2LyTwsdLzJKh9CxesOmPuNePSPqAxKoT59FIdU4aFPS1k7eBdbaCxg=="],
|
||||||
@ -263,6 +271,8 @@
|
|||||||
|
|
||||||
"browserslist": ["browserslist@4.25.1", "", { "dependencies": { "caniuse-lite": "^1.0.30001726", "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw=="],
|
"browserslist": ["browserslist@4.25.1", "", { "dependencies": { "caniuse-lite": "^1.0.30001726", "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw=="],
|
||||||
|
|
||||||
|
"buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
|
||||||
|
|
||||||
"buffer-builder": ["buffer-builder@0.2.0", "", {}, "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg=="],
|
"buffer-builder": ["buffer-builder@0.2.0", "", {}, "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg=="],
|
||||||
|
|
||||||
"camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
|
"camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
|
||||||
@ -285,6 +295,10 @@
|
|||||||
|
|
||||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
|
"crypto": ["crypto@1.0.1", "", {}, "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig=="],
|
||||||
|
|
||||||
|
"crypto-js": ["crypto-js@4.2.0", "", {}, "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="],
|
||||||
|
|
||||||
"css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="],
|
"css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="],
|
||||||
|
|
||||||
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
||||||
@ -337,6 +351,8 @@
|
|||||||
|
|
||||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||||
|
|
||||||
|
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||||
|
|
||||||
"immutable": ["immutable@5.1.3", "", {}, "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg=="],
|
"immutable": ["immutable@5.1.3", "", {}, "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg=="],
|
||||||
|
|
||||||
"inline-style-parser": ["inline-style-parser@0.2.4", "", {}, "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q=="],
|
"inline-style-parser": ["inline-style-parser@0.2.4", "", {}, "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q=="],
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
"@tauri-apps/plugin-shell": "2.3.0",
|
"@tauri-apps/plugin-shell": "2.3.0",
|
||||||
"@tauri-apps/plugin-sql": "2.3.0",
|
"@tauri-apps/plugin-sql": "2.3.0",
|
||||||
"animejs": "^4.0.2",
|
"animejs": "^4.0.2",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
|
"crypto": "^1.0.1",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"ky": "1.8.1",
|
"ky": "1.8.1",
|
||||||
"lucide-svelte": "0.523.0",
|
"lucide-svelte": "0.523.0",
|
||||||
"osu-classes": "3.1.0",
|
"osu-classes": "3.1.0",
|
||||||
@ -37,6 +40,7 @@
|
|||||||
"@sveltejs/kit": "2.22.2",
|
"@sveltejs/kit": "2.22.2",
|
||||||
"@sveltejs/vite-plugin-svelte": "5.1.0",
|
"@sveltejs/vite-plugin-svelte": "5.1.0",
|
||||||
"@tauri-apps/cli": "2.6.1",
|
"@tauri-apps/cli": "2.6.1",
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
"autoprefixer": "10.4.21",
|
"autoprefixer": "10.4.21",
|
||||||
"bits-ui": "^1.4.7",
|
"bits-ui": "^1.4.7",
|
||||||
"clsx": "2.1.1",
|
"clsx": "2.1.1",
|
||||||
|
24
src-tauri/Cargo.lock
generated
24
src-tauri/Cargo.lock
generated
@ -836,7 +836,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users",
|
"redox_users",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -966,7 +966,7 @@ dependencies = [
|
|||||||
"rustc_version",
|
"rustc_version",
|
||||||
"toml",
|
"toml",
|
||||||
"vswhom",
|
"vswhom",
|
||||||
"winreg",
|
"winreg 0.55.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1073,6 +1073,7 @@ dependencies = [
|
|||||||
name = "ezpplauncher"
|
name = "ezpplauncher"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"hardware-id",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
@ -1586,6 +1587,16 @@ dependencies = [
|
|||||||
"syn 2.0.90",
|
"syn 2.0.90",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hardware-id"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3165b5280ce11f886e353961b966becc45a598a9440707dec3e1cdd8f07cbe7"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
"winreg 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@ -5809,6 +5820,15 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winreg"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winreg"
|
name = "winreg"
|
||||||
version = "0.55.0"
|
version = "0.55.0"
|
||||||
|
@ -26,6 +26,7 @@ serde_repr = "0.1.20"
|
|||||||
tauri-plugin-sql = "2.3.0"
|
tauri-plugin-sql = "2.3.0"
|
||||||
tauri-plugin-dialog = "2.3.0"
|
tauri-plugin-dialog = "2.3.0"
|
||||||
tauri-plugin-fs = "2.4.0"
|
tauri-plugin-fs = "2.4.0"
|
||||||
|
hardware-id = "0.3.0"
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
tauri-plugin-single-instance = "2.3.0"
|
tauri-plugin-single-instance = "2.3.0"
|
||||||
|
@ -14,6 +14,62 @@
|
|||||||
"core:window:allow-start-dragging",
|
"core:window:allow-start-dragging",
|
||||||
"core:window:allow-minimize",
|
"core:window:allow-minimize",
|
||||||
"core:window:allow-close",
|
"core:window:allow-close",
|
||||||
"fs:default"
|
"fs:default",
|
||||||
|
{
|
||||||
|
"identifier": "fs:allow-write",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "$HOME/**/*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "fs:allow-read",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "$HOME/**/*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "fs:allow-exists",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "$HOME/**/*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "fs:allow-write-file",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "$HOME/**/*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "fs:allow-read-file",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "$HOME/**/*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "fs:allow-read-text-file",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "$HOME/**/*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "fs:allow-mkdir",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "$HOME/**/*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,6 +1,13 @@
|
|||||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||||
|
use hardware_id::get_id;
|
||||||
use tauri::Manager;
|
use tauri::Manager;
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
fn get_hwid() -> String {
|
||||||
|
let hwid = get_id().unwrap();
|
||||||
|
hwid.into()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
let mut builder = tauri::Builder::default().plugin(tauri_plugin_fs::init());
|
let mut builder = tauri::Builder::default().plugin(tauri_plugin_fs::init());
|
||||||
@ -16,9 +23,10 @@ pub fn run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
builder
|
builder
|
||||||
|
.invoke_handler(tauri::generate_handler![get_hwid])
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
.plugin(tauri_plugin_sql::Builder::default().build())
|
.plugin(tauri_plugin_sql::Builder::default().build())
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
import { animate } from 'animejs';
|
import { animate } from 'animejs';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
let { smoothCursor = true }: { smoothCursor?: boolean } =
|
||||||
|
$props();
|
||||||
|
|
||||||
let mouseX = $state(0);
|
let mouseX = $state(0);
|
||||||
let mouseY = $state(0);
|
let mouseY = $state(0);
|
||||||
let rotation = $state(0);
|
let rotation = $state(0);
|
||||||
@ -75,7 +78,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
animate(cursor, {
|
animate(cursor, {
|
||||||
duration: 180,
|
duration: smoothCursor ? 180 : 0,
|
||||||
translateX: mouseX,
|
translateX: mouseX,
|
||||||
translateY: mouseY - 50,
|
translateY: mouseY - 50,
|
||||||
ease: (t: number) => (t - 1) ** 3 + 1,
|
ease: (t: number) => (t - 1) ** 3 + 1,
|
||||||
@ -128,19 +131,12 @@
|
|||||||
let cursorInner: HTMLDivElement;
|
let cursorInner: HTMLDivElement;
|
||||||
let cursorAdditive: HTMLImageElement;
|
let cursorAdditive: HTMLImageElement;
|
||||||
|
|
||||||
/* onMount(() => {
|
onMount(() => {
|
||||||
const processMouseMove = (e: MouseEvent) =>
|
document.documentElement.classList.add('hiddenCursor');
|
||||||
handleMouseMove(e.clientX, e.clientY, e.pageX, e.pageY);
|
|
||||||
document.addEventListener('pointermove', processMouseMove);
|
|
||||||
document.addEventListener('pointerdown', handleMouseDown);
|
|
||||||
document.addEventListener('pointerup', handleMouseUp);
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('pointermove', processMouseMove);
|
document.documentElement.classList.remove('hiddenCursor');
|
||||||
document.removeEventListener('pointerdown', handleMouseDown);
|
|
||||||
document.removeEventListener('pointerup', handleMouseUp);
|
|
||||||
};
|
};
|
||||||
}); */
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window
|
<svelte:window
|
||||||
@ -148,8 +144,10 @@
|
|||||||
onmousedown={handleMouseDown}
|
onmousedown={handleMouseDown}
|
||||||
onmouseup={handleMouseUp}
|
onmouseup={handleMouseUp}
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
<div class="h-7 w-7 fixed pointer-events-none z-[99999]" bind:this={cursor}>
|
class="h-7 w-7 fixed pointer-events-none z-[99999]"
|
||||||
|
bind:this={cursor}
|
||||||
|
>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<img class="absolute top-0 left-0" src={cursor_default} bind:this={cursorInner} alt="cursor" />
|
<img class="absolute top-0 left-0" src={cursor_default} bind:this={cursorInner} alt="cursor" />
|
||||||
<img
|
<img
|
||||||
@ -162,15 +160,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:global(html),
|
:global(html.hiddenCursor),
|
||||||
:global(body),
|
:global(html.hiddenCursor body),
|
||||||
:global(*),
|
:global(html.hiddenCursor *),
|
||||||
:global(*:hover),
|
:global(html.hiddenCursor *:hover),
|
||||||
:global(button),
|
:global(html.hiddenCursor button),
|
||||||
:global(a),
|
:global(html.hiddenCursor a),
|
||||||
:global(input),
|
:global(html.hiddenCursor input),
|
||||||
:global(select),
|
:global(html.hiddenCursor select),
|
||||||
:global(textarea) {
|
:global(html.hiddenCursor textarea) {
|
||||||
cursor: none !important;
|
cursor: none !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
77
src/lib/config.ts
Normal file
77
src/lib/config.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import {
|
||||||
|
BaseDirectory,
|
||||||
|
exists,
|
||||||
|
mkdir,
|
||||||
|
readFile,
|
||||||
|
readTextFile,
|
||||||
|
writeFile,
|
||||||
|
} from '@tauri-apps/plugin-fs';
|
||||||
|
import * as path from '@tauri-apps/api/path';
|
||||||
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
|
import { Crypto } from './crypto';
|
||||||
|
import { enc } from 'crypto-js';
|
||||||
|
|
||||||
|
export class Config {
|
||||||
|
private config: Record<string, unknown> = {};
|
||||||
|
private crypto: Crypto | undefined;
|
||||||
|
private configFilePath: string | undefined;
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
const hwid: string = (await invoke('get_hwid')) ?? 'recorderinsandybridge';
|
||||||
|
|
||||||
|
this.crypto = new Crypto(hwid);
|
||||||
|
|
||||||
|
const homeDir = await path.homeDir();
|
||||||
|
const folderPath = await path.join(homeDir, '.ezpplauncher');
|
||||||
|
this.configFilePath = await path.join(folderPath, 'user_settings');
|
||||||
|
|
||||||
|
const createFolder = !(await exists(folderPath));
|
||||||
|
if (createFolder) await mkdir(folderPath);
|
||||||
|
|
||||||
|
const createConfig = !(await exists(this.configFilePath));
|
||||||
|
if (createConfig) await this.save();
|
||||||
|
else await this.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async load() {
|
||||||
|
if (!this.configFilePath) throw Error('configFilePath not set');
|
||||||
|
if (!this.crypto) throw Error('crypto not initialized');
|
||||||
|
|
||||||
|
const fileStream = await readTextFile(this.configFilePath);
|
||||||
|
try {
|
||||||
|
const decryptedJSON = JSON.parse(this.crypto.decrypt(fileStream)) as Record<string, unknown>;
|
||||||
|
this.config = decryptedJSON;
|
||||||
|
console.log('config file loaded');
|
||||||
|
console.log(JSON.stringify(this.config));
|
||||||
|
} catch (err) {
|
||||||
|
console.log('failed to read file');
|
||||||
|
this.config = {};
|
||||||
|
await this.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async save() {
|
||||||
|
if (!this.configFilePath) throw Error('configFilePath not set');
|
||||||
|
if (!this.crypto) throw Error('crypto not initialized');
|
||||||
|
const encryptedJSON = this.crypto.encrypt(JSON.stringify(this.config));
|
||||||
|
|
||||||
|
console.log(this.config);
|
||||||
|
console.log('saving file...');
|
||||||
|
console.log(encryptedJSON);
|
||||||
|
await writeFile(this.configFilePath, Buffer.from(encryptedJSON), {
|
||||||
|
append: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
value(key: string) {
|
||||||
|
console.log(this.config);
|
||||||
|
return {
|
||||||
|
set: <T>(val: T) => {
|
||||||
|
this.config[key] = val;
|
||||||
|
},
|
||||||
|
get: <T>(fallback: T): T => {
|
||||||
|
return (this.config[key] as T) ?? fallback;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
37
src/lib/crypto.ts
Normal file
37
src/lib/crypto.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import cryptojs from 'crypto-js';
|
||||||
|
|
||||||
|
export class Crypto {
|
||||||
|
private key: cryptojs.lib.WordArray;
|
||||||
|
private ivLength: number;
|
||||||
|
|
||||||
|
constructor(key: string, opts?: { ivLength?: number }) {
|
||||||
|
this.key = cryptojs.SHA256(key);
|
||||||
|
this.ivLength = opts?.ivLength ?? 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypt(str: string): string {
|
||||||
|
const iv = cryptojs.lib.WordArray.random(this.ivLength);
|
||||||
|
const encrypted = cryptojs.AES.encrypt(str, this.key, { iv });
|
||||||
|
|
||||||
|
const ivBase64 = iv.toString(cryptojs.enc.Base64);
|
||||||
|
const ctBase64 = encrypted.ciphertext.toString(cryptojs.enc.Base64);
|
||||||
|
|
||||||
|
return `${ivBase64}:${ctBase64}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
decrypt(data: string): string {
|
||||||
|
const [ivBase64, ctBase64] = data.split(':');
|
||||||
|
|
||||||
|
if (!ivBase64 || !ctBase64) throw new Error('Invalid input format');
|
||||||
|
|
||||||
|
const iv = cryptojs.enc.Base64.parse(ivBase64);
|
||||||
|
const ciphertext = cryptojs.enc.Base64.parse(ctBase64);
|
||||||
|
|
||||||
|
const cipherParams = cryptojs.lib.CipherParams.create({
|
||||||
|
ciphertext,
|
||||||
|
});
|
||||||
|
|
||||||
|
const decrypted = cryptojs.AES.decrypt(cipherParams, this.key, { iv });
|
||||||
|
return decrypted.toString(cryptojs.enc.Utf8);
|
||||||
|
}
|
||||||
|
}
|
7
src/lib/userSettings.ts
Normal file
7
src/lib/userSettings.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { writable } from 'svelte/store';
|
||||||
|
import { Config } from './config';
|
||||||
|
|
||||||
|
export const userSettings = writable<Config>(new Config());
|
||||||
|
|
||||||
|
export const customCursor = writable<boolean>(true);
|
||||||
|
export const cursorSmoothening = writable<boolean>(true);
|
@ -6,7 +6,17 @@
|
|||||||
import * as Select from '@/components/ui/select';
|
import * as Select from '@/components/ui/select';
|
||||||
import { beatmap_sets, online_friends, server_connection_fails, server_ping } from '@/global';
|
import { beatmap_sets, online_friends, server_connection_fails, server_ping } from '@/global';
|
||||||
import { WebviewWindow } from '@tauri-apps/api/webviewWindow';
|
import { WebviewWindow } from '@tauri-apps/api/webviewWindow';
|
||||||
import { LoaderCircle, Logs, Music2, Play, Users, Wifi, Gamepad2, WifiOff, Settings2 } from 'lucide-svelte';
|
import {
|
||||||
|
LoaderCircle,
|
||||||
|
Logs,
|
||||||
|
Music2,
|
||||||
|
Play,
|
||||||
|
Users,
|
||||||
|
Wifi,
|
||||||
|
Gamepad2,
|
||||||
|
WifiOff,
|
||||||
|
Settings2,
|
||||||
|
} from 'lucide-svelte';
|
||||||
import { Circle } from 'radix-icons-svelte';
|
import { Circle } from 'radix-icons-svelte';
|
||||||
import NumberFlow from '@number-flow/svelte';
|
import NumberFlow from '@number-flow/svelte';
|
||||||
import * as AlertDialog from '@/components/ui/alert-dialog';
|
import * as AlertDialog from '@/components/ui/alert-dialog';
|
||||||
@ -15,6 +25,7 @@
|
|||||||
import { fade, fly, scale } from 'svelte/transition';
|
import { fade, fly, scale } from 'svelte/transition';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import Label from '@/components/ui/label/label.svelte';
|
import Label from '@/components/ui/label/label.svelte';
|
||||||
|
import { cursorSmoothening, customCursor, userSettings } from '@/userSettings';
|
||||||
|
|
||||||
let selectedTab = $state('settings');
|
let selectedTab = $state('settings');
|
||||||
let launching = $state(false);
|
let launching = $state(false);
|
||||||
@ -273,24 +284,48 @@
|
|||||||
class="bg-theme-900/90 flex flex-col justify-center gap-3 border border-theme-800/90 rounded-lg"
|
class="bg-theme-900/90 flex flex-col justify-center gap-3 border border-theme-800/90 rounded-lg"
|
||||||
in:scale={{ duration: 400, start: 0.98 }}
|
in:scale={{ duration: 400, start: 0.98 }}
|
||||||
>
|
>
|
||||||
<div class="flex flex-row items-center gap-3 font-semibold text-xl px-3 pt-3"><Settings2 /> EZPPLauncher Settings</div>
|
<div class="flex flex-row items-center gap-3 font-semibold text-xl px-3 pt-3">
|
||||||
<div class="grid grid-cols-[1fr_auto] gap-y-5 items-center border-t border-theme-800 py-3 px-6">
|
<Settings2 /> EZPPLauncher Settings
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="grid grid-cols-[1fr_auto] gap-y-5 items-center border-t border-theme-800 py-3 px-6"
|
||||||
|
>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<Label class="text-sm" for="setting-custom-cursor">Lazer-Style Cursor</Label>
|
<Label class="text-sm" for="setting-custom-cursor">Lazer-Style Cursor</Label>
|
||||||
<div class="text-muted-foreground text-xs">
|
<div class="text-muted-foreground text-xs">
|
||||||
Enable a custom cursor in the Launcher like in the lazer build of osu!
|
Enable a custom cursor in the Launcher like in the lazer build of osu!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Checkbox id="setting-custom-cursor" class="flex items-center justify-center w-5 h-5"
|
<Checkbox
|
||||||
|
id="setting-custom-cursor"
|
||||||
|
checked={$customCursor}
|
||||||
|
onCheckedChange={async (e) => {
|
||||||
|
if (!e) {
|
||||||
|
cursorSmoothening.set(false);
|
||||||
|
}
|
||||||
|
customCursor.set(e);
|
||||||
|
|
||||||
|
$userSettings.save();
|
||||||
|
}}
|
||||||
|
class="flex items-center justify-center w-5 h-5"
|
||||||
></Checkbox>
|
></Checkbox>
|
||||||
|
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<Label class="text-sm" for="setting-custom-cursor">Cursor Smoothening</Label>
|
<Label class="text-sm" for="setting-cursor-smoothening">Cursor Smoothening</Label>
|
||||||
<div class="text-muted-foreground text-xs">
|
<div class="text-muted-foreground text-xs">
|
||||||
Makes the custom cursor movement smoother.
|
Makes the custom cursor movement smoother.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Checkbox id="setting-custom-cursor" class="flex items-center justify-center w-5 h-5"
|
<Checkbox
|
||||||
|
id="setting-cursor-smoothening"
|
||||||
|
checked={$cursorSmoothening}
|
||||||
|
onCheckedChange={async (e) => {
|
||||||
|
if (!$customCursor) return;
|
||||||
|
cursorSmoothening.set(e);
|
||||||
|
$userSettings.save();
|
||||||
|
}}
|
||||||
|
disabled={!$customCursor}
|
||||||
|
class="flex items-center justify-center w-5 h-5"
|
||||||
></Checkbox>
|
></Checkbox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,12 +4,31 @@
|
|||||||
import { setupValues } from '@/global';
|
import { setupValues } from '@/global';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import OsuCursor from '@/components/ui/osu-cursor/OsuCursor.svelte';
|
import OsuCursor from '@/components/ui/osu-cursor/OsuCursor.svelte';
|
||||||
|
import { cursorSmoothening, customCursor, userSettings } from '@/userSettings';
|
||||||
|
import { Buffer } from 'buffer';
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
|
|
||||||
onMount(setupValues);
|
onMount(async () => {
|
||||||
|
window.Buffer = Buffer;
|
||||||
|
setupValues();
|
||||||
|
await $userSettings.init();
|
||||||
|
|
||||||
|
const config_custom_cursor = $userSettings.value('custom_cursor');
|
||||||
|
const config_cursor_smoothening = $userSettings.value('cursor_smoothening');
|
||||||
|
|
||||||
|
console.log("yes", config_cursor_smoothening.get(true))
|
||||||
|
|
||||||
|
customCursor.set(config_custom_cursor.get(true));
|
||||||
|
cursorSmoothening.set(config_cursor_smoothening.get(true));
|
||||||
|
|
||||||
|
customCursor.subscribe((val) => config_custom_cursor.set(val));
|
||||||
|
cursorSmoothening.subscribe((val) => config_cursor_smoothening.set(val));
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<OsuCursor />
|
{#if $customCursor}
|
||||||
|
<OsuCursor smoothCursor={$cursorSmoothening} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
<Titlebar />
|
<Titlebar />
|
||||||
<main>
|
<main>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Tauri doesn't have a Node.js server to do proper SSR
|
// Tauri doesn't have a Node.js server to do proper SSR
|
||||||
// so we will use adapter-static to prerender the app (SSG)
|
// so we will use adapter-static to prerender the app (SSG)
|
||||||
|
|
||||||
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
||||||
export const prerender = true;
|
export const prerender = true;
|
||||||
export const ssr = false;
|
export const ssr = false;
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user