Compare commits
153 Commits
3.0.3
..
40a32d7a60
| Author | SHA1 | Date | |
|---|---|---|---|
| 40a32d7a60 | |||
| 52c60acf37 | |||
| 2788cd6e8b | |||
| 2d1941db33 | |||
| 00958d5238 | |||
| b8a0b448c7 | |||
| 09487e945e | |||
| 2532ab0059 | |||
| 16fe91b3a5 | |||
| eca08f16c5 | |||
| e76d67f3a8 | |||
| 9811b36e58 | |||
|
0f10beb3b4
|
|||
|
4326199a56
|
|||
|
7f65384b1c
|
|||
|
aacd0d1d91
|
|||
|
079a076f99
|
|||
| 6d88c39ce2 | |||
| 56608a64fc | |||
| eaf6f5976d | |||
| 93f1f380ec | |||
| c47ea1f976 | |||
| 09af78f1aa | |||
| 3900b5c6cf | |||
| adf607e24c | |||
| 1128b51778 | |||
| d435f0c09a | |||
| b188e2dee8 | |||
| 8fd56ae749 | |||
| b2e7d22d28 | |||
| d871e06172 | |||
| 6a1c5441c3 | |||
| ef36f49a6f | |||
| 7e40536ec8 | |||
| 694d403aeb | |||
| 9515892b2f | |||
| 0a58f0f63b | |||
| 60e3ef4131 | |||
| 7375cccc05 | |||
| 251bf8177c | |||
| bf4ce18671 | |||
| 4dc83c882d | |||
| e20f11be64 | |||
| 407996269e | |||
| 95c6db6a1d | |||
| a87a4bcc54 | |||
| 97f072f4ce | |||
| 1aa3070ea1 | |||
| d3c3e4e771 | |||
| 921dbd716c | |||
| 34e82f89e8 | |||
| 901fbefd1b | |||
| a795978827 | |||
| a9152cc376 | |||
| 8d790c7da3 | |||
| f5a2c4365b | |||
| a925548ae9 | |||
| a6495ea353 | |||
| 24802b5132 | |||
| f09405ed58 | |||
| eeda85f48f | |||
| 9770e81d6f | |||
| 31b7d17b09 | |||
| 1fc0391113 | |||
| 62f03cf7c0 | |||
| 94f6e850cf | |||
| d6fdb2a152 | |||
| 9cd990cf96 | |||
| 2e0ef81bcb | |||
| 96680ff8b5 | |||
| 0b9d6373bf | |||
| 295c1424c9 | |||
| 0e12a801d2 | |||
| cf86dba5c4 | |||
| 540c653399 | |||
| c9b8d9f599 | |||
| 49665d94bc | |||
| 1a19c19399 | |||
| cbfe5ec868 | |||
| c5b18dacbb | |||
| ef01984875 | |||
| 46ee36ce81 | |||
| c4658ae4cc | |||
| ca15ff566f | |||
| a6fdda4487 | |||
| a30946eb60 | |||
| 9106ad89b3 | |||
| 194709df0c | |||
| 20f625be60 | |||
| 66a5fd84ae | |||
| 44d7401947 | |||
| f973e48561 | |||
| de186b7ff9 | |||
| 244d526933 | |||
| c7a990e3fe | |||
| ed1f741a9e | |||
| b6616a37f4 | |||
| 63433ac626 | |||
| 149b4715d7 | |||
| ae3443d0b9 | |||
| abc7b9d9d9 | |||
| d9dd21d3be | |||
| 0df31178f4 | |||
| 6825f9e99b | |||
| 08a8e34781 | |||
| 1aa973f6bb | |||
| 0999832985 | |||
| 11798318f4 | |||
| f1b909e248 | |||
| 1f845f1282 | |||
| f9b38ec9eb | |||
| 623559cf8e | |||
| 80bd096834 | |||
| e1c6e35f95 | |||
| 57158bab15 | |||
| 58837053c7 | |||
| 458a2cca36 | |||
| cb66df6082 | |||
| 1d1904e995 | |||
| c07e390b65 | |||
| bae0fad19b | |||
| 993eb167fc | |||
| ea2e348ccc | |||
| 2855880c18 | |||
| dcb57c5452 | |||
| c9def2c46b | |||
| b8ebcf5509 | |||
| a338df6a36 | |||
| d67d58824b | |||
| ad090ce38c | |||
| 3d57524a16 | |||
| d6bf3ccb3c | |||
| a548dc875e | |||
| 3029cc66fb | |||
| adf40b70cb | |||
| ff00b27330 | |||
| 95a5591c70 | |||
| cdc3c78ffe | |||
| 509aa36379 | |||
| 20e5961b7c | |||
| 9b816e1e5c | |||
| ada83b32dc | |||
| cbf85753a8 | |||
| eb1ef06c07 | |||
| a64655ec5d | |||
| 45b902cfb6 | |||
| f53aba9a7b | |||
| f7c2dc689a | |||
| b778a5a369 | |||
| 084e006f06 | |||
| 9b3cb0bd26 | |||
| c5649c3f8a | |||
| fac54f3e59 |
@@ -1,7 +1,16 @@
|
||||
{
|
||||
"svelte.enable-ts-plugin": true,
|
||||
"git.enableCommitSigning": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[rust]": {
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
||||
},
|
||||
"json.schemaDownload.trustedDomains": {
|
||||
"https://schemastore.azurewebsites.net/": true,
|
||||
"https://raw.githubusercontent.com/": true,
|
||||
"https://www.schemastore.org/": true,
|
||||
"https://json.schemastore.org/": true,
|
||||
"https://json-schema.org/": true,
|
||||
"https://schema.tauri.app/": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ It enhances the osu! experience with quality-of-life features and integration sp
|
||||
- [x] Displays ping to the EZPPFarm server
|
||||
- [x] Discord Rich Presence
|
||||
- [x] Performance Display Overlay (currently in experimental patcher release stream)
|
||||
- [x] Launcher Theming
|
||||
|
||||
---
|
||||
|
||||
@@ -43,6 +44,7 @@ It enhances the osu! experience with quality-of-life features and integration sp
|
||||
|
||||
- **Rust** (installed via [rustup](https://rustup.rs/) – recommended for Windows)
|
||||
- **Cargo** (comes with rustup)
|
||||
- **[CMake](https://cmake.org/download/)**
|
||||
- **[Bun](https://bun.sh/)** (JavaScript runtime)
|
||||
|
||||
### Steps
|
||||
@@ -72,3 +74,9 @@ src-tauri/target/release/ezpplauncher.exe
|
||||
├── package.json # Bun project config
|
||||
└── README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Launcher Themes
|
||||
|
||||
By default, the launcher includes several downloadable themes. If you want to create your own custom theme, please use the [create-ezpplauncher-theme](https://git.ez-pp.farm/EZPPFarm/create-ezpplauncher-theme) repository for a template and instructions.
|
||||
|
||||
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 157 KiB |
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "ezpplauncher",
|
||||
@@ -7,56 +8,62 @@
|
||||
"@better-fetch/fetch": "^1.1.18",
|
||||
"@fontsource/sora": "^5.2.6",
|
||||
"@fontsource/space-mono": "^5.2.8",
|
||||
"@iarna/toml": "2.2.5",
|
||||
"@number-flow/svelte": "^0.3.9",
|
||||
"@tailwindcss/typography": "0.5.16",
|
||||
"@number-flow/svelte": "^0.4.0",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@tauri-apps/api": "2.6.0",
|
||||
"@tauri-apps/plugin-dialog": "2.3.1",
|
||||
"@tauri-apps/plugin-fs": "2.4.1",
|
||||
"@tauri-apps/plugin-shell": "2.3.0",
|
||||
"animejs": "^4.0.2",
|
||||
"@tauri-apps/api": "^2.10.1",
|
||||
"@tauri-apps/plugin-dialog": "^2.7.0",
|
||||
"@tauri-apps/plugin-fs": "^2.5.0",
|
||||
"@tauri-apps/plugin-shell": "^2.3.5",
|
||||
"animejs": "^4.1.3",
|
||||
"buffer": "^6.0.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
"lucide-svelte": "0.525.0",
|
||||
"jszip": "^3.10.1",
|
||||
"lucide-svelte": "^1.0.1",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-to-webcomponent": "^2.0.1",
|
||||
"semver": "^7.7.2",
|
||||
"svelte-confetti": "^2.0.0",
|
||||
"tw-animate-css": "^1.3.0",
|
||||
"sileo": "^0.1.3",
|
||||
"svelte-confetti": "^2.3.2",
|
||||
"tw-animate-css": "^1.3.8",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^1.2.5",
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@lucide/svelte": "^0.525.0",
|
||||
"@sveltejs/adapter-static": "3.0.8",
|
||||
"@sveltejs/kit": "2.22.2",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.1.0",
|
||||
"@tauri-apps/cli": "2.6.1",
|
||||
"@types/bun": "^1.2.18",
|
||||
"@eslint/compat": "^2.0.0",
|
||||
"@eslint/js": "^9.35.0",
|
||||
"@iarna/toml": "2.2.5",
|
||||
"@lucide/svelte": "^1.8.0",
|
||||
"@sveltejs/adapter-static": "^3.0.9",
|
||||
"@sveltejs/kit": "^2.57.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
||||
"@tauri-apps/cli": "^2.10.0",
|
||||
"@types/bun": "^1.2.21",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/semver": "^7.7.0",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/semver": "^7.7.1",
|
||||
"autoprefixer": "10.4.21",
|
||||
"bits-ui": "^2.8.10",
|
||||
"clsx": "2.1.1",
|
||||
"eslint": "^9.18.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-svelte": "^3.0.0",
|
||||
"globals": "^16.0.0",
|
||||
"mode-watcher": "^1.0.6",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-svelte": "^3.3.3",
|
||||
"sass-embedded": "1.89.2",
|
||||
"svelte": "5.34.8",
|
||||
"svelte-check": "4.2.2",
|
||||
"bits-ui": "^1.4.7",
|
||||
"clsx": "^2.1.1",
|
||||
"eslint": "^9.35.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-svelte": "^3.12.2",
|
||||
"globals": "^17.0.0",
|
||||
"mode-watcher": "^1.1.0",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"sass-embedded": "^1.92.1",
|
||||
"svelte": "^5.55.3",
|
||||
"svelte-check": "^4.3.1",
|
||||
"svelte-sonner": "^1.0.5",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tailwind-variants": "^1.0.0",
|
||||
"tailwind-variants": "^3.1.0",
|
||||
"tailwindcss": "^4.1.7",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tslib": "2.8.1",
|
||||
"typescript": "5.8.3",
|
||||
"typescript-eslint": "^8.20.0",
|
||||
"vite": "7.0.0",
|
||||
"vite-plugin-devtools-json": "^0.3.0",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^6.0.2",
|
||||
"typescript-eslint": "^8.42.0",
|
||||
"vite": "^8.0.8",
|
||||
"vite-plugin-devtools-json": "^1.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -67,75 +74,31 @@
|
||||
|
||||
"@bufbuild/protobuf": ["@bufbuild/protobuf@2.5.2", "", {}, "sha512-foZ7qr0IsUBjzWIq+SuBLfdQCpJ1j8cTuNNT4owngTHoN5KsJb8L9t65fzz7SCeSWzescoOil/0ldqiL041ABg=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA=="],
|
||||
"@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=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.5", "", { "os": "android", "cpu": "arm" }, "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA=="],
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.5", "", { "os": "android", "cpu": "arm64" }, "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg=="],
|
||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.5", "", { "os": "android", "cpu": "x64" }, "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.5", "", { "os": "linux", "cpu": "arm" }, "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.5", "", { "os": "linux", "cpu": "x64" }, "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw=="],
|
||||
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.5", "", { "os": "none", "cpu": "arm64" }, "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.5", "", { "os": "none", "cpu": "x64" }, "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ=="],
|
||||
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.5", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g=="],
|
||||
|
||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="],
|
||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="],
|
||||
|
||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="],
|
||||
|
||||
"@eslint/compat": ["@eslint/compat@1.3.1", "", { "peerDependencies": { "eslint": "^8.40 || 9" }, "optionalPeers": ["eslint"] }, "sha512-k8MHony59I5EPic6EQTCNOuPoVBnoYXkP+20xvwFjN7t0qI3ImyvyBgg+hIVPwC8JaxVjjUZld+cLfBLFDLucg=="],
|
||||
"@eslint/compat": ["@eslint/compat@2.0.0", "", { "dependencies": { "@eslint/core": "^1.0.0" }, "peerDependencies": { "eslint": "^8.40 || 9" }, "optionalPeers": ["eslint"] }, "sha512-T9AfE1G1uv4wwq94ozgTGio5EUQBqAVe1X9qsQtSNVEYW6j3hvtZVm8Smr4qL1qDPFg+lOB2cL5RxTRMzq4CTA=="],
|
||||
|
||||
"@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="],
|
||||
|
||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.3.0", "", {}, "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw=="],
|
||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.3.1", "", {}, "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA=="],
|
||||
|
||||
"@eslint/core": ["@eslint/core@0.14.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg=="],
|
||||
"@eslint/core": ["@eslint/core@1.0.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-PRfWP+8FOldvbApr6xL7mNCw4cJcSTq4GA7tYbgq15mRb0kWKO/wEB2jr+uwjFH3sZvEZneZyCUGTxsv4Sahyw=="],
|
||||
|
||||
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
|
||||
|
||||
"@eslint/js": ["@eslint/js@9.30.1", "", {}, "sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg=="],
|
||||
"@eslint/js": ["@eslint/js@9.35.0", "", {}, "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw=="],
|
||||
|
||||
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
|
||||
|
||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.3", "", { "dependencies": { "@eslint/core": "^0.15.1", "levn": "^0.4.1" } }, "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag=="],
|
||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.5", "", { "dependencies": { "@eslint/core": "^0.15.2", "levn": "^0.4.1" } }, "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w=="],
|
||||
|
||||
"@floating-ui/core": ["@floating-ui/core@1.7.1", "", { "dependencies": { "@floating-ui/utils": "^0.2.9" } }, "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw=="],
|
||||
|
||||
@@ -163,6 +126,8 @@
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="],
|
||||
|
||||
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||
|
||||
"@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="],
|
||||
@@ -171,7 +136,9 @@
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="],
|
||||
|
||||
"@lucide/svelte": ["@lucide/svelte@0.525.0", "", { "peerDependencies": { "svelte": "^5" } }, "sha512-dyUxkXzepagLUzL8jHQNdeH286nC66ClLACsg+Neu/bjkRJWPWMzkT+H0DKlE70QdkicGCfs1ZGmXCc351hmZA=="],
|
||||
"@lucide/svelte": ["@lucide/svelte@1.8.0", "", { "peerDependencies": { "svelte": "^5" } }, "sha512-+zYQUKqEOVP5lxbGmxL1OVgGMQtRK91eIJ0bR+3Cr1ts4oQEsQfxyzzd5X47psJlblAuGFrl2xm4YuATjR9oaA=="],
|
||||
|
||||
"@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" } }, "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ=="],
|
||||
|
||||
"@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=="],
|
||||
|
||||
@@ -179,59 +146,83 @@
|
||||
|
||||
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||
|
||||
"@number-flow/svelte": ["@number-flow/svelte@0.3.9", "", { "dependencies": { "esm-env": "^1.1.4", "number-flow": "0.5.8" }, "peerDependencies": { "svelte": "^4 || ^5" } }, "sha512-CTw1+e0074GzbPX2IHcNCaK8nqxGNCOIUnQUjEjhcmBwBxOAhN3GYLQ6cJHvhQnWwplVe4eQ3z+c25Vttr2stQ=="],
|
||||
"@number-flow/svelte": ["@number-flow/svelte@0.4.0", "", { "dependencies": { "esm-env": "^1.1.4", "number-flow": "0.6.0" }, "peerDependencies": { "svelte": "^4 || ^5" } }, "sha512-9tnowrlZlBV3IVe3Gm1V7yXSf4Ugag2k7iW45xqb04HXSa1ApEImopvGWAjJpHDvS849o+UCb0YH461Mtde9lA=="],
|
||||
|
||||
"@oxc-project/types": ["@oxc-project/types@0.124.0", "", {}, "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg=="],
|
||||
|
||||
"@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
|
||||
|
||||
"@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="],
|
||||
|
||||
"@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw=="],
|
||||
|
||||
"@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg=="],
|
||||
|
||||
"@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ=="],
|
||||
|
||||
"@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA=="],
|
||||
|
||||
"@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q=="],
|
||||
|
||||
"@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w=="],
|
||||
|
||||
"@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg=="],
|
||||
|
||||
"@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A=="],
|
||||
|
||||
"@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg=="],
|
||||
|
||||
"@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw=="],
|
||||
|
||||
"@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ=="],
|
||||
|
||||
"@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="],
|
||||
|
||||
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
||||
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.44.1", "", { "os": "android", "cpu": "arm" }, "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w=="],
|
||||
"@r2wc/core": ["@r2wc/core@1.3.0", "", {}, "sha512-aPBnND92Itl+SWWbWyyxdFFF0+RqKB6dptGHEdiPB8ZvnHWHlVzOfEvbEcyUYGtB6HBdsfkVuBiaGYyBFVTzVQ=="],
|
||||
|
||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.44.1", "", { "os": "android", "cpu": "arm64" }, "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ=="],
|
||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.15", "", { "os": "android", "cpu": "arm64" }, "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA=="],
|
||||
|
||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.44.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg=="],
|
||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.15", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg=="],
|
||||
|
||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.44.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw=="],
|
||||
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.15", "", { "os": "darwin", "cpu": "x64" }, "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw=="],
|
||||
|
||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.44.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA=="],
|
||||
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.15", "", { "os": "freebsd", "cpu": "x64" }, "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw=="],
|
||||
|
||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.44.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw=="],
|
||||
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm" }, "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.44.1", "", { "os": "linux", "cpu": "arm" }, "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ=="],
|
||||
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.44.1", "", { "os": "linux", "cpu": "arm" }, "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw=="],
|
||||
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.44.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ=="],
|
||||
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "ppc64" }, "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.44.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g=="],
|
||||
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "s390x" }, "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ=="],
|
||||
|
||||
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.44.1", "", { "os": "linux", "cpu": "none" }, "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew=="],
|
||||
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "x64" }, "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA=="],
|
||||
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.44.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA=="],
|
||||
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.15", "", { "os": "linux", "cpu": "x64" }, "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.44.1", "", { "os": "linux", "cpu": "none" }, "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw=="],
|
||||
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.15", "", { "os": "none", "cpu": "arm64" }, "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.44.1", "", { "os": "linux", "cpu": "none" }, "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg=="],
|
||||
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.15", "", { "dependencies": { "@emnapi/core": "1.9.2", "@emnapi/runtime": "1.9.2", "@napi-rs/wasm-runtime": "^1.1.3" }, "cpu": "none" }, "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q=="],
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.44.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw=="],
|
||||
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15", "", { "os": "win32", "cpu": "arm64" }, "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.44.1", "", { "os": "linux", "cpu": "x64" }, "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw=="],
|
||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.15", "", { "os": "win32", "cpu": "x64" }, "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.44.1", "", { "os": "linux", "cpu": "x64" }, "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g=="],
|
||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.15", "", {}, "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g=="],
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.44.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg=="],
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.44.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A=="],
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.44.1", "", { "os": "win32", "cpu": "x64" }, "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug=="],
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
|
||||
|
||||
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.5", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ=="],
|
||||
|
||||
"@sveltejs/adapter-static": ["@sveltejs/adapter-static@3.0.8", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-YaDrquRpZwfcXbnlDsSrBQNCChVOT9MGuSg+dMAyfsAa1SmiAhrA5jUYUiIMC59G92kIbY/AaQOWcBdq+lh+zg=="],
|
||||
"@sveltejs/adapter-static": ["@sveltejs/adapter-static@3.0.9", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-aytHXcMi7lb9ljsWUzXYQ0p5X1z9oWud2olu/EpmH7aCu4m84h7QLvb5Wp+CFirKcwoNnYvYWhyP/L8Vh1ztdw=="],
|
||||
|
||||
"@sveltejs/kit": ["@sveltejs/kit@2.22.2", "", { "dependencies": { "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.1.0", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0", "vitefu": "^1.0.6" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-2MvEpSYabUrsJAoq5qCOBGAlkICjfjunrnLcx3YAk2XV7TvAIhomlKsAgR4H/4uns5rAfYmj7Wet5KRtc8dPIg=="],
|
||||
"@sveltejs/kit": ["@sveltejs/kit@2.57.1", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.6.4", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "set-cookie-parser": "^3.0.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3 || ^6.0.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-VRdSbB96cI1EnRh09CqmnQqP/YJvET5buj8S6k7CxaJqBJD4bw4fRKDjcarAj/eX9k2eHifQfDH8NtOh+ZxxPw=="],
|
||||
|
||||
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.1.0", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0-next.1", "debug": "^4.4.1", "deepmerge": "^4.3.1", "kleur": "^4.1.5", "magic-string": "^0.30.17", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-+U6lz1wvGEG/BvQyL4z/flyNdQ9xDNv5vrh+vWBWTHaebqT0c9RNggpZTo/XSPoHsSCWBlYaTlRX8pZ9GATXCw=="],
|
||||
|
||||
"@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.0", "", { "dependencies": { "debug": "^4.4.1" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-iwQ8Z4ET6ZFSt/gC+tVfcsSBHwsqc6RumSaiLUkAurW3BCpJam65cmHw0oOlDMTO0u+PZi9hilBRYN+LZNHTUQ=="],
|
||||
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@7.0.0", "", { "dependencies": { "deepmerge": "^4.3.1", "magic-string": "^0.30.21", "obug": "^2.1.0", "vitefu": "^1.1.2" }, "peerDependencies": { "svelte": "^5.46.4", "vite": "^8.0.0-beta.7 || ^8.0.0" } }, "sha512-ILXmxC7HAsnkK2eslgPetrqqW1BKSL7LktsFgqzNj83MaivMGZzluWq32m25j2mDOjmSKX7GGWahePhuEs7P/g=="],
|
||||
|
||||
"@swc/helpers": ["@swc/helpers@0.5.17", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A=="],
|
||||
|
||||
@@ -267,39 +258,41 @@
|
||||
|
||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.11", "", { "dependencies": { "@tailwindcss/node": "4.1.11", "@tailwindcss/oxide": "4.1.11", "tailwindcss": "4.1.11" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw=="],
|
||||
|
||||
"@tauri-apps/api": ["@tauri-apps/api@2.6.0", "", {}, "sha512-hRNcdercfgpzgFrMXWwNDBN0B7vNzOzRepy6ZAmhxi5mDLVPNrTpo9MGg2tN/F7JRugj4d2aF7E1rtPXAHaetg=="],
|
||||
"@tauri-apps/api": ["@tauri-apps/api@2.10.1", "", {}, "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw=="],
|
||||
|
||||
"@tauri-apps/cli": ["@tauri-apps/cli@2.6.1", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.6.1", "@tauri-apps/cli-darwin-x64": "2.6.1", "@tauri-apps/cli-linux-arm-gnueabihf": "2.6.1", "@tauri-apps/cli-linux-arm64-gnu": "2.6.1", "@tauri-apps/cli-linux-arm64-musl": "2.6.1", "@tauri-apps/cli-linux-riscv64-gnu": "2.6.1", "@tauri-apps/cli-linux-x64-gnu": "2.6.1", "@tauri-apps/cli-linux-x64-musl": "2.6.1", "@tauri-apps/cli-win32-arm64-msvc": "2.6.1", "@tauri-apps/cli-win32-ia32-msvc": "2.6.1", "@tauri-apps/cli-win32-x64-msvc": "2.6.1" }, "bin": { "tauri": "tauri.js" } }, "sha512-8NrwfZjeyKH1zwg+Xu4epx8WLjffoiW1Zs9CCFYCJns7uUghzudDm92o+8ROosg5Njlvp1GXBuIRsdrEwBsDhg=="],
|
||||
"@tauri-apps/cli": ["@tauri-apps/cli@2.10.0", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.10.0", "@tauri-apps/cli-darwin-x64": "2.10.0", "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.0", "@tauri-apps/cli-linux-arm64-gnu": "2.10.0", "@tauri-apps/cli-linux-arm64-musl": "2.10.0", "@tauri-apps/cli-linux-riscv64-gnu": "2.10.0", "@tauri-apps/cli-linux-x64-gnu": "2.10.0", "@tauri-apps/cli-linux-x64-musl": "2.10.0", "@tauri-apps/cli-win32-arm64-msvc": "2.10.0", "@tauri-apps/cli-win32-ia32-msvc": "2.10.0", "@tauri-apps/cli-win32-x64-msvc": "2.10.0" }, "bin": { "tauri": "tauri.js" } }, "sha512-ZwT0T+7bw4+DPCSWzmviwq5XbXlM0cNoleDKOYPFYqcZqeKY31KlpoMW/MOON/tOFBPgi31a2v3w9gliqwL2+Q=="],
|
||||
|
||||
"@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.6.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-67aVLeXcJrl9D+4xQLR8NCQYKXQyZB96Tai+uy53jOY0u+uKvFngjbSS9CmntILFhLWoueDxQj3Ws5OSvjekiA=="],
|
||||
"@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.10.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-avqHD4HRjrMamE/7R/kzJPcAJnZs0IIS+1nkDP5b+TNBn3py7N2aIo9LIpy+VQq0AkN8G5dDpZtOOBkmWt/zjA=="],
|
||||
|
||||
"@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.6.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-6mQp/VikM0pKVKau1p/NMVyGq1JakOFbk6YlCzwdd04OwmiDuVe9PTxzqcA/JnqWXEhSGlRKeyMXUxqifPBPYw=="],
|
||||
"@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.10.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-keDmlvJRStzVFjZTd0xYkBONLtgBC9eMTpmXnBXzsHuawV2q9PvDo2x6D5mhuoMVrJ9QWjgaPKBBCFks4dK71Q=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.6.1", "", { "os": "linux", "cpu": "arm" }, "sha512-iY9cr2k3h2nh6I0bExEWCOgWloN4q0p/evhfNBIAIly1kycy+xWHEsFj2WfzU31Ce8RkqxilPHNuCp36gDM+Yw=="],
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.10.0", "", { "os": "linux", "cpu": "arm" }, "sha512-e5u0VfLZsMAC9iHaOEANumgl6lfnJx0Dtjkd8IJpysZ8jp0tJ6wrIkto2OzQgzcYyRCKgX72aKE0PFgZputA8g=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.6.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-AT+SpHShi/uJipzj+A9kHPDUgZfzHYyl0B3/4UXYtHB9hQfQUmjh9wLadmx0ai/ESyJFxkJJK6FFRvxotQ3gIQ=="],
|
||||
"@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.10.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-YrYYk2dfmBs5m+OIMCrb+JH/oo+4FtlpcrTCgiFYc7vcs6m3QDd1TTyWu0u01ewsCtK2kOdluhr/zKku+KP7HA=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.6.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CCgE0uqcWTtU48TmK/J03h5x/hxi3PEc11ci3LQ9WqIE15btyhynNzDKbxKwOyDCMcfbDT+MweoiCPnely2ZRA=="],
|
||||
"@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.10.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-GUoPdVJmrJRIXFfW3Rkt+eGK9ygOdyISACZfC/bCSfOnGt8kNdQIQr5WRH9QUaTVFIwxMlQyV3m+yXYP+xhSVA=="],
|
||||
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.6.1", "", { "os": "linux", "cpu": "none" }, "sha512-2i3MYr2oKaJk7Tz2FZ+R5x8cV827CudvEXW6FzCER26pfx/PofH/55N7aRQf4+qPXi5O3T+3myq88nRerzHr6g=="],
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.10.0", "", { "os": "linux", "cpu": "none" }, "sha512-JO7s3TlSxshwsoKNCDkyvsx5gw2QAs/Y2GbR5UE2d5kkU138ATKoPOtxn8G1fFT1aDW4LH0rYAAfBpGkDyJJnw=="],
|
||||
|
||||
"@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.6.1", "", { "os": "linux", "cpu": "x64" }, "sha512-of5i3FW1tjTXECtMdirQsQnVIzcKq1s5Cad9YLVa6agEnFnZbFU3rKQ6/Wfu5SZbjSiI7SBO1hksjIAq1vkVcg=="],
|
||||
"@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.10.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Uvh4SUUp4A6DVRSMWjelww0GnZI3PlVy7VS+DRF5napKuIehVjGl9XD0uKoCoxwAQBLctvipyEK+pDXpJeoHng=="],
|
||||
|
||||
"@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.6.1", "", { "os": "linux", "cpu": "x64" }, "sha512-QfAgg7VIlOrTa2X3fBLRp6ugbC5ZonSWgVhNCLDgHLp5Cga41XOi5qU7ZtZhjjCdcWNiE0DtBQmSb1YVhCp+SA=="],
|
||||
"@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.10.0", "", { "os": "linux", "cpu": "x64" }, "sha512-AP0KRK6bJuTpQ8kMNWvhIpKUkQJfcPFeba7QshOQZjJ8wOS6emwTN4K5g/d3AbCMo0RRdnZWwu67MlmtJyxC1Q=="],
|
||||
|
||||
"@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.6.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-ee1h3jwamumGjLEXZA4VsSUcVWTtGpuvxy+nqFfu7wb2k6IcBrFEJGa6yXa7sQjuCAAorLfSIXGuDEJARqnpFw=="],
|
||||
"@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.10.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-97DXVU3dJystrq7W41IX+82JEorLNY+3+ECYxvXWqkq7DBN6FsA08x/EFGE8N/b0LTOui9X2dvpGGoeZKKV08g=="],
|
||||
|
||||
"@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.6.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-WEZVYekxuG9X9mFJEeJPHsSAl8sHOEEbJQriim+OziFbLA9pv/gfcRRqsbmEJL8uBC8GLTEOdUVolohwXk6S9g=="],
|
||||
"@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.10.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-EHyQ1iwrWy1CwMalEm9z2a6L5isQ121pe7FcA2xe4VWMJp+GHSDDGvbTv/OPdkt2Lyr7DAZBpZHM6nvlHXEc4A=="],
|
||||
|
||||
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.6.1", "", { "os": "win32", "cpu": "x64" }, "sha512-fBsjPqIIHaaQt7tnjIGmPHu5p/BNBVD4JfOhO3QqIVBzAb+W2bDyIQPdoDMI943soLr/+N10xeTiPu+3L74+dQ=="],
|
||||
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.10.0", "", { "os": "win32", "cpu": "x64" }, "sha512-NTpyQxkpzGmU6ceWBTY2xRIEaS0ZLbVx1HE1zTA3TY/pV3+cPoPPOs+7YScr4IMzXMtOw7tLw5LEXo5oIG3qaQ=="],
|
||||
|
||||
"@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.3.1", "", { "dependencies": { "@tauri-apps/api": "^2.6.0" } }, "sha512-B7jvyhycV8SI/WHzPjciwtYfdFM6/9EXuMjRgYWZwn8GPDmHxpT80aJdb/eDVN+NgoAFDh9bu4QPonYahoYnZQ=="],
|
||||
"@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.1", "", { "dependencies": { "@tauri-apps/api": "^2.6.0" } }, "sha512-vJlKZVGF3UAFGoIEVT6Oq5L4HGDCD78WmA4uhzitToqYiBKWAvZR61M6zAyQzHqLs0ADemkE4RSy/5sCmZm6ZQ=="],
|
||||
"@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-shell": ["@tauri-apps/plugin-shell@2.3.0", "", { "dependencies": { "@tauri-apps/api": "^2.6.0" } }, "sha512-6GIRxO2z64uxPX4CCTuhQzefvCC0ew7HjdBhMALiGw74vFBDY95VWueAHOHgNOMV4UOUAFupyidN9YulTe5xlA=="],
|
||||
"@tauri-apps/plugin-shell": ["@tauri-apps/plugin-shell@2.3.5", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-jewtULhiQ7lI7+owCKAjc8tYLJr92U16bPOeAa472LHJdgaibLP83NcfAF2e+wkEcA53FxKQAZ7byDzs2eeizg=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="],
|
||||
|
||||
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
||||
|
||||
@@ -313,27 +306,31 @@
|
||||
|
||||
"@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="],
|
||||
|
||||
"@types/semver": ["@types/semver@7.7.0", "", {}, "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA=="],
|
||||
"@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.35.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.35.1", "@typescript-eslint/type-utils": "8.35.1", "@typescript-eslint/utils": "8.35.1", "@typescript-eslint/visitor-keys": "8.35.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.35.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg=="],
|
||||
"@types/semver": ["@types/semver@7.7.1", "", {}, "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.35.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.35.1", "@typescript-eslint/types": "8.35.1", "@typescript-eslint/typescript-estree": "8.35.1", "@typescript-eslint/visitor-keys": "8.35.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w=="],
|
||||
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
||||
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.35.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.35.1", "@typescript-eslint/types": "^8.35.1", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q=="],
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.42.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/type-utils": "8.42.0", "@typescript-eslint/utils": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.42.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ=="],
|
||||
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.35.1", "", { "dependencies": { "@typescript-eslint/types": "8.35.1", "@typescript-eslint/visitor-keys": "8.35.1" } }, "sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg=="],
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.42.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg=="],
|
||||
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.35.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ=="],
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.42.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.42.0", "@typescript-eslint/types": "^8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg=="],
|
||||
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.35.1", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.35.1", "@typescript-eslint/utils": "8.35.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-HOrUBlfVRz5W2LIKpXzZoy6VTZzMu2n8q9C2V/cFngIC5U1nStJgv0tMV4sZPzdf4wQm9/ToWUFPMN9Vq9VJQQ=="],
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0" } }, "sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw=="],
|
||||
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.35.1", "", {}, "sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ=="],
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.42.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.35.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.35.1", "@typescript-eslint/tsconfig-utils": "8.35.1", "@typescript-eslint/types": "8.35.1", "@typescript-eslint/visitor-keys": "8.35.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g=="],
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.35.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.35.1", "@typescript-eslint/types": "8.35.1", "@typescript-eslint/typescript-estree": "8.35.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ=="],
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.42.0", "", {}, "sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.35.1", "", { "dependencies": { "@typescript-eslint/types": "8.35.1", "eslint-visitor-keys": "^4.2.1" } }, "sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw=="],
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.42.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.42.0", "@typescript-eslint/tsconfig-utils": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.42.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ=="],
|
||||
|
||||
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||
|
||||
@@ -341,13 +338,13 @@
|
||||
|
||||
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
|
||||
|
||||
"animejs": ["animejs@4.0.2", "", {}, "sha512-f0L/kSya2RF23iMSF/VO01pMmLwlAFoiQeNAvBXhEyLzIPd2/QTBRatwGUqkVCC6seaAJYzAkGir55N4SL+h3A=="],
|
||||
"animejs": ["animejs@4.1.3", "", {}, "sha512-4XzlIsQsku1ycSPzchxxT0N+ohEMZObG71nOSBBkZoV4sgQvtXa/qAANkFpTE6pegdV8JnIBZiB0LfdxNoRNMw=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
|
||||
"aria-query": ["aria-query@5.3.1", "", {}, "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g=="],
|
||||
|
||||
"autoprefixer": ["autoprefixer@10.4.21", "", { "dependencies": { "browserslist": "^4.24.4", "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ=="],
|
||||
|
||||
@@ -357,7 +354,7 @@
|
||||
|
||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||
|
||||
"bits-ui": ["bits-ui@2.8.10", "", { "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", "runed": "^0.29.1", "svelte-toolbelt": "^0.9.3", "tabbable": "^6.2.0" }, "peerDependencies": { "@internationalized/date": "^3.8.1", "svelte": "^5.33.0" } }, "sha512-MOobkqapDZNrpcNmeL2g664xFmH4tZBOKBTxFmsQYMZQuybSZHQnPXy+AjM5XZEXRmCFx5+XRmo6+fC3vHh1hQ=="],
|
||||
"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=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
||||
|
||||
@@ -369,7 +366,7 @@
|
||||
|
||||
"buffer-builder": ["buffer-builder@0.2.0", "", {}, "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg=="],
|
||||
|
||||
"bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||
"bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="],
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
@@ -393,10 +390,14 @@
|
||||
|
||||
"cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],
|
||||
|
||||
"core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"crypto-js": ["crypto-js@4.2.0", "", {}, "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="],
|
||||
|
||||
"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=="],
|
||||
|
||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
@@ -409,23 +410,21 @@
|
||||
|
||||
"detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
|
||||
|
||||
"devalue": ["devalue@5.1.1", "", {}, "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="],
|
||||
"devalue": ["devalue@5.7.1", "", {}, "sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.176", "", {}, "sha512-2nDK9orkm7M9ZZkjO3PjbEd3VUulQLyg5T9O3enJdFvUg46Hzd4DUvTvAuEgbdHYXyFsiG4A5sO9IzToMH1cDg=="],
|
||||
|
||||
"enhanced-resolve": ["enhanced-resolve@5.18.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ=="],
|
||||
|
||||
"esbuild": ["esbuild@0.25.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.5", "@esbuild/android-arm": "0.25.5", "@esbuild/android-arm64": "0.25.5", "@esbuild/android-x64": "0.25.5", "@esbuild/darwin-arm64": "0.25.5", "@esbuild/darwin-x64": "0.25.5", "@esbuild/freebsd-arm64": "0.25.5", "@esbuild/freebsd-x64": "0.25.5", "@esbuild/linux-arm": "0.25.5", "@esbuild/linux-arm64": "0.25.5", "@esbuild/linux-ia32": "0.25.5", "@esbuild/linux-loong64": "0.25.5", "@esbuild/linux-mips64el": "0.25.5", "@esbuild/linux-ppc64": "0.25.5", "@esbuild/linux-riscv64": "0.25.5", "@esbuild/linux-s390x": "0.25.5", "@esbuild/linux-x64": "0.25.5", "@esbuild/netbsd-arm64": "0.25.5", "@esbuild/netbsd-x64": "0.25.5", "@esbuild/openbsd-arm64": "0.25.5", "@esbuild/openbsd-x64": "0.25.5", "@esbuild/sunos-x64": "0.25.5", "@esbuild/win32-arm64": "0.25.5", "@esbuild/win32-ia32": "0.25.5", "@esbuild/win32-x64": "0.25.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ=="],
|
||||
|
||||
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||
|
||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||
|
||||
"eslint": ["eslint@9.30.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.0", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.30.1", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ=="],
|
||||
"eslint": ["eslint@9.35.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.35.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg=="],
|
||||
|
||||
"eslint-config-prettier": ["eslint-config-prettier@10.1.5", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw=="],
|
||||
"eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="],
|
||||
|
||||
"eslint-plugin-svelte": ["eslint-plugin-svelte@3.10.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.6.1", "@jridgewell/sourcemap-codec": "^1.5.0", "esutils": "^2.0.3", "globals": "^16.0.0", "known-css-properties": "^0.37.0", "postcss": "^8.4.49", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^7.0.0", "semver": "^7.6.3", "svelte-eslint-parser": "^1.2.0" }, "peerDependencies": { "eslint": "^8.57.1 || ^9.0.0", "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-csCh2x0ge/DugXC7dCANh46Igi7bjMZEy6rHZCdS13AoGVJSu7a90Kru3I8oMYLGEemPRE1hQXadxvRPVMAAXQ=="],
|
||||
"eslint-plugin-svelte": ["eslint-plugin-svelte@3.12.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.6.1", "@jridgewell/sourcemap-codec": "^1.5.0", "esutils": "^2.0.3", "globals": "^16.0.0", "known-css-properties": "^0.37.0", "postcss": "^8.4.49", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^7.0.0", "semver": "^7.6.3", "svelte-eslint-parser": "^1.3.0" }, "peerDependencies": { "eslint": "^8.57.1 || ^9.0.0", "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-NDYltSWcDybvnXD5P3NtrLAfdrgr2lklZsXpyIoSlQfg2d80p/E853XXccu+uVn+w4+Q/iHy4oRw00GJH9I/Cg=="],
|
||||
|
||||
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
|
||||
|
||||
@@ -437,7 +436,7 @@
|
||||
|
||||
"esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
|
||||
|
||||
"esrap": ["esrap@1.4.9", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-3OMlcd0a03UGuZpPeUC1HxR3nA23l+HEyCiZw3b3FumJIN9KphoGzDJKMXI1S72jVS1dsenDyQC0kJlO1U9E1g=="],
|
||||
"esrap": ["esrap@2.2.5", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, "peerDependencies": { "@typescript-eslint/types": "^8.2.0" }, "optionalPeers": ["@typescript-eslint/types"] }, "sha512-/yLB1538mag+dn0wsePTe8C0rDIjUOaJpMs2McodSzmM2msWcZsBSdRtg6HOBt0A/r82BN+Md3pgwSc/uWt2Ig=="],
|
||||
|
||||
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
|
||||
|
||||
@@ -469,11 +468,13 @@
|
||||
|
||||
"fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="],
|
||||
|
||||
"framer-motion": ["framer-motion@12.34.1", "", { "dependencies": { "motion-dom": "^12.34.1", "motion-utils": "^12.29.2", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-kcZyNaYQfvE2LlH6+AyOaJAQV4rGp5XbzfhsZpiSZcwDMfZUHhuxLWeyRzf5I7jip3qKRpuimPA9pXXfr111kQ=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||
|
||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||
|
||||
"globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="],
|
||||
"globals": ["globals@17.0.0", "", {}, "sha512-gv5BeD2EssA793rlFWVPMMCqefTlpusw6/2TbAVMy0FzcG8wKJn4O+NqJ4+XWmmwrayJgw5TzrmWjFgmz1XPqw=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
@@ -485,12 +486,16 @@
|
||||
|
||||
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||
|
||||
"immediate": ["immediate@3.0.6", "", {}, "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="],
|
||||
|
||||
"immutable": ["immutable@5.1.3", "", {}, "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg=="],
|
||||
|
||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||
|
||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
||||
"inline-style-parser": ["inline-style-parser@0.2.4", "", {}, "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q=="],
|
||||
|
||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
@@ -501,9 +506,11 @@
|
||||
|
||||
"is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="],
|
||||
|
||||
"isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="],
|
||||
"jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
||||
|
||||
@@ -513,6 +520,8 @@
|
||||
|
||||
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
|
||||
|
||||
"jszip": ["jszip@3.10.1", "", { "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", "readable-stream": "~2.3.6", "setimmediate": "^1.0.5" } }, "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g=="],
|
||||
|
||||
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
|
||||
|
||||
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
||||
@@ -521,27 +530,31 @@
|
||||
|
||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||
|
||||
"lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
|
||||
"lie": ["lie@3.3.0", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ=="],
|
||||
|
||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
|
||||
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
||||
|
||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
|
||||
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
|
||||
|
||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
|
||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
|
||||
|
||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
|
||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
|
||||
|
||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
|
||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
|
||||
|
||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
|
||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
|
||||
|
||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
|
||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
|
||||
|
||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
|
||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
|
||||
|
||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
|
||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
|
||||
|
||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
|
||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
|
||||
|
||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
|
||||
|
||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
|
||||
|
||||
"lilconfig": ["lilconfig@2.1.0", "", {}, "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="],
|
||||
|
||||
@@ -555,9 +568,9 @@
|
||||
|
||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||
|
||||
"lucide-svelte": ["lucide-svelte@0.525.0", "", { "peerDependencies": { "svelte": "^3 || ^4 || ^5.0.0-next.42" } }, "sha512-kfuN6JcCqTfCz2B76aXnyGLAzEBRSYw5GaUspM5RNHQZS5aI5yaKu06fbaofOk8cDvUtY0AUm/zAix7aUX6Q3A=="],
|
||||
"lucide-svelte": ["lucide-svelte@1.0.1", "", { "peerDependencies": { "svelte": "^3 || ^4 || ^5.0.0-next.42" } }, "sha512-WvzZgk0pqzgda+AErLvgWxHkfg/+GgUwqKMRHvzt0IqyMdmyEDzDCk3Z+Wo/3y753oIgx8u9Q4eUbWkghFa8Jg=="],
|
||||
|
||||
"magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
|
||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||
|
||||
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
||||
|
||||
@@ -573,6 +586,12 @@
|
||||
|
||||
"mode-watcher": ["mode-watcher@1.1.0", "", { "dependencies": { "runed": "^0.25.0", "svelte-toolbelt": "^0.7.1" }, "peerDependencies": { "svelte": "^5.27.0" } }, "sha512-mUT9RRGPDYenk59qJauN1rhsIMKBmWA3xMF+uRwE8MW/tjhaDSCCARqkSuDTq8vr4/2KcAxIGVjACxTjdk5C3g=="],
|
||||
|
||||
"motion": ["motion@12.34.1", "", { "dependencies": { "framer-motion": "^12.34.1", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-N9RVNGn/NSo85OgHX1wGaUWHvReuQ7dZUwuQRhHyzY2wfVOvY3cEgn0Mw4NXOsXMHL/y7EYuzA+b59PYI6EejA=="],
|
||||
|
||||
"motion-dom": ["motion-dom@12.34.1", "", { "dependencies": { "motion-utils": "^12.29.2" } }, "sha512-SC7ZC5dRcGwku2g7EsPvI4q/EzHumUbqsDNumBmZTLFg+goBO5LTJvDu9MAxx+0mtX4IA78B2be/A3aRjY0jnw=="],
|
||||
|
||||
"motion-utils": ["motion-utils@12.29.2", "", {}, "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A=="],
|
||||
|
||||
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
|
||||
|
||||
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
|
||||
@@ -583,11 +602,15 @@
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
|
||||
|
||||
"node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="],
|
||||
|
||||
"normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="],
|
||||
|
||||
"number-flow": ["number-flow@0.5.8", "", { "dependencies": { "esm-env": "^1.1.4" } }, "sha512-FPr1DumWyGi5Nucoug14bC6xEz70A1TnhgSHhKyfqjgji2SOTz+iLJxKtv37N5JyJbteGYCm6NQ9p1O4KZ7iiA=="],
|
||||
"number-flow": ["number-flow@0.6.0", "", { "dependencies": { "esm-env": "^1.1.4" } }, "sha512-K8flNq2Wqus53vjp/btVo3qXFkagF8dIdYavreBfE7hlvFFG/b1HMGEH6nZL+mlrJ+4lbLP9OmPv3t2rmRkpSQ=="],
|
||||
|
||||
"obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="],
|
||||
|
||||
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
|
||||
|
||||
@@ -595,6 +618,8 @@
|
||||
|
||||
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
|
||||
|
||||
"pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="],
|
||||
|
||||
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||
|
||||
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||
@@ -603,7 +628,7 @@
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
"picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
|
||||
|
||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||
|
||||
@@ -619,93 +644,119 @@
|
||||
|
||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||
|
||||
"prettier": ["prettier@3.6.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-5xGWRa90Sp2+x1dQtNpIpeOQpTDBs9cZDmA/qs2vDNN2i18PdapqY7CmBeyLlMuGqXJRIOPaCaVZTLNQRWUH/A=="],
|
||||
"prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
|
||||
|
||||
"prettier-plugin-svelte": ["prettier-plugin-svelte@3.4.0", "", { "peerDependencies": { "prettier": "^3.0.0", "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ=="],
|
||||
|
||||
"process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
|
||||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||
|
||||
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
||||
|
||||
"react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
|
||||
|
||||
"react-to-webcomponent": ["react-to-webcomponent@2.0.1", "", { "dependencies": { "@r2wc/core": "^1.0.0" }, "peerDependencies": { "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-jpVztcA0SbV6TnBRV6EFuU+hmuuSIxgEww3wRcbneT0ytqn57y9ygeRfUmhzz8+bYg53u1h4COKk8iAextHE+Q=="],
|
||||
|
||||
"readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||
|
||||
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
||||
|
||||
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
||||
|
||||
"rollup": ["rollup@4.44.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.44.1", "@rollup/rollup-android-arm64": "4.44.1", "@rollup/rollup-darwin-arm64": "4.44.1", "@rollup/rollup-darwin-x64": "4.44.1", "@rollup/rollup-freebsd-arm64": "4.44.1", "@rollup/rollup-freebsd-x64": "4.44.1", "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", "@rollup/rollup-linux-arm-musleabihf": "4.44.1", "@rollup/rollup-linux-arm64-gnu": "4.44.1", "@rollup/rollup-linux-arm64-musl": "4.44.1", "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", "@rollup/rollup-linux-riscv64-gnu": "4.44.1", "@rollup/rollup-linux-riscv64-musl": "4.44.1", "@rollup/rollup-linux-s390x-gnu": "4.44.1", "@rollup/rollup-linux-x64-gnu": "4.44.1", "@rollup/rollup-linux-x64-musl": "4.44.1", "@rollup/rollup-win32-arm64-msvc": "4.44.1", "@rollup/rollup-win32-ia32-msvc": "4.44.1", "@rollup/rollup-win32-x64-msvc": "4.44.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg=="],
|
||||
"rolldown": ["rolldown@1.0.0-rc.15", "", { "dependencies": { "@oxc-project/types": "=0.124.0", "@rolldown/pluginutils": "1.0.0-rc.15" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-x64": "1.0.0-rc.15", "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g=="],
|
||||
|
||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||
|
||||
"runed": ["runed@0.29.2", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-0cq6cA6sYGZwl/FvVqjx9YN+1xEBu9sDDyuWdDW1yWX7JF2wmvmVKfH+hVCZs+csW+P3ARH92MjI3H9QTagOQA=="],
|
||||
"runed": ["runed@0.23.4", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="],
|
||||
|
||||
"rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
|
||||
|
||||
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
|
||||
|
||||
"sass-embedded": ["sass-embedded@1.89.2", "", { "dependencies": { "@bufbuild/protobuf": "^2.5.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "optionalDependencies": { "sass-embedded-android-arm": "1.89.2", "sass-embedded-android-arm64": "1.89.2", "sass-embedded-android-riscv64": "1.89.2", "sass-embedded-android-x64": "1.89.2", "sass-embedded-darwin-arm64": "1.89.2", "sass-embedded-darwin-x64": "1.89.2", "sass-embedded-linux-arm": "1.89.2", "sass-embedded-linux-arm64": "1.89.2", "sass-embedded-linux-musl-arm": "1.89.2", "sass-embedded-linux-musl-arm64": "1.89.2", "sass-embedded-linux-musl-riscv64": "1.89.2", "sass-embedded-linux-musl-x64": "1.89.2", "sass-embedded-linux-riscv64": "1.89.2", "sass-embedded-linux-x64": "1.89.2", "sass-embedded-win32-arm64": "1.89.2", "sass-embedded-win32-x64": "1.89.2" }, "bin": { "sass": "dist/bin/sass.js" } }, "sha512-Ack2K8rc57kCFcYlf3HXpZEJFNUX8xd8DILldksREmYXQkRHI879yy8q4mRDJgrojkySMZqmmmW1NxrFxMsYaA=="],
|
||||
"safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||
|
||||
"sass-embedded-android-arm": ["sass-embedded-android-arm@1.89.2", "", { "os": "android", "cpu": "arm" }, "sha512-oHAPTboBHRZlDBhyRB6dvDKh4KvFs+DZibDHXbkSI6dBZxMTT+Yb2ivocHnctVGucKTLQeT7+OM5DjWHyynL/A=="],
|
||||
"sass": ["sass@1.92.1", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-ffmsdbwqb3XeyR8jJR6KelIXARM9bFQe8A6Q3W4Klmwy5Ckd5gz7jgUNHo4UOqutU5Sk1DtKLbpDP0nLCg1xqQ=="],
|
||||
|
||||
"sass-embedded-android-arm64": ["sass-embedded-android-arm64@1.89.2", "", { "os": "android", "cpu": "arm64" }, "sha512-+pq7a7AUpItNyPu61sRlP6G2A8pSPpyazASb+8AK2pVlFayCSPAEgpwpCE9A2/Xj86xJZeMizzKUHxM2CBCUxA=="],
|
||||
"sass-embedded": ["sass-embedded@1.92.1", "", { "dependencies": { "@bufbuild/protobuf": "^2.5.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "optionalDependencies": { "sass-embedded-all-unknown": "1.92.1", "sass-embedded-android-arm": "1.92.1", "sass-embedded-android-arm64": "1.92.1", "sass-embedded-android-riscv64": "1.92.1", "sass-embedded-android-x64": "1.92.1", "sass-embedded-darwin-arm64": "1.92.1", "sass-embedded-darwin-x64": "1.92.1", "sass-embedded-linux-arm": "1.92.1", "sass-embedded-linux-arm64": "1.92.1", "sass-embedded-linux-musl-arm": "1.92.1", "sass-embedded-linux-musl-arm64": "1.92.1", "sass-embedded-linux-musl-riscv64": "1.92.1", "sass-embedded-linux-musl-x64": "1.92.1", "sass-embedded-linux-riscv64": "1.92.1", "sass-embedded-linux-x64": "1.92.1", "sass-embedded-unknown-all": "1.92.1", "sass-embedded-win32-arm64": "1.92.1", "sass-embedded-win32-x64": "1.92.1" }, "bin": { "sass": "dist/bin/sass.js" } }, "sha512-28YwLnF5atAhogt3E4hXzz/NB9dwKffyw08a7DEasLh94P7+aELkG3ENSHYCWB9QFN14hYNLfwr9ozUsPDhcDQ=="],
|
||||
|
||||
"sass-embedded-android-riscv64": ["sass-embedded-android-riscv64@1.89.2", "", { "os": "android", "cpu": "none" }, "sha512-HfJJWp/S6XSYvlGAqNdakeEMPOdhBkj2s2lN6SHnON54rahKem+z9pUbCriUJfM65Z90lakdGuOfidY61R9TYg=="],
|
||||
"sass-embedded-all-unknown": ["sass-embedded-all-unknown@1.92.1", "", { "dependencies": { "sass": "1.92.1" }, "cpu": [ "!arm", "!x64", "!arm64", ] }, "sha512-5t6/YZf+vhO3OY/49h8RCL6Cwo78luva0M+TnTM9gu9ASffRXAuOVLNKciSXa3loptyemDDS6IU5/dVH5w0KmA=="],
|
||||
|
||||
"sass-embedded-android-x64": ["sass-embedded-android-x64@1.89.2", "", { "os": "android", "cpu": "x64" }, "sha512-BGPzq53VH5z5HN8de6jfMqJjnRe1E6sfnCWFd4pK+CAiuM7iw5Fx6BQZu3ikfI1l2GY0y6pRXzsVLdp/j4EKEA=="],
|
||||
"sass-embedded-android-arm": ["sass-embedded-android-arm@1.92.1", "", { "os": "android", "cpu": "arm" }, "sha512-4EjpVVzuksERdgAd4BqeSXFnWtWN3DSRyEIUPJ7BhcS9sfDh2Gf6miI2kNTvIQLJ2XIJynDDcEQ8a1U9KwKUTQ=="],
|
||||
|
||||
"sass-embedded-darwin-arm64": ["sass-embedded-darwin-arm64@1.89.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-UCm3RL/tzMpG7DsubARsvGUNXC5pgfQvP+RRFJo9XPIi6elopY5B6H4m9dRYDpHA+scjVthdiDwkPYr9+S/KGw=="],
|
||||
"sass-embedded-android-arm64": ["sass-embedded-android-arm64@1.92.1", "", { "os": "android", "cpu": "arm64" }, "sha512-Q+UruGb7yKawHagVmVDRRKsnc4mJZvWMBnuRCu2coJo2FofyqBmXohVGXbxko97sYceA9TJTrUEx3WVKQUNCbQ=="],
|
||||
|
||||
"sass-embedded-darwin-x64": ["sass-embedded-darwin-x64@1.89.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-D9WxtDY5VYtMApXRuhQK9VkPHB8R79NIIR6xxVlN2MIdEid/TZWi1MHNweieETXhWGrKhRKglwnHxxyKdJYMnA=="],
|
||||
"sass-embedded-android-riscv64": ["sass-embedded-android-riscv64@1.92.1", "", { "os": "android", "cpu": "none" }, "sha512-nCY5btLlX7W7Jc6cCL6D2Yklpiu540EJ2G08YVGu12DrAMCBzqM347CSRf2ojp1H8jyhvmLkaFwnrJWzh+6S+w=="],
|
||||
|
||||
"sass-embedded-linux-arm": ["sass-embedded-linux-arm@1.89.2", "", { "os": "linux", "cpu": "arm" }, "sha512-leP0t5U4r95dc90o8TCWfxNXwMAsQhpWxTkdtySDpngoqtTy3miMd7EYNYd1znI0FN1CBaUvbdCMbnbPwygDlA=="],
|
||||
"sass-embedded-android-x64": ["sass-embedded-android-x64@1.92.1", "", { "os": "android", "cpu": "x64" }, "sha512-qYWR3bftJ77aLYwYDFuzDI4dcwVVixxqQxlIQWNGkHRCexj614qGSSHemr18C2eVj3mjXAQxTQxU68U7pkGPAA=="],
|
||||
|
||||
"sass-embedded-linux-arm64": ["sass-embedded-linux-arm64@1.89.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-2N4WW5LLsbtrWUJ7iTpjvhajGIbmDR18ZzYRywHdMLpfdPApuHPMDF5CYzHbS+LLx2UAx7CFKBnj5LLjY6eFgQ=="],
|
||||
"sass-embedded-darwin-arm64": ["sass-embedded-darwin-arm64@1.92.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-g2yQ3txjMYLKMjL2cW1xRO9nnV3ijf95NbX/QShtV6tiVUETZNWDsRMDEwBNGYY6PTE/UZerjJL1R/2xpQg6WA=="],
|
||||
|
||||
"sass-embedded-linux-musl-arm": ["sass-embedded-linux-musl-arm@1.89.2", "", { "os": "linux", "cpu": "arm" }, "sha512-Z6gG2FiVEEdxYHRi2sS5VIYBmp17351bWtOCUZ/thBM66+e70yiN6Eyqjz80DjL8haRUegNQgy9ZJqsLAAmr9g=="],
|
||||
"sass-embedded-darwin-x64": ["sass-embedded-darwin-x64@1.92.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-eH+fgxLQhTEPjZPCgPAVuX5e514Qp/4DMAUMtlNShv4cr4TD5qOp1XlsPYR/b7uE7p2cKFkUpUn/bHNqJ2ay4A=="],
|
||||
|
||||
"sass-embedded-linux-musl-arm64": ["sass-embedded-linux-musl-arm64@1.89.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-nTyuaBX6U1A/cG7WJh0pKD1gY8hbg1m2SnzsyoFG+exQ0lBX/lwTLHq3nyhF+0atv7YYhYKbmfz+sjPP8CZ9lw=="],
|
||||
"sass-embedded-linux-arm": ["sass-embedded-linux-arm@1.92.1", "", { "os": "linux", "cpu": "arm" }, "sha512-cT3w8yoQTqrtZvWLJeutEGmawITDTY4J6oSVQjeDcPnnoPt0gOFxem8YMznraACXvahw/2+KJDH33BTNgiPo0A=="],
|
||||
|
||||
"sass-embedded-linux-musl-riscv64": ["sass-embedded-linux-musl-riscv64@1.89.2", "", { "os": "linux", "cpu": "none" }, "sha512-N6oul+qALO0SwGY8JW7H/Vs0oZIMrRMBM4GqX3AjM/6y8JsJRxkAwnfd0fDyK+aICMFarDqQonQNIx99gdTZqw=="],
|
||||
"sass-embedded-linux-arm64": ["sass-embedded-linux-arm64@1.92.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-dNmlpGeZkry1BofhAdGFBXrpM69y9LlYuNnncf+HfsOOUtj8j0q1RwS+zb5asknhKFUOAG8GCGRY1df7Rwu35g=="],
|
||||
|
||||
"sass-embedded-linux-musl-x64": ["sass-embedded-linux-musl-x64@1.89.2", "", { "os": "linux", "cpu": "x64" }, "sha512-K+FmWcdj/uyP8GiG9foxOCPfb5OAZG0uSVq80DKgVSC0U44AdGjvAvVZkrgFEcZ6cCqlNC2JfYmslB5iqdL7tg=="],
|
||||
"sass-embedded-linux-musl-arm": ["sass-embedded-linux-musl-arm@1.92.1", "", { "os": "linux", "cpu": "arm" }, "sha512-nPBos6lI31ef2zQhqTZhFOU7ar4impJbLIax0XsqS269YsiCwjhk11VmUloJTpFlJuKMiVXNo7dPx+katxhD/Q=="],
|
||||
|
||||
"sass-embedded-linux-riscv64": ["sass-embedded-linux-riscv64@1.89.2", "", { "os": "linux", "cpu": "none" }, "sha512-g9nTbnD/3yhOaskeqeBQETbtfDQWRgsjHok6bn7DdAuwBsyrR3JlSFyqKc46pn9Xxd9SQQZU8AzM4IR+sY0A0w=="],
|
||||
"sass-embedded-linux-musl-arm64": ["sass-embedded-linux-musl-arm64@1.92.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-TfiEBkCyNzVoOhjHXUT+vZ6+p0ueDbvRw6f4jHdkvljZzXdXMby4wh7BU1odl69rgRTkSvYKhgbErRLDR/F7pQ=="],
|
||||
|
||||
"sass-embedded-linux-x64": ["sass-embedded-linux-x64@1.89.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Ax7dKvzncyQzIl4r7012KCMBvJzOz4uwSNoyoM5IV6y5I1f5hEwI25+U4WfuTqdkv42taCMgpjZbh9ERr6JVMQ=="],
|
||||
"sass-embedded-linux-musl-riscv64": ["sass-embedded-linux-musl-riscv64@1.92.1", "", { "os": "linux", "cpu": "none" }, "sha512-R+RcJA4EYpJDE9JM1GgPYgZo7x94FlxZ6jPodOQkEaZ1S9kvXVCuP5X/0PXRPhu08KJOfeMsAElzfdAjUf7KJg=="],
|
||||
|
||||
"sass-embedded-win32-arm64": ["sass-embedded-win32-arm64@1.89.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-j96iJni50ZUsfD6tRxDQE2QSYQ2WrfHxeiyAXf41Kw0V4w5KYR/Sf6rCZQLMTUOHnD16qTMVpQi20LQSqf4WGg=="],
|
||||
"sass-embedded-linux-musl-x64": ["sass-embedded-linux-musl-x64@1.92.1", "", { "os": "linux", "cpu": "x64" }, "sha512-/HolYRGXJjx8nLw6oj5ZrkR7PFM7X/5kE4MYZaFMpDIPIcw3bqB2fUXLo/MYlRLsw7gBAT6hJAMBrNdKuTphfw=="],
|
||||
|
||||
"sass-embedded-win32-x64": ["sass-embedded-win32-x64@1.89.2", "", { "os": "win32", "cpu": "x64" }, "sha512-cS2j5ljdkQsb4PaORiClaVYynE9OAPZG/XjbOMxpQmjRIf7UroY4PEIH+Waf+y47PfXFX9SyxhYuw2NIKGbEng=="],
|
||||
"sass-embedded-linux-riscv64": ["sass-embedded-linux-riscv64@1.92.1", "", { "os": "linux", "cpu": "none" }, "sha512-b9bxe0CMsbSsLx3nrR0cq8xpIkoAC6X36o4DGMITF3m2v3KsojC7ru9X0Gz+zUFr6rwpq/0lTNzFLNu6sPNo3w=="],
|
||||
|
||||
"sass-embedded-linux-x64": ["sass-embedded-linux-x64@1.92.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xuiK5Jp5NldW4bvlC7AuX1Wf7o0gLZ3md/hNg+bkTvxtCDgnUHtfdo8Q+xWP11bD9QX31xXFWpmUB8UDLi6XQQ=="],
|
||||
|
||||
"sass-embedded-unknown-all": ["sass-embedded-unknown-all@1.92.1", "", { "dependencies": { "sass": "1.92.1" }, "os": [ "!linux", "!win32", "!darwin", "!android", ] }, "sha512-AT9oXvtNY4N+Nd0wvoWqq9A5HjdH/X3aUH4boQUtXyaJ/9DUwnQmBpP5Gtn028ZS8exOGBdobmmWAuigv0k/OA=="],
|
||||
|
||||
"sass-embedded-win32-arm64": ["sass-embedded-win32-arm64@1.92.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-KvmpQjY9yTBMtTYz4WBqetlv9bGaDW1aStcu7MSTbH7YiSybX/9fnxlCAEQv1WlIidQhcJAiyk0Eae+LGK7cIQ=="],
|
||||
|
||||
"sass-embedded-win32-x64": ["sass-embedded-win32-x64@1.92.1", "", { "os": "win32", "cpu": "x64" }, "sha512-B6Nz/GbH7Vkpb2TkQHsGcczWM5t+70VWopWF1x5V5yxLpA8ZzVQ7NTKKi+jDoVY2Efu6ZyzgT9n5KgG2kWliXA=="],
|
||||
|
||||
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||
|
||||
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||
|
||||
"set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="],
|
||||
"set-cookie-parser": ["set-cookie-parser@3.1.0", "", {}, "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw=="],
|
||||
|
||||
"setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"sileo": ["sileo@0.1.3", "", { "dependencies": { "motion": "^12.34.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-kmGjM2ts2TpuPzOaD7llxcMpU37Pyj5dO8s4wGXvDlR143zV2sB6sJ76PCVP4kY2+hfkrLJhiSm/wXGdUHDFjQ=="],
|
||||
|
||||
"sirv": ["sirv@3.0.1", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A=="],
|
||||
|
||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||
|
||||
"string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||
|
||||
"style-to-object": ["style-to-object@1.0.9", "", { "dependencies": { "inline-style-parser": "0.2.4" } }, "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw=="],
|
||||
|
||||
"supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||
|
||||
"svelte": ["svelte@5.34.8", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^1.4.8", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-TF+8irl7rpj3+fpaLuPRX5BqReTAqckp0Fumxa/mCeK3fo0/MnBb9W/Z2bLwtqj3C3r5Lm6NKIAw7YrgIv1Fwg=="],
|
||||
"svelte": ["svelte@5.55.3", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.6.4", "esm-env": "^1.2.1", "esrap": "^2.2.4", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-dS1N+i3bA1v+c4UDb750MlN5vCO82G6vxh8HeTsPsTdJ1BLsN1zxSyDlIdBBqUjqZ/BxEwM8UrFf98aaoVnZFQ=="],
|
||||
|
||||
"svelte-check": ["svelte-check@4.2.2", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-1+31EOYZ7NKN0YDMKusav2hhEoA51GD9Ws6o//0SphMT0ve9mBTsTUEX7OmDMadUP3KjNHsSKtJrqdSaD8CrGQ=="],
|
||||
"svelte-check": ["svelte-check@4.3.1", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-lkh8gff5gpHLjxIV+IaApMxQhTGnir2pNUAqcNgeKkvK5bT/30Ey/nzBxNLDlkztCH4dP7PixkMt9SWEKFPBWg=="],
|
||||
|
||||
"svelte-confetti": ["svelte-confetti@2.3.1", "", { "peerDependencies": { "svelte": ">=5.0.0" } }, "sha512-bKd8etTOeBQyeS9LDPuSd7Oqy5msf0xvxItzsHPajKaarr/LWFzqPq7rp6QQO5rGTzLgM0fmjovOvLkRbrd2gg=="],
|
||||
"svelte-confetti": ["svelte-confetti@2.3.2", "", { "peerDependencies": { "svelte": ">=5.0.0" } }, "sha512-cfIwoGqMPYWRYDUz2g7mG1uHYWy7VBepelQdzCC3j/M42UrAqaBYmIi9xaoQfow4fbINHO9WuARnTyK2bjjGQg=="],
|
||||
|
||||
"svelte-eslint-parser": ["svelte-eslint-parser@1.2.0", "", { "dependencies": { "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.0.0", "espree": "^10.0.0", "postcss": "^8.4.49", "postcss-scss": "^4.0.9", "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-mbPtajIeuiyU80BEyGvwAktBeTX7KCr5/0l+uRGLq1dafwRNrjfM5kHGJScEBlPG3ipu6dJqfW/k0/fujvIEVw=="],
|
||||
"svelte-eslint-parser": ["svelte-eslint-parser@1.3.1", "", { "dependencies": { "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.0.0", "espree": "^10.0.0", "postcss": "^8.4.49", "postcss-scss": "^4.0.9", "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-0Iztj5vcOVOVkhy1pbo5uA9r+d3yaVoE5XPc9eABIWDOSJZ2mOsZ4D+t45rphWCOr0uMw3jtSG2fh2e7GvKnPg=="],
|
||||
|
||||
"svelte-sonner": ["svelte-sonner@1.0.5", "", { "dependencies": { "runed": "^0.28.0" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-9dpGPFqKb/QWudYqGnEz93vuY+NgCEvyNvxoCLMVGw6sDN/3oVeKV1xiEirW2E1N3vJEyj5imSBNOGltQHA7mg=="],
|
||||
|
||||
"svelte-toolbelt": ["svelte-toolbelt@0.9.3", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.29.0", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.30.2" } }, "sha512-HCSWxCtVmv+c6g1ACb8LTwHVbDqLKJvHpo6J8TaqwUme2hj9ATJCpjCPNISR1OCq2Q4U1KT41if9ON0isINQZw=="],
|
||||
"svelte-toolbelt": ["svelte-toolbelt@0.7.1", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="],
|
||||
|
||||
"sync-child-process": ["sync-child-process@1.0.2", "", { "dependencies": { "sync-message-port": "^1.0.0" } }, "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA=="],
|
||||
|
||||
@@ -715,7 +766,7 @@
|
||||
|
||||
"tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="],
|
||||
|
||||
"tailwind-variants": ["tailwind-variants@1.0.0", "", { "dependencies": { "tailwind-merge": "3.0.2" }, "peerDependencies": { "tailwindcss": "*" } }, "sha512-2WSbv4ulEEyuBKomOunut65D8UZwxrHoRfYnxGcQNnHqlSCp2+B7Yz2W+yrNDrxRodOXtGD/1oCcKGNBnUqMqA=="],
|
||||
"tailwind-variants": ["tailwind-variants@3.1.0", "", { "peerDependencies": { "tailwind-merge": ">=3.0.0", "tailwindcss": "*" }, "optionalPeers": ["tailwind-merge"] }, "sha512-ieiYaEfUr+sNhw/k++dosmZfVA4VIG5bV+G1eGdJSC4FcflqQv0iSIlOLj/RbzRuTu/VrIiNSlwh1esBM3BXUg=="],
|
||||
|
||||
"tailwindcss": ["tailwindcss@4.1.11", "", {}, "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA=="],
|
||||
|
||||
@@ -725,7 +776,7 @@
|
||||
|
||||
"tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
@@ -735,13 +786,13 @@
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"tw-animate-css": ["tw-animate-css@1.3.5", "", {}, "sha512-t3u+0YNoloIhj1mMXs779P6MO9q3p3mvGn4k1n3nJPqJw/glZcuijG2qTSN4z4mgNRfW5ZC3aXJFLwDtiipZXA=="],
|
||||
"tw-animate-css": ["tw-animate-css@1.3.8", "", {}, "sha512-Qrk3PZ7l7wUcGYhwZloqfkWCmaXZAoqjkdbIDvzfGshwGtexa/DAs9koXxIkrpEasyevandomzCBAV1Yyop5rw=="],
|
||||
|
||||
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
||||
|
||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
"typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
|
||||
|
||||
"typescript-eslint": ["typescript-eslint@8.35.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.35.1", "@typescript-eslint/parser": "8.35.1", "@typescript-eslint/utils": "8.35.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-xslJjFzhOmHYQzSB/QTeASAHbjmxOGEP6Coh93TXmUBFQoJ1VU35UHIDmG06Jd6taf3wqqC1ntBnCMeymy5Ovw=="],
|
||||
"typescript-eslint": ["typescript-eslint@8.42.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.42.0", "@typescript-eslint/parser": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ozR/rQn+aQXQxh1YgbCzQWDFrsi9mcg+1PM3l/z5o1+20P7suOIaNg515bpr/OYt6FObz/NHcBstydDLHWeEKg=="],
|
||||
|
||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||
|
||||
@@ -755,11 +806,11 @@
|
||||
|
||||
"varint": ["varint@6.0.0", "", {}, "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="],
|
||||
|
||||
"vite": ["vite@7.0.0", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.2", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g=="],
|
||||
"vite": ["vite@8.0.8", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.15", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw=="],
|
||||
|
||||
"vite-plugin-devtools-json": ["vite-plugin-devtools-json@0.3.0", "", { "dependencies": { "uuid": "^11.1.0" }, "peerDependencies": { "vite": "^2.7.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-y8QdN/uZNV0Jj96H9R3s7G9jtcSuyssk8EwSfWaY+NUAdy7976d7rjtXJzqmeCcgp4CZywcTyUc+k6zpPFHdeg=="],
|
||||
"vite-plugin-devtools-json": ["vite-plugin-devtools-json@1.0.0", "", { "dependencies": { "uuid": "^11.1.0" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-MobvwqX76Vqt/O4AbnNMNWoXWGrKUqZbphCUle/J2KXH82yKQiunOeKnz/nqEPosPsoWWPP9FtNuPBSYpiiwkw=="],
|
||||
|
||||
"vitefu": ["vitefu@1.0.7", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-eRWXLBbJjW3X5z5P5IHcSm2yYbYRPb2kQuc+oqsbAl99WB5kVsPbiiox+cymo8twTzifA6itvhr2CmjnaZZp0Q=="],
|
||||
"vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
@@ -767,7 +818,7 @@
|
||||
|
||||
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
||||
|
||||
"yaml": ["yaml@2.8.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ=="],
|
||||
"yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="],
|
||||
|
||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
@@ -777,13 +828,15 @@
|
||||
|
||||
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
|
||||
|
||||
"@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.15.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA=="],
|
||||
"@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.15.2", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg=="],
|
||||
|
||||
"@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="],
|
||||
|
||||
"@sveltejs/vite-plugin-svelte/vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
|
||||
"@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="],
|
||||
|
||||
"@tailwindcss/node/jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
|
||||
"@tailwindcss/node/lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
|
||||
|
||||
"@tailwindcss/node/magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.4.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g=="],
|
||||
|
||||
@@ -803,24 +856,56 @@
|
||||
|
||||
"chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
|
||||
"eslint/@eslint/core": ["@eslint/core@0.15.2", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg=="],
|
||||
|
||||
"eslint-plugin-svelte/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="],
|
||||
|
||||
"eslint-plugin-svelte/globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="],
|
||||
|
||||
"esrap/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"magic-string/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"mode-watcher/runed": ["runed@0.25.0", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-7+ma4AG9FT2sWQEA0Egf6mb7PBT2vHyuHail1ie8ropfSjvZGtEAx8YTmUjv/APCsdRRxEVvArNjALk9zFSOrg=="],
|
||||
|
||||
"mode-watcher/svelte-toolbelt": ["svelte-toolbelt@0.7.1", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="],
|
||||
|
||||
"postcss-load-config/yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="],
|
||||
"svelte/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"svelte-eslint-parser/postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="],
|
||||
|
||||
"svelte-sonner/runed": ["runed@0.28.0", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ=="],
|
||||
|
||||
"tailwind-variants/tailwind-merge": ["tailwind-merge@3.0.2", "", {}, "sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw=="],
|
||||
"tinyglobby/fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"vite/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=="],
|
||||
|
||||
"@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
|
||||
|
||||
"@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
|
||||
|
||||
"@tailwindcss/node/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
|
||||
|
||||
"@tailwindcss/node/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
|
||||
|
||||
"@tailwindcss/node/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
|
||||
|
||||
"@tailwindcss/node/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
|
||||
|
||||
"@tailwindcss/node/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
|
||||
|
||||
"@tailwindcss/node/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
|
||||
|
||||
"@tailwindcss/node/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
|
||||
|
||||
"@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
|
||||
"mode-watcher/svelte-toolbelt/runed": ["runed@0.23.4", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="],
|
||||
"eslint-plugin-svelte/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,5 +36,14 @@ export default ts.config(
|
||||
svelteConfig,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
'no-empty': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_', varsIgnorePattern: '^\\$\\$(Props|Events|Slots|Generic)$' },
|
||||
],
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "ezpplauncher",
|
||||
"version": "3.0.0",
|
||||
"version": "3.2.0",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"debug": "bun run tauri dev",
|
||||
"build": "bun ./scripts/sync-version.ts && bun run tauri:build",
|
||||
"build": "bun ./scripts/sync-version.ts && bun run vite:build && bun run tauri:build",
|
||||
"vite:dev": "vite dev",
|
||||
"vite:build": "vite build",
|
||||
"tauri:build": "tauri build",
|
||||
@@ -21,55 +21,61 @@
|
||||
"@better-fetch/fetch": "^1.1.18",
|
||||
"@fontsource/sora": "^5.2.6",
|
||||
"@fontsource/space-mono": "^5.2.8",
|
||||
"@number-flow/svelte": "^0.3.9",
|
||||
"@tailwindcss/typography": "0.5.16",
|
||||
"@number-flow/svelte": "^0.4.0",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@tauri-apps/api": "2.6.0",
|
||||
"@tauri-apps/plugin-dialog": "2.3.1",
|
||||
"@tauri-apps/plugin-fs": "2.4.1",
|
||||
"@tauri-apps/plugin-shell": "2.3.0",
|
||||
"animejs": "^4.0.2",
|
||||
"@tauri-apps/api": "^2.10.1",
|
||||
"@tauri-apps/plugin-dialog": "^2.7.0",
|
||||
"@tauri-apps/plugin-fs": "^2.5.0",
|
||||
"@tauri-apps/plugin-shell": "^2.3.5",
|
||||
"animejs": "^4.1.3",
|
||||
"buffer": "^6.0.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
"lucide-svelte": "0.525.0",
|
||||
"jszip": "^3.10.1",
|
||||
"lucide-svelte": "^1.0.1",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-to-webcomponent": "^2.0.1",
|
||||
"semver": "^7.7.2",
|
||||
"tw-animate-css": "^1.3.0",
|
||||
"svelte-confetti": "^2.0.0"
|
||||
"sileo": "^0.1.3",
|
||||
"svelte-confetti": "^2.3.2",
|
||||
"tw-animate-css": "^1.3.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^1.2.5",
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@eslint/compat": "^2.0.0",
|
||||
"@eslint/js": "^9.35.0",
|
||||
"@iarna/toml": "2.2.5",
|
||||
"@lucide/svelte": "^0.525.0",
|
||||
"@sveltejs/adapter-static": "3.0.8",
|
||||
"@sveltejs/kit": "2.22.2",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.1.0",
|
||||
"@tauri-apps/cli": "2.6.1",
|
||||
"@types/bun": "^1.2.18",
|
||||
"@lucide/svelte": "^1.8.0",
|
||||
"@sveltejs/adapter-static": "^3.0.9",
|
||||
"@sveltejs/kit": "^2.57.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
||||
"@tauri-apps/cli": "^2.10.0",
|
||||
"@types/bun": "^1.2.21",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/semver": "^7.7.0",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/semver": "^7.7.1",
|
||||
"autoprefixer": "10.4.21",
|
||||
"bits-ui": "^2.8.10",
|
||||
"clsx": "2.1.1",
|
||||
"eslint": "^9.18.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-svelte": "^3.0.0",
|
||||
"globals": "^16.0.0",
|
||||
"mode-watcher": "^1.0.6",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-svelte": "^3.3.3",
|
||||
"sass-embedded": "1.89.2",
|
||||
"svelte": "5.34.8",
|
||||
"svelte-check": "4.2.2",
|
||||
"bits-ui": "^1.4.7",
|
||||
"clsx": "^2.1.1",
|
||||
"eslint": "^9.35.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-svelte": "^3.12.2",
|
||||
"globals": "^17.0.0",
|
||||
"mode-watcher": "^1.1.0",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"sass-embedded": "^1.92.1",
|
||||
"svelte": "^5.55.3",
|
||||
"svelte-check": "^4.3.1",
|
||||
"svelte-sonner": "^1.0.5",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tailwind-variants": "^1.0.0",
|
||||
"tailwind-variants": "^3.1.0",
|
||||
"tailwindcss": "^4.1.7",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tslib": "2.8.1",
|
||||
"typescript": "5.8.3",
|
||||
"typescript-eslint": "^8.20.0",
|
||||
"vite": "7.0.0",
|
||||
"vite-plugin-devtools-json": "^0.3.0"
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^6.0.2",
|
||||
"typescript-eslint": "^8.42.0",
|
||||
"vite": "^8.0.8",
|
||||
"vite-plugin-devtools-json": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,19 +3,26 @@ import path from 'path';
|
||||
import * as toml from '@iarna/toml';
|
||||
import { cwd } from 'process';
|
||||
|
||||
const packageJsonPath = path.join(cwd(), 'package.json');
|
||||
const cargoTomlPath = path.join(cwd(), 'src-tauri', 'Cargo.toml');
|
||||
const tauriConfPath = path.join(cwd(), 'src-tauri', 'tauri.conf.json');
|
||||
|
||||
const cargoToml = fs.readFileSync(cargoTomlPath, 'utf8');
|
||||
const cargo = toml.parse(cargoToml) as Record<string, string>;
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
||||
const version = packageJson.version;
|
||||
if (!version) throw new Error('Could not find version in package.json');
|
||||
|
||||
const version = cargo.package['version'];
|
||||
if (!version) throw new Error('Could not find version in Cargo.toml');
|
||||
let cargoTomlContent = fs.readFileSync(cargoTomlPath, 'utf8');
|
||||
const cargo = toml.parse(cargoTomlContent) as { package: { version: string } };
|
||||
|
||||
if (cargo.package.version !== version) {
|
||||
cargoTomlContent = cargoTomlContent.replace(/version = ".*?"/, `version = "${version}"`);
|
||||
fs.writeFileSync(cargoTomlPath, cargoTomlContent);
|
||||
console.log(`✅ Synced Cargo.toml version to ${version}`);
|
||||
}
|
||||
|
||||
const tauriConf = JSON.parse(fs.readFileSync(tauriConfPath, 'utf8'));
|
||||
if (tauriConf.version !== version) {
|
||||
tauriConf.version = version;
|
||||
|
||||
fs.writeFileSync(tauriConfPath, JSON.stringify(tauriConf, null, 2));
|
||||
console.log(`✅ Synced tauri.conf.json version to ${version}`);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
[package]
|
||||
name = "ezpplauncher"
|
||||
version = "3.0.3"
|
||||
version = "3.2.0"
|
||||
description = "EZPPLauncher redefined."
|
||||
authors = ["HorizonCode"]
|
||||
edition = "2024"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[profile.dev]
|
||||
incremental = true # Compile your binary in smaller steps.
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1 # Allows LLVM to perform better optimization.
|
||||
lto = true # Enables link-time-optimizations.
|
||||
opt-level = "s" # Prioritizes small binary size. Use `3` if you prefer speed.
|
||||
panic = "abort" # Higher performance by disabling panic handlers.
|
||||
strip = true # Ensures debug symbols are removed.
|
||||
|
||||
[lib]
|
||||
# The `_lib` suffix may seem redundant but it is necessary
|
||||
# to make the lib name unique and wouldn't conflict with the bin name.
|
||||
@@ -15,33 +25,37 @@ name = "ezpplauncher_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.3.1", features = [] }
|
||||
tauri-build = { version = "2.5.6", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.7.0", features = [] }
|
||||
tauri-plugin-shell = "2.3.0"
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.141"
|
||||
tauri = { version = "2.10.3", features = ["protocol-asset"] }
|
||||
tauri-plugin-shell = "2.3.5"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.149"
|
||||
serde_repr = "0.1.20"
|
||||
tauri-plugin-dialog = "2.3.1"
|
||||
tauri-plugin-fs = "2.4.1"
|
||||
tauri-plugin-dialog = "2.7.0"
|
||||
tauri-plugin-fs = "2.5.0"
|
||||
hardware-id = "0.3.0"
|
||||
tauri-plugin-cors-fetch = "4.1.0"
|
||||
sysinfo = "0.36.1"
|
||||
reqwest = { version = "0.12.22", features = ["json", "stream"] }
|
||||
tauri-plugin-cors-fetch = "5.0.0"
|
||||
sysinfo = "0.38.4"
|
||||
reqwest = { version = "0.13.2", features = ["json", "stream", "query"] }
|
||||
md5 = "0.8.0"
|
||||
tokio = { version = "1.46.1", features = ["full"] }
|
||||
open = "5.3.2"
|
||||
windows-sys = "0.60.2"
|
||||
discord-rich-presence = "0.2.5"
|
||||
once_cell = "1.21.3"
|
||||
tokio = { version = "1.52.1", features = ["full"] }
|
||||
open = "5.3.4"
|
||||
discord-rich-presence = "1.1.0"
|
||||
once_cell = "1.21.4"
|
||||
futures-util = "0.3.32"
|
||||
byteorder = "1.5.0"
|
||||
anyhow = "1.0.102"
|
||||
url = "2"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winreg = "0.55.0"
|
||||
winreg = "0.56.0"
|
||||
winapi = { version = "0.3", features = ["winuser", "wincrypt", "memoryapi", "winbase", "dpapi"] }
|
||||
base64 = "0.22.1"
|
||||
widestring = "1.0"
|
||||
widestring = "1.2.1"
|
||||
windows-sys = "0.61.2"
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-single-instance = "2.3.2"
|
||||
tauri-plugin-single-instance = "2.4.1"
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"windows": ["main"],
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"shell:allow-open",
|
||||
@@ -19,58 +21,128 @@
|
||||
{
|
||||
"identifier": "fs:allow-read",
|
||||
"allow": [
|
||||
{ "path": "$HOME/.ezpplauncher" },
|
||||
{ "path": "$HOME/.ezpplauncher/*" },
|
||||
{ "path": "$HOME/.ezpplauncher/**/*" }
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/*"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/**/*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write",
|
||||
"allow": [
|
||||
{ "path": "$HOME/.ezpplauncher" },
|
||||
{ "path": "$HOME/.ezpplauncher/*" },
|
||||
{ "path": "$HOME/.ezpplauncher/**/*" }
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/*"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/**/*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-exists",
|
||||
"allow": [
|
||||
{ "path": "$HOME/.ezpplauncher" },
|
||||
{ "path": "$HOME/.ezpplauncher/*" },
|
||||
{ "path": "$HOME/.ezpplauncher/**/*" }
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/*"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/**/*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-file",
|
||||
"allow": [
|
||||
{ "path": "$HOME/.ezpplauncher" },
|
||||
{ "path": "$HOME/.ezpplauncher/*" },
|
||||
{ "path": "$HOME/.ezpplauncher/**/*" }
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/*"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/**/*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-write-file",
|
||||
"allow": [
|
||||
{ "path": "$HOME/.ezpplauncher" },
|
||||
{ "path": "$HOME/.ezpplauncher/*" },
|
||||
{ "path": "$HOME/.ezpplauncher/**/*" }
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/*"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/**/*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-text-file",
|
||||
"allow": [
|
||||
{ "path": "$HOME/.ezpplauncher" },
|
||||
{ "path": "$HOME/.ezpplauncher/*" },
|
||||
{ "path": "$HOME/.ezpplauncher/**/*" }
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/*"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/**/*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-mkdir",
|
||||
"allow": [
|
||||
{ "path": "$HOME/.ezpplauncher" },
|
||||
{ "path": "$HOME/.ezpplauncher/*" },
|
||||
{ "path": "$HOME/.ezpplauncher/**/*" }
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/*"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/**/*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-read-dir",
|
||||
"allow": [
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/*"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/**/*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "fs:allow-remove",
|
||||
"allow": [
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/*"
|
||||
},
|
||||
{
|
||||
"path": "$HOME/.ezpplauncher/**/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.6 KiB |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#fff</color>
|
||||
</resources>
|
||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 357 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 24 KiB |
@@ -0,0 +1,6 @@
|
||||
!macro NSIS_HOOK_POSTINSTALL
|
||||
${If} $PassiveMode = 1
|
||||
${OrIf} ${Silent}
|
||||
Exec '"$INSTDIR\${MAINBINARYNAME}.exe"'
|
||||
${EndIf}
|
||||
!macroend
|
||||
@@ -6,11 +6,14 @@ use std::path::PathBuf;
|
||||
use sysinfo::System;
|
||||
use tauri::AppHandle;
|
||||
use tauri::Emitter;
|
||||
use tauri::Manager;
|
||||
use tokio::fs;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::process::Command;
|
||||
use tokio::time::{Duration, sleep};
|
||||
|
||||
use crate::OpenedUrls;
|
||||
use crate::osudb::parse_osudb;
|
||||
use crate::presence;
|
||||
use crate::utils::{
|
||||
check_folder_completeness, encrypt_password, get_osu_config, get_osu_user_config,
|
||||
@@ -18,6 +21,11 @@ use crate::utils::{
|
||||
set_osu_config_vals, set_osu_user_config_vals,
|
||||
};
|
||||
|
||||
#[tauri::command]
|
||||
pub fn opened_urls(app: tauri::AppHandle) -> Vec<PathBuf> {
|
||||
app.state::<OpenedUrls>().0.lock().unwrap().clone()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_launcher_version() -> String {
|
||||
env!("CARGO_PKG_VERSION").to_string()
|
||||
@@ -55,17 +63,11 @@ pub fn valid_osu_folder(folder: String) -> bool {
|
||||
"scores.db",
|
||||
];
|
||||
|
||||
let folder_files: Vec<&str> = osu_folder_files.iter().map(|&s| s).collect();
|
||||
if folder_files.iter().any(|&file| file == "osu!.exe") == false {
|
||||
let path = PathBuf::from(folder);
|
||||
if !path.join("osu!.exe").exists() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let path = PathBuf::from(folder);
|
||||
let match_percentage = check_folder_completeness(path, &osu_folder_files) >= 70.0;
|
||||
if match_percentage {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
check_folder_completeness(path, &osu_folder_files) >= 70.0
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
@@ -82,10 +84,10 @@ pub fn find_osu_installation() -> Option<String> {
|
||||
|
||||
let hklm_registry_paths = ["SOFTWARE\\Classes\\osu\\DefaultIcon"];
|
||||
|
||||
let hkcr_registry_paths = [
|
||||
"osustable.File.osk\\DefaultIcon",
|
||||
"osustable.File.osr\\DefaultIcon",
|
||||
"osustable.File.osz\\DefaultIcon",
|
||||
let hkcu_registry_paths = [
|
||||
"Software\\Classes\\osustable.File.osk\\DefaultIcon",
|
||||
"Software\\Classes\\osustable.File.osr\\DefaultIcon",
|
||||
"Software\\Classes\\osustable.File.osz\\DefaultIcon",
|
||||
];
|
||||
|
||||
let osu_folder_files = [
|
||||
@@ -134,10 +136,10 @@ pub fn find_osu_installation() -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
let hkcr = RegKey::predef(HKEY_CLASSES_ROOT);
|
||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||
|
||||
for reg_path in &hkcr_registry_paths {
|
||||
if let Ok(subkey) = hkcr.open_subkey_with_flags(reg_path, KEY_READ | KEY_WOW64_32KEY) {
|
||||
for reg_path in &hkcu_registry_paths {
|
||||
if let Ok(subkey) = hkcu.open_subkey_with_flags(reg_path, KEY_READ | KEY_WOW64_32KEY) {
|
||||
let value_names = [""];
|
||||
for value_name in &value_names {
|
||||
if let Ok(value) = subkey.get_value::<String, _>(value_name) {
|
||||
@@ -159,53 +161,108 @@ pub fn find_osu_installation() -> Option<String> {
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_beatmapsets_count(folder: String) -> Option<u64> {
|
||||
pub async fn get_beatmapsets_count(folder: String) -> Option<u64> {
|
||||
let path = PathBuf::from(folder);
|
||||
let osu_user_config = get_osu_user_config(path.clone());
|
||||
let songs_path = osu_user_config
|
||||
.and_then(|config| config.get("Songs").cloned())
|
||||
.unwrap_or_else(|| path.join("Songs").to_string_lossy().into_owned());
|
||||
let songs_folder = PathBuf::from(songs_path);
|
||||
|
||||
if !songs_folder.exists() {
|
||||
return None;
|
||||
let osu_db_path = path.join("osu!.db");
|
||||
if !osu_db_path.exists() {
|
||||
return Some(0);
|
||||
}
|
||||
let osu_db_bytes = fs::read(osu_db_path).await.ok()?;
|
||||
let osu_db = parse_osudb(osu_db_bytes).ok()?;
|
||||
let beatmap_sets = osu_db
|
||||
.beatmaps
|
||||
.iter()
|
||||
.map(|b| b.beatmapset_id)
|
||||
.collect::<HashSet<_>>()
|
||||
.len();
|
||||
Some(beatmap_sets as u64)
|
||||
}
|
||||
|
||||
let mut count = 0;
|
||||
if let Ok(entries) = std::fs::read_dir(songs_folder) {
|
||||
for entry in entries.flatten() {
|
||||
if entry.file_type().map_or(false, |ft| ft.is_dir()) {
|
||||
let dir_path = entry.path();
|
||||
if let Ok(files) = std::fs::read_dir(&dir_path) {
|
||||
for file in files.flatten() {
|
||||
if file.path().extension().map_or(false, |ext| ext == "osu") {
|
||||
count += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Some(count);
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SkinInfo {
|
||||
pub name: String,
|
||||
pub author: Option<String>,
|
||||
pub modified: u64,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_skins_count(folder: String) -> Option<u64> {
|
||||
let path = PathBuf::from(folder);
|
||||
let skins_folder = path.join("Skins");
|
||||
pub async fn get_skins(folder: String) -> Option<Vec<SkinInfo>> {
|
||||
use std::path::PathBuf;
|
||||
use std::time::UNIX_EPOCH;
|
||||
use tokio::fs;
|
||||
|
||||
let skins_folder = PathBuf::from(folder).join("Skins");
|
||||
|
||||
if !skins_folder.exists() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut entries = fs::read_dir(skins_folder).await.ok()?;
|
||||
|
||||
let mut skins = Vec::new();
|
||||
|
||||
while let Some(entry) = entries.next_entry().await.ok()? {
|
||||
if !entry.file_type().await.ok()?.is_dir() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let dir_path = entry.path();
|
||||
let skin_ini = dir_path.join("skin.ini");
|
||||
|
||||
if !skin_ini.exists() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = entry.file_name().to_string_lossy().to_string();
|
||||
|
||||
let author = fs::read_to_string(&skin_ini)
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|content| {
|
||||
content.lines().find_map(|line| {
|
||||
let (key, value) = line.split_once(':')?;
|
||||
key.trim()
|
||||
.eq_ignore_ascii_case("Author")
|
||||
.then(|| value.trim().to_string())
|
||||
})
|
||||
});
|
||||
|
||||
let modified = entry
|
||||
.metadata()
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|m| m.modified().ok())
|
||||
.and_then(|t| t.duration_since(UNIX_EPOCH).ok())
|
||||
.map(|d| d.as_secs())
|
||||
.unwrap_or(0);
|
||||
|
||||
skins.push(SkinInfo {
|
||||
name,
|
||||
author,
|
||||
modified,
|
||||
});
|
||||
}
|
||||
|
||||
Some(skins)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_skins_count(folder: String) -> Option<u64> {
|
||||
let path = PathBuf::from(folder);
|
||||
let skins_folder = path.join("Skins");
|
||||
|
||||
if !skins_folder.exists() {
|
||||
return Some(0);
|
||||
}
|
||||
|
||||
let mut count = 0;
|
||||
if let Ok(entries) = std::fs::read_dir(skins_folder) {
|
||||
for entry in entries.flatten() {
|
||||
if entry.file_type().map_or(false, |ft| ft.is_dir()) {
|
||||
if let Ok(mut entries) = fs::read_dir(skins_folder).await {
|
||||
while let Ok(Some(entry)) = entries.next_entry().await {
|
||||
if entry.file_type().await.map_or(false, |ft| ft.is_dir()) {
|
||||
let dir_path = entry.path();
|
||||
if let Ok(files) = std::fs::read_dir(&dir_path) {
|
||||
for file in files.flatten() {
|
||||
if let Ok(mut files) = fs::read_dir(&dir_path).await {
|
||||
while let Ok(Some(file)) = files.next_entry().await {
|
||||
if file.path().extension().map_or(false, |ext| ext == "ini") {
|
||||
count += 1;
|
||||
break;
|
||||
@@ -221,28 +278,28 @@ pub fn get_skins_count(folder: String) -> Option<u64> {
|
||||
#[tauri::command]
|
||||
pub fn get_osu_skin(folder: String) -> String {
|
||||
let path = PathBuf::from(folder);
|
||||
let osu_user_config = get_osu_user_config(path.clone());
|
||||
return osu_user_config
|
||||
let osu_user_config = get_osu_user_config(path);
|
||||
osu_user_config
|
||||
.and_then(|config| config.get("Skin").cloned())
|
||||
.unwrap_or_else(|| "Default".to_string());
|
||||
.unwrap_or_else(|| "Default".to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_osu_version(folder: String) -> String {
|
||||
let path = PathBuf::from(folder);
|
||||
let osu_user_config = get_osu_user_config(path.clone());
|
||||
return osu_user_config
|
||||
let osu_user_config = get_osu_user_config(path);
|
||||
osu_user_config
|
||||
.and_then(|config| config.get("LastVersion").cloned())
|
||||
.unwrap_or_else(|| "failed".to_string());
|
||||
.unwrap_or_else(|| "failed".to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_osu_release_stream(folder: String) -> String {
|
||||
let path = PathBuf::from(folder);
|
||||
let osu_config = get_osu_config(path.clone());
|
||||
return osu_config
|
||||
let osu_config = get_osu_config(path);
|
||||
osu_config
|
||||
.and_then(|config| config.get("_ReleaseStream").cloned())
|
||||
.unwrap_or_else(|| "Stable40".to_string());
|
||||
.unwrap_or_else(|| "Stable40".to_string())
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
@@ -260,10 +317,7 @@ pub fn set_osu_user_config_values(
|
||||
.iter()
|
||||
.map(|entry| (entry.key.as_str(), Some(entry.value.as_str())))
|
||||
.collect();
|
||||
match set_osu_user_config_vals(&osu_folder_path, &converted) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(_) => Ok(false),
|
||||
}
|
||||
Ok(set_osu_user_config_vals(&osu_folder_path, &converted).is_ok())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -275,22 +329,16 @@ pub fn set_osu_config_values(
|
||||
.iter()
|
||||
.map(|entry| (entry.key.as_str(), Some(entry.value.as_str())))
|
||||
.collect();
|
||||
match set_osu_config_vals(&osu_folder_path, &converted) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(_) => Ok(false),
|
||||
}
|
||||
Ok(set_osu_config_vals(&osu_folder_path, &converted).is_ok())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn run_osu_updater(folder: String) -> Result<(), String> {
|
||||
#[cfg(windows)]
|
||||
const DETACHED_PROCESS: u32 = 0x00000008;
|
||||
#[cfg(windows)]
|
||||
const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
|
||||
|
||||
let mut updater_process = {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
const DETACHED_PROCESS: u32 = 0x00000008;
|
||||
const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
|
||||
let osu_exe_path = PathBuf::from(&folder).join("osu!.exe");
|
||||
Command::new(&osu_exe_path)
|
||||
.arg("-repair")
|
||||
@@ -367,9 +415,6 @@ pub async fn run_osu_updater(folder: String) -> Result<(), String> {
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn run_osu(folder: String, patch: bool) -> Result<(), String> {
|
||||
/* #[cfg(windows)]
|
||||
use std::os::windows::process::CommandExt; */
|
||||
|
||||
#[cfg(windows)]
|
||||
const DETACHED_PROCESS: u32 = 0x00000008;
|
||||
#[cfg(windows)]
|
||||
@@ -384,7 +429,7 @@ pub async fn run_osu(folder: String, patch: bool) -> Result<(), String> {
|
||||
.arg("ez-pp.farm")
|
||||
.creation_flags(DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to spawn updater: {}", e))?
|
||||
.map_err(|e| format!("Failed to spawn osu: {}", e))?
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
@@ -393,25 +438,52 @@ pub async fn run_osu(folder: String, patch: bool) -> Result<(), String> {
|
||||
.arg("--devserver")
|
||||
.arg("ez-pp.farm")
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to spawn updater: {}", e))?
|
||||
.map_err(|e| format!("Failed to spawn osu: {}", e))?
|
||||
}
|
||||
};
|
||||
|
||||
if patch {
|
||||
sleep(Duration::from_secs(3)).await;
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if patch {
|
||||
let patcher_exe_path = PathBuf::from(&folder)
|
||||
.join("EZPPLauncher")
|
||||
.join("patcher")
|
||||
.join("osu!.patcher.exe");
|
||||
|
||||
let patcher_exe_path = PathBuf::from(&folder)
|
||||
.join("EZPPLauncher")
|
||||
.join("patcher")
|
||||
.join("osu!.patcher.exe");
|
||||
if patcher_exe_path.exists() {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let mut sys = System::new_all();
|
||||
|
||||
if patcher_exe_path.exists() {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let _ = Command::new(&patcher_exe_path)
|
||||
.creation_flags(DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to run patcher: {e}"))?;
|
||||
loop {
|
||||
sys.refresh_processes(sysinfo::ProcessesToUpdate::All, true);
|
||||
|
||||
let mut found = false;
|
||||
|
||||
for (_pid, process) in sys.processes() {
|
||||
if process.name() == "osu!.exe" {
|
||||
let pid = process.pid();
|
||||
let title = get_window_title_by_pid(pid);
|
||||
|
||||
if !title.is_empty() && !title.contains("updater") {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
}
|
||||
|
||||
let _ = Command::new(&patcher_exe_path)
|
||||
.creation_flags(DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to run patcher: {e}"))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -556,7 +628,6 @@ pub async fn download_ezpp_launcher_update_files(
|
||||
#[serde(tag = "type", content = "details")]
|
||||
pub enum ReplaceUIError {
|
||||
FileNotFound(String),
|
||||
PermissionDenied(String),
|
||||
IoError(String),
|
||||
}
|
||||
|
||||
@@ -565,44 +636,169 @@ pub fn replace_ui_files(folder: String, revert: bool) -> Result<(), ReplaceUIErr
|
||||
let osu_path = PathBuf::from(folder);
|
||||
let ezpp_ui = osu_path.join("EZPPLauncher").join("ezpp!ui.dll");
|
||||
let osu_ui = osu_path.join("osu!ui.dll");
|
||||
let ezpp_seasonal = osu_path.join("EZPPLauncher").join("ezpp!seasonal.dll");
|
||||
let osu_seasonal = osu_path.join("osu!seasonal.dll");
|
||||
let ezpp_gameplay = osu_path.join("EZPPLauncher").join("ezpp!gameplay.dll");
|
||||
let osu_gameplay = osu_path.join("osu!gameplay.dll");
|
||||
|
||||
let osu_ui_bak = osu_path.join("osu!ui.dll.bak");
|
||||
let osu_seasonal_bak = osu_path.join("osu!seasonal.dll.bak");
|
||||
let osu_gameplay_bak = osu_path.join("osu!gameplay.dll.bak");
|
||||
|
||||
let try_rename = |from: &PathBuf, to: &PathBuf| -> Result<(), ReplaceUIError> {
|
||||
if !from.exists() {
|
||||
return Err(ReplaceUIError::FileNotFound(from.display().to_string()));
|
||||
let temp_file = osu_path.join(".ezpplauncher_files");
|
||||
|
||||
let copy_file = |source: &PathBuf, dest: &PathBuf, name: &str| -> Result<(), ReplaceUIError> {
|
||||
if !source.exists() {
|
||||
return Err(ReplaceUIError::FileNotFound(source.display().to_string()));
|
||||
}
|
||||
std::fs::rename(from, to).map_err(|e| match e.kind() {
|
||||
std::io::ErrorKind::NotFound => {
|
||||
ReplaceUIError::FileNotFound(from.display().to_string())
|
||||
}
|
||||
std::io::ErrorKind::PermissionDenied => {
|
||||
ReplaceUIError::PermissionDenied(from.display().to_string())
|
||||
}
|
||||
_ => ReplaceUIError::IoError(e.to_string()),
|
||||
})
|
||||
|
||||
if dest.exists() {
|
||||
std::fs::remove_file(dest).map_err(|e| {
|
||||
ReplaceUIError::IoError(format!("Failed to remove {}: {}", name, e))
|
||||
})?;
|
||||
}
|
||||
|
||||
std::fs::copy(source, dest)
|
||||
.map_err(|e| ReplaceUIError::IoError(format!("Failed to copy {}: {}", name, e)))?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let restore_backup =
|
||||
|bak: &PathBuf, dest: &PathBuf, name: &str| -> Result<(), ReplaceUIError> {
|
||||
if bak.exists() {
|
||||
if dest.exists() {
|
||||
std::fs::remove_file(dest).map_err(|e| {
|
||||
ReplaceUIError::IoError(format!("Failed to remove {}: {}", name, e))
|
||||
})?;
|
||||
}
|
||||
std::fs::rename(bak, dest).map_err(|e| {
|
||||
ReplaceUIError::IoError(format!("Failed to rename {} from backup: {}", name, e))
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
|
||||
if !revert {
|
||||
try_rename(&osu_ui, &osu_ui_bak)?;
|
||||
try_rename(&ezpp_ui, &osu_ui)?;
|
||||
if osu_ui.exists() && !osu_ui_bak.exists() {
|
||||
std::fs::rename(&osu_ui, &osu_ui_bak).map_err(|e| {
|
||||
ReplaceUIError::IoError(format!("Failed to backup osu!ui.dll: {}", e))
|
||||
})?;
|
||||
}
|
||||
if osu_seasonal.exists() && !osu_seasonal_bak.exists() {
|
||||
std::fs::rename(&osu_seasonal, &osu_seasonal_bak).map_err(|e| {
|
||||
ReplaceUIError::IoError(format!("Failed to backup osu!seasonal.dll: {}", e))
|
||||
})?;
|
||||
}
|
||||
if osu_gameplay.exists() && !osu_gameplay_bak.exists() {
|
||||
std::fs::rename(&osu_gameplay, &osu_gameplay_bak).map_err(|e| {
|
||||
ReplaceUIError::IoError(format!("Failed to backup osu!gameplay.dll: {}", e))
|
||||
})?;
|
||||
}
|
||||
|
||||
try_rename(&osu_gameplay, &osu_gameplay_bak)?;
|
||||
try_rename(&ezpp_gameplay, &osu_gameplay)?;
|
||||
copy_file(&ezpp_ui, &osu_ui, "osu!ui.dll")?;
|
||||
copy_file(&ezpp_seasonal, &osu_seasonal, "osu!seasonal.dll")?;
|
||||
copy_file(&ezpp_gameplay, &osu_gameplay, "osu!gameplay.dll")?;
|
||||
|
||||
std::fs::write(&temp_file, b"1")
|
||||
.map_err(|e| ReplaceUIError::IoError(format!("Failed to write marker file: {}", e)))?;
|
||||
} else {
|
||||
try_rename(&osu_ui, &ezpp_ui)?;
|
||||
try_rename(&osu_ui_bak, &osu_ui)?;
|
||||
restore_backup(&osu_ui_bak, &osu_ui, "osu!ui.dll")?;
|
||||
restore_backup(&osu_seasonal_bak, &osu_seasonal, "osu!seasonal.dll")?;
|
||||
restore_backup(&osu_gameplay_bak, &osu_gameplay, "osu!gameplay.dll")?;
|
||||
|
||||
try_rename(&osu_gameplay, &ezpp_gameplay)?;
|
||||
try_rename(&osu_gameplay_bak, &osu_gameplay)?;
|
||||
if osu_ui.exists() && osu_seasonal.exists() && osu_gameplay.exists() {
|
||||
std::fs::remove_file(&temp_file).map_err(|e| {
|
||||
ReplaceUIError::IoError(format!("Failed to remove marker file: {}", e))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(tag = "type", content = "details")]
|
||||
pub enum CorruptionCheckError {
|
||||
IoError(String),
|
||||
FileNotFound(String),
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn check_for_corruption(folder: String) -> Result<bool, CorruptionCheckError> {
|
||||
let osu_path = PathBuf::from(folder);
|
||||
let osu_ui = osu_path.join("osu!ui.dll");
|
||||
let osu_gameplay = osu_path.join("osu!gameplay.dll");
|
||||
let osu_seasonal = osu_path.join("osu!seasonal.dll");
|
||||
|
||||
let osu_ui_bak = osu_path.join("osu!ui.dll.bak");
|
||||
let osu_gameplay_bak = osu_path.join("osu!gameplay.dll.bak");
|
||||
let osu_seasonal_bak = osu_path.join("osu!seasonal.dll.bak");
|
||||
|
||||
let temp_file = osu_path.join(".ezpplauncher_files");
|
||||
|
||||
if temp_file.exists() {
|
||||
if osu_ui_bak.exists() {
|
||||
if osu_ui.exists() {
|
||||
fs::remove_file(&osu_ui).await.map_err(|e| {
|
||||
CorruptionCheckError::IoError(format!("Failed to remove osu!ui.dll: {}", e))
|
||||
})?;
|
||||
}
|
||||
|
||||
fs::rename(&osu_ui_bak, &osu_ui).await.map_err(|e| {
|
||||
CorruptionCheckError::IoError(format!(
|
||||
"Failed to restore osu!ui.dll from backup: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
if osu_gameplay_bak.exists() {
|
||||
if osu_gameplay.exists() {
|
||||
fs::remove_file(&osu_gameplay).await.map_err(|e| {
|
||||
CorruptionCheckError::IoError(format!(
|
||||
"Failed to remove osu!gameplay.dll: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
|
||||
fs::rename(&osu_gameplay_bak, &osu_gameplay)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
CorruptionCheckError::IoError(format!(
|
||||
"Failed to restore osu!gameplay.dll from backup: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
if osu_seasonal_bak.exists() {
|
||||
if osu_seasonal.exists() {
|
||||
fs::remove_file(&osu_seasonal).await.map_err(|e| {
|
||||
CorruptionCheckError::IoError(format!(
|
||||
"Failed to remove osu!seasonal.dll: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
|
||||
fs::rename(&osu_seasonal_bak, &osu_seasonal)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
CorruptionCheckError::IoError(format!(
|
||||
"Failed to restore osu!seasonal.dll from backup: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
if !osu_ui.exists() || !osu_gameplay.exists() || !osu_seasonal.exists() {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn is_osu_running() -> bool {
|
||||
let mut sys = System::new_all();
|
||||
@@ -632,35 +828,6 @@ pub fn get_platform() -> String {
|
||||
std::env::consts::OS.to_string()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn check_for_corruption(folder: String) -> Result<bool, String> {
|
||||
let osu_path = PathBuf::from(folder);
|
||||
let osu_ui = osu_path.join("osu!ui.dll");
|
||||
let osu_gameplay = osu_path.join("osu!gameplay.dll");
|
||||
|
||||
let osu_ui_bak = osu_path.join("osu!ui.dll.bak");
|
||||
let osu_gameplay_bak = osu_path.join("osu!gameplay.dll.bak");
|
||||
|
||||
let required_files = [&osu_ui, &osu_gameplay];
|
||||
|
||||
for file in &required_files {
|
||||
if !file.exists() {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
let bak_files = [&osu_ui_bak, &osu_gameplay_bak];
|
||||
for bak in &bak_files {
|
||||
if bak.exists() {
|
||||
if let Err(e) = fs::remove_file(bak).await {
|
||||
return Err(format!("Failed to delete {}: {}", bak.display(), e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn presence_connect() -> bool {
|
||||
presence::connect().await
|
||||
@@ -722,10 +889,81 @@ pub async fn has_net8() -> bool {
|
||||
|
||||
#[tauri::command]
|
||||
pub fn encrypt_string(string: String, entropy: String) -> String {
|
||||
let encrypted = encrypt_password(&string, &entropy);
|
||||
|
||||
match encrypted {
|
||||
Ok(encrypted_vec) => encrypted_vec,
|
||||
Err(_) => string,
|
||||
}
|
||||
encrypt_password(&string, &entropy).unwrap_or(string)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn download_ezpp_launcher_update(app: AppHandle, url: String) -> Result<(), String> {
|
||||
let client = Client::new();
|
||||
|
||||
let mut response = client.get(&url).send().await.map_err(|e| e.to_string())?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(format!("Failed to download update: {}", response.status()));
|
||||
}
|
||||
|
||||
let temp_dir = app.path().temp_dir().expect("Failed to get temp directory");
|
||||
let file_path = temp_dir.join("ezpplauncher_update.exe");
|
||||
|
||||
let mut file_out = fs::File::create(&file_path)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
let mut downloaded = 0u64;
|
||||
let size = response
|
||||
.content_length()
|
||||
.ok_or("Failed to get content length")? as usize;
|
||||
|
||||
while let Some(chunk) = response.chunk().await.map_err(|e| e.to_string())? {
|
||||
downloaded += chunk.len() as u64;
|
||||
file_out
|
||||
.write_all(&chunk)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
app.emit(
|
||||
"download-progress",
|
||||
UpdateStatus {
|
||||
file_name: "Update".to_string(),
|
||||
downloaded,
|
||||
size,
|
||||
progress: ((downloaded as f64 / size as f64 * 100.0) * 100.0).trunc() / 100.0,
|
||||
},
|
||||
)
|
||||
.unwrap_or_default();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[tauri::command]
|
||||
pub async fn install_ezpp_launcher_update(app: AppHandle) -> Result<(), String> {
|
||||
let temp_dir = app.path().temp_dir().expect("Failed to get temp directory");
|
||||
let file_path = temp_dir.join("ezpplauncher_update.exe");
|
||||
if !file_path.exists() {
|
||||
return Err("Update file does not exist".to_string());
|
||||
}
|
||||
|
||||
// run this app detached and exit
|
||||
|
||||
const DETACHED_PROCESS: u32 = 0x00000008;
|
||||
const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
|
||||
|
||||
Command::new(&file_path)
|
||||
.arg("/S")
|
||||
.creation_flags(DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to spawn updater: {}", e))?;
|
||||
|
||||
sleep(Duration::from_millis(250)).await;
|
||||
|
||||
app.exit(0x0100);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[tauri::command]
|
||||
pub async fn install_ezpp_launcher_update(_app: AppHandle) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Mutex;
|
||||
use tauri::Manager;
|
||||
|
||||
pub mod commands;
|
||||
pub mod osudb;
|
||||
pub mod presence;
|
||||
pub mod utils;
|
||||
use crate::commands::{
|
||||
check_for_corruption, download_ezpp_launcher_update_files, encrypt_string, exit,
|
||||
find_osu_installation, get_beatmapsets_count, get_ezpp_launcher_update_files, get_hwid,
|
||||
get_launcher_version, get_osu_release_stream, get_osu_skin, get_osu_version, get_platform,
|
||||
get_skins_count, has_net8, has_osuwinello, has_wmctrl, is_osu_running, open_url_in_browser,
|
||||
presence_connect, presence_disconnect, presence_is_connected, presence_update_status,
|
||||
presence_update_user, replace_ui_files, run_osu, run_osu_updater, set_osu_config_values,
|
||||
set_osu_user_config_values, valid_osu_folder,
|
||||
check_for_corruption, download_ezpp_launcher_update, download_ezpp_launcher_update_files,
|
||||
encrypt_string, exit, find_osu_installation, get_beatmapsets_count,
|
||||
get_ezpp_launcher_update_files, get_hwid, get_launcher_version, get_osu_release_stream,
|
||||
get_osu_skin, get_osu_version, get_platform, get_skins, get_skins_count, has_net8,
|
||||
has_osuwinello, has_wmctrl, install_ezpp_launcher_update, is_osu_running, open_url_in_browser,
|
||||
opened_urls, presence_connect, presence_disconnect, presence_is_connected,
|
||||
presence_update_status, presence_update_user, replace_ui_files, run_osu, run_osu_updater,
|
||||
set_osu_config_values, set_osu_user_config_values, valid_osu_folder,
|
||||
};
|
||||
|
||||
struct OpenedUrls(Mutex<Vec<PathBuf>>);
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
#[cfg(target_os = "linux")]
|
||||
unsafe {
|
||||
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||
// std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||
}
|
||||
|
||||
let mut builder = tauri::Builder::default();
|
||||
@@ -31,11 +37,44 @@ pub fn run() {
|
||||
}
|
||||
|
||||
let app = builder
|
||||
.manage(OpenedUrls(Mutex::new(vec![])))
|
||||
.setup(|app| {
|
||||
let args = std::env::args().collect::<Vec<_>>();
|
||||
if args.len() > 1 {
|
||||
let mut files = Vec::new();
|
||||
|
||||
for maybe_file in args.iter().skip(1) {
|
||||
if maybe_file.starts_with("-") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Ok(url) = url::Url::parse(&maybe_file) {
|
||||
if let Ok(path) = url.to_file_path() {
|
||||
if path.extension().and_then(|str| str.to_str())
|
||||
== Some("ezpplauncher-theme")
|
||||
{
|
||||
files.push(path);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let maybe_file_path = PathBuf::from(maybe_file);
|
||||
if maybe_file_path.extension().and_then(|str| str.to_str()) == Some("ezpplauncher-theme") {
|
||||
files.push(maybe_file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.state::<OpenedUrls>().0.lock().unwrap().extend(files);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
opened_urls,
|
||||
get_hwid,
|
||||
find_osu_installation,
|
||||
valid_osu_folder,
|
||||
get_beatmapsets_count,
|
||||
get_skins,
|
||||
get_skins_count,
|
||||
get_osu_version,
|
||||
get_osu_release_stream,
|
||||
@@ -61,7 +100,9 @@ pub fn run() {
|
||||
has_osuwinello,
|
||||
has_wmctrl,
|
||||
has_net8,
|
||||
encrypt_string
|
||||
encrypt_string,
|
||||
download_ezpp_launcher_update,
|
||||
install_ezpp_launcher_update
|
||||
])
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
|
||||
@@ -0,0 +1,370 @@
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
use anyhow::{Result, anyhow};
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct OsuReader {
|
||||
cursor: Cursor<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl OsuReader {
|
||||
pub fn new(data: Vec<u8>) -> Self {
|
||||
Self {
|
||||
cursor: Cursor::new(data),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_i16(&mut self) -> Result<i16> {
|
||||
Ok(self.cursor.read_i16::<LittleEndian>()?)
|
||||
}
|
||||
|
||||
fn read_i32(&mut self) -> Result<i32> {
|
||||
Ok(self.cursor.read_i32::<LittleEndian>()?)
|
||||
}
|
||||
|
||||
fn read_i64(&mut self) -> Result<i64> {
|
||||
Ok(self.cursor.read_i64::<LittleEndian>()?)
|
||||
}
|
||||
|
||||
fn read_u8(&mut self) -> Result<u8> {
|
||||
Ok(self.cursor.read_u8()?)
|
||||
}
|
||||
|
||||
fn read_f32(&mut self) -> Result<f32> {
|
||||
Ok(self.cursor.read_f32::<LittleEndian>()?)
|
||||
}
|
||||
|
||||
fn read_f64(&mut self) -> Result<f64> {
|
||||
Ok(self.cursor.read_f64::<LittleEndian>()?)
|
||||
}
|
||||
|
||||
fn read_bool(&mut self) -> Result<bool> {
|
||||
Ok(self.read_u8()? != 0)
|
||||
}
|
||||
|
||||
fn read_string(&mut self) -> Result<Option<String>> {
|
||||
let indicator = self.read_u8()?;
|
||||
|
||||
if indicator == 0 {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if indicator != 0x0B {
|
||||
return Err(anyhow!("Invalid osu string indicator"));
|
||||
}
|
||||
|
||||
let len = self.read_uleb128()? as usize;
|
||||
let mut buf = vec![0; len];
|
||||
self.cursor.read_exact(&mut buf)?;
|
||||
|
||||
Ok(Some(String::from_utf8(buf)?))
|
||||
}
|
||||
|
||||
fn read_uleb128(&mut self) -> Result<u64> {
|
||||
let mut result = 0;
|
||||
let mut shift = 0;
|
||||
|
||||
loop {
|
||||
let byte = self.read_u8()?;
|
||||
result |= ((byte & 0x7F) as u64) << shift;
|
||||
|
||||
if (byte & 0x80) == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
shift += 7;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TimingPoint {
|
||||
pub bpm: f64,
|
||||
pub offset: f64,
|
||||
pub inherited: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Beatmap {
|
||||
pub artist_name: Option<String>,
|
||||
pub artist_unicode: Option<String>,
|
||||
pub song_title: Option<String>,
|
||||
pub song_title_unicode: Option<String>,
|
||||
pub creator: Option<String>,
|
||||
pub difficulty: Option<String>,
|
||||
pub audio: Option<String>,
|
||||
pub md5: Option<String>,
|
||||
pub osu_file_name: Option<String>,
|
||||
|
||||
pub ranked_status: u8,
|
||||
pub hitcircles: i16,
|
||||
pub slider_count: i16,
|
||||
pub spinner_count: i16,
|
||||
pub last_modification: i64,
|
||||
|
||||
pub approach_rate: f32,
|
||||
pub circle_size: f32,
|
||||
pub hp_drain: f32,
|
||||
pub overall_difficulty: f32,
|
||||
pub slider_velocity: f64,
|
||||
|
||||
pub difficulties: HashMap<i32, f64>,
|
||||
|
||||
pub drain_time: i32,
|
||||
pub total_time: i32,
|
||||
pub preview_offset: i32,
|
||||
|
||||
pub beatmap_id: i32,
|
||||
pub beatmapset_id: i32,
|
||||
pub thread_id: i32,
|
||||
|
||||
pub grade_standard: u8,
|
||||
pub grade_taiko: u8,
|
||||
pub grade_catch: u8,
|
||||
pub grade_mania: u8,
|
||||
|
||||
pub local_beatmap_offset: i16,
|
||||
pub stack_leniency: f32,
|
||||
|
||||
pub mode: u8,
|
||||
pub song_source: Option<String>,
|
||||
pub song_tags: Option<String>,
|
||||
|
||||
pub online_beatmap_offset: i16,
|
||||
pub title_font: Option<String>,
|
||||
|
||||
pub unplayed: bool,
|
||||
pub last_played: i64,
|
||||
pub osz2: bool,
|
||||
pub folder_name: Option<String>,
|
||||
pub last_checked_against_repository: i64,
|
||||
|
||||
pub ignore_sound: bool,
|
||||
pub ignore_skin: bool,
|
||||
pub disable_storyboard: bool,
|
||||
pub disable_video: bool,
|
||||
pub visual_override: bool,
|
||||
|
||||
pub last_modification_time: i32,
|
||||
pub mania_scroll_speed: u8,
|
||||
|
||||
pub timing_points: Vec<TimingPoint>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OsuDbData {
|
||||
pub osuver: i32,
|
||||
pub folder_count: i32,
|
||||
pub is_unlocked: bool,
|
||||
pub date_unlock_ticks: i64,
|
||||
pub username: Option<String>,
|
||||
pub beatmaps: Vec<Beatmap>,
|
||||
pub userperms: i32,
|
||||
}
|
||||
|
||||
//
|
||||
// =========================
|
||||
// PARSER
|
||||
// =========================
|
||||
//
|
||||
|
||||
pub fn parse_osudb(bytes: Vec<u8>) -> Result<OsuDbData> {
|
||||
let mut reader = OsuReader::new(bytes);
|
||||
|
||||
let osuver = reader.read_i32()?;
|
||||
let folder_count = reader.read_i32()?;
|
||||
let is_unlocked = reader.read_bool()?;
|
||||
let date_unlock_ticks = reader.read_i64()?;
|
||||
let username = reader.read_string()?;
|
||||
let beatmaps_count = reader.read_i32()?;
|
||||
|
||||
let mut beatmaps = Vec::new();
|
||||
|
||||
for _ in 0..beatmaps_count {
|
||||
if osuver < 20191107 {
|
||||
reader.read_i32()?; // entry size
|
||||
}
|
||||
|
||||
let artist_name = reader.read_string()?;
|
||||
let artist_unicode = reader.read_string()?;
|
||||
let song_title = reader.read_string()?;
|
||||
let song_title_unicode = reader.read_string()?;
|
||||
let creator = reader.read_string()?;
|
||||
let difficulty = reader.read_string()?;
|
||||
let audio = reader.read_string()?;
|
||||
let md5 = reader.read_string()?;
|
||||
let osu_file_name = reader.read_string()?;
|
||||
|
||||
let ranked_status = reader.read_u8()?;
|
||||
let hitcircles = reader.read_i16()?;
|
||||
let slider_count = reader.read_i16()?;
|
||||
let spinner_count = reader.read_i16()?;
|
||||
let last_modification = reader.read_i64()?;
|
||||
|
||||
let approach_rate = if osuver < 20140609 {
|
||||
reader.read_u8()? as f32
|
||||
} else {
|
||||
reader.read_f32()?
|
||||
};
|
||||
|
||||
let circle_size = if osuver < 20140609 {
|
||||
reader.read_u8()? as f32
|
||||
} else {
|
||||
reader.read_f32()?
|
||||
};
|
||||
|
||||
let hp_drain = if osuver < 20140609 {
|
||||
reader.read_u8()? as f32
|
||||
} else {
|
||||
reader.read_f32()?
|
||||
};
|
||||
|
||||
let overall_difficulty = if osuver < 20140609 {
|
||||
reader.read_u8()? as f32
|
||||
} else {
|
||||
reader.read_f32()?
|
||||
};
|
||||
|
||||
let slider_velocity = reader.read_f64()?;
|
||||
|
||||
let mut difficulties: HashMap<i32, f64> = HashMap::new();
|
||||
|
||||
if osuver >= 20140609 {
|
||||
for _ in 0..4 {
|
||||
let len = reader.read_i32()?;
|
||||
for _ in 0..len {
|
||||
reader.read_u8()?;
|
||||
let mode = reader.read_i32()?;
|
||||
reader.read_u8()?;
|
||||
let diff = if osuver > 20250107 {
|
||||
reader.read_f32()? as f64
|
||||
} else {
|
||||
reader.read_f64()?
|
||||
};
|
||||
|
||||
difficulties.insert(mode, diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let drain_time = reader.read_i32()?;
|
||||
let total_time = reader.read_i32()?;
|
||||
let preview_offset = reader.read_i32()?;
|
||||
|
||||
let timing_len = reader.read_i32()?;
|
||||
let mut timing_points = Vec::new();
|
||||
for _ in 0..timing_len {
|
||||
timing_points.push(TimingPoint {
|
||||
bpm: reader.read_f64()?,
|
||||
offset: reader.read_f64()?,
|
||||
inherited: reader.read_bool()?,
|
||||
});
|
||||
}
|
||||
|
||||
let beatmap_id = reader.read_i32()?;
|
||||
let beatmapset_id = reader.read_i32()?;
|
||||
let thread_id = reader.read_i32()?;
|
||||
|
||||
let grade_standard = reader.read_u8()?;
|
||||
let grade_taiko = reader.read_u8()?;
|
||||
let grade_catch = reader.read_u8()?;
|
||||
let grade_mania = reader.read_u8()?;
|
||||
|
||||
let local_beatmap_offset = reader.read_i16()?;
|
||||
let stack_leniency = reader.read_f32()?;
|
||||
|
||||
let mode = reader.read_u8()?;
|
||||
let song_source = reader.read_string()?;
|
||||
let song_tags = reader.read_string()?;
|
||||
|
||||
let online_beatmap_offset = reader.read_i16()?;
|
||||
let title_font = reader.read_string()?;
|
||||
|
||||
let unplayed = reader.read_bool()?;
|
||||
let last_played = reader.read_i64()?;
|
||||
let osz2 = reader.read_bool()?;
|
||||
let folder_name = reader.read_string()?;
|
||||
let last_checked_against_repository = reader.read_i64()?;
|
||||
|
||||
let ignore_sound = reader.read_bool()?;
|
||||
let ignore_skin = reader.read_bool()?;
|
||||
let disable_storyboard = reader.read_bool()?;
|
||||
let disable_video = reader.read_bool()?;
|
||||
let visual_override = reader.read_bool()?;
|
||||
|
||||
if osuver < 20140609 {
|
||||
reader.read_i16()?;
|
||||
}
|
||||
|
||||
let last_modification_time = reader.read_i32()?;
|
||||
let mania_scroll_speed = reader.read_u8()?;
|
||||
|
||||
beatmaps.push(Beatmap {
|
||||
artist_name,
|
||||
artist_unicode,
|
||||
song_title,
|
||||
song_title_unicode,
|
||||
creator,
|
||||
difficulty,
|
||||
audio,
|
||||
md5,
|
||||
osu_file_name,
|
||||
ranked_status,
|
||||
hitcircles,
|
||||
slider_count,
|
||||
spinner_count,
|
||||
last_modification,
|
||||
approach_rate,
|
||||
circle_size,
|
||||
hp_drain,
|
||||
overall_difficulty,
|
||||
slider_velocity,
|
||||
difficulties,
|
||||
drain_time,
|
||||
total_time,
|
||||
preview_offset,
|
||||
beatmap_id,
|
||||
beatmapset_id,
|
||||
thread_id,
|
||||
grade_standard,
|
||||
grade_taiko,
|
||||
grade_catch,
|
||||
grade_mania,
|
||||
local_beatmap_offset,
|
||||
stack_leniency,
|
||||
mode,
|
||||
song_source,
|
||||
song_tags,
|
||||
online_beatmap_offset,
|
||||
title_font,
|
||||
unplayed,
|
||||
last_played,
|
||||
osz2,
|
||||
folder_name,
|
||||
last_checked_against_repository,
|
||||
ignore_sound,
|
||||
ignore_skin,
|
||||
disable_storyboard,
|
||||
disable_video,
|
||||
visual_override,
|
||||
last_modification_time,
|
||||
mania_scroll_speed,
|
||||
timing_points,
|
||||
});
|
||||
}
|
||||
|
||||
let userperms = reader.read_i32()?;
|
||||
|
||||
Ok(OsuDbData {
|
||||
osuver,
|
||||
folder_count,
|
||||
is_unlocked,
|
||||
date_unlock_ticks,
|
||||
username,
|
||||
beatmaps,
|
||||
userperms,
|
||||
})
|
||||
}
|
||||
@@ -1,12 +1,18 @@
|
||||
use discord_rich_presence::{
|
||||
activity::{Activity, Assets, Button, Timestamps},
|
||||
DiscordIpc, DiscordIpcClient,
|
||||
activity::{Activity, Assets, Button, Timestamps},
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::Mutex as StdMutex;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use tokio::sync::{mpsc, oneshot};
|
||||
use tokio::time::{interval, Duration};
|
||||
use tokio::time::{Duration, interval};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PresenceButton {
|
||||
pub label: String,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PresenceData {
|
||||
@@ -16,6 +22,21 @@ pub struct PresenceData {
|
||||
pub large_image_text: String,
|
||||
pub small_image_key: Option<String>,
|
||||
pub small_image_text: Option<String>,
|
||||
pub dynamic_button: Option<PresenceButton>,
|
||||
}
|
||||
|
||||
impl Default for PresenceData {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
state: "Idle in Launcher...".to_string(),
|
||||
details: " ".to_string(),
|
||||
large_image_key: "ezppfarm".to_string(),
|
||||
large_image_text: "EZPPFarm".to_string(),
|
||||
small_image_key: None,
|
||||
small_image_text: None,
|
||||
dynamic_button: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -26,11 +47,19 @@ enum PresenceCommand {
|
||||
IsConnected(oneshot::Sender<bool>),
|
||||
}
|
||||
|
||||
enum ReconnectResult {
|
||||
Connected(DiscordIpcClient),
|
||||
Failed,
|
||||
}
|
||||
|
||||
struct PresenceActor {
|
||||
receiver: mpsc::Receiver<PresenceCommand>,
|
||||
reconnect_rx: mpsc::Receiver<ReconnectResult>,
|
||||
reconnect_tx: mpsc::Sender<ReconnectResult>,
|
||||
client: Option<DiscordIpcClient>,
|
||||
data: PresenceData,
|
||||
start_timestamp: i64,
|
||||
reconnecting: bool,
|
||||
}
|
||||
|
||||
impl PresenceActor {
|
||||
@@ -40,141 +69,183 @@ impl PresenceActor {
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
|
||||
let data = PresenceData {
|
||||
state: "Idle in Launcher...".to_string(),
|
||||
details: " ".to_string(),
|
||||
large_image_key: "ezppfarm".to_string(),
|
||||
large_image_text: "EZPPFarm".to_string(),
|
||||
small_image_key: None,
|
||||
small_image_text: None,
|
||||
};
|
||||
let (reconnect_tx, reconnect_rx) = mpsc::channel(1);
|
||||
|
||||
PresenceActor {
|
||||
Self {
|
||||
receiver,
|
||||
reconnect_rx,
|
||||
reconnect_tx,
|
||||
client: None,
|
||||
data,
|
||||
data: PresenceData::default(),
|
||||
start_timestamp: start,
|
||||
reconnecting: false,
|
||||
}
|
||||
}
|
||||
|
||||
async fn run(&mut self) {
|
||||
let mut update_interval = interval(Duration::from_millis(2500));
|
||||
let mut heartbeat = interval(Duration::from_secs(5));
|
||||
heartbeat.tick().await;
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
Some(cmd) = self.receiver.recv() => {
|
||||
match cmd {
|
||||
PresenceCommand::Connect(responder) => self.handle_connect(responder).await,
|
||||
PresenceCommand::Disconnect(responder) => {
|
||||
self.handle_disconnect(responder).await;
|
||||
},
|
||||
PresenceCommand::UpdateData(new_data) => {
|
||||
self.data = new_data;
|
||||
},
|
||||
PresenceCommand::IsConnected(responder) => {
|
||||
let _ = responder.send(self.client.is_some());
|
||||
PresenceCommand::Connect(resp) => self.cmd_connect(resp).await,
|
||||
PresenceCommand::Disconnect(resp) => self.cmd_disconnect(resp).await,
|
||||
PresenceCommand::UpdateData(data) => {
|
||||
self.data = data;
|
||||
self.push_presence().await;
|
||||
}
|
||||
PresenceCommand::IsConnected(resp) => {
|
||||
let _ = resp.send(self.client.is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = update_interval.tick() => {
|
||||
if self.client.is_some() {
|
||||
self.handle_update().await;
|
||||
|
||||
Some(result) = self.reconnect_rx.recv() => {
|
||||
self.reconnecting = false;
|
||||
match result {
|
||||
ReconnectResult::Connected(client) => {
|
||||
println!("Presence: reconnect succeeded.");
|
||||
self.client = Some(client);
|
||||
self.push_presence().await;
|
||||
}
|
||||
ReconnectResult::Failed => {
|
||||
eprintln!("Presence: all reconnect attempts exhausted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = heartbeat.tick() => {
|
||||
self.push_presence().await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_connect(&mut self, responder: oneshot::Sender<bool>) {
|
||||
async fn cmd_connect(&mut self, resp: oneshot::Sender<bool>) {
|
||||
if self.client.is_some() {
|
||||
let _ = responder.send(true);
|
||||
let _ = resp.send(true);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("Actor: Connecting to Discord...");
|
||||
match DiscordIpcClient::new("1032772293220384808").map_err(|e| e.to_string()) {
|
||||
Ok(mut new_client) => {
|
||||
if let Err(e) = new_client.connect().map_err(|e| e.to_string()) {
|
||||
eprintln!("Failed to connect to Discord: {:?}", e);
|
||||
let _ = responder.send(false);
|
||||
match try_connect_once() {
|
||||
Some(client) => {
|
||||
self.client = Some(client);
|
||||
self.reconnecting = false;
|
||||
self.push_presence().await;
|
||||
let _ = resp.send(true);
|
||||
}
|
||||
None => {
|
||||
eprintln!("Presence: initial connect failed; spawning reconnect task.");
|
||||
let _ = resp.send(false);
|
||||
self.spawn_reconnect_task();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn cmd_disconnect(&mut self, resp: oneshot::Sender<()>) {
|
||||
if let Some(mut client) = self.client.take() {
|
||||
let _ = client.clear_activity();
|
||||
let _ = client.close();
|
||||
println!("Presence: disconnected.");
|
||||
}
|
||||
let _ = resp.send(());
|
||||
}
|
||||
|
||||
async fn push_presence(&mut self) {
|
||||
let client = match self.client.as_mut() {
|
||||
Some(c) => c,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let mut assets = Assets::new()
|
||||
.large_image(&self.data.large_image_key)
|
||||
.large_text(&self.data.large_image_text);
|
||||
|
||||
if let Some(key) = &self.data.small_image_key {
|
||||
assets = assets.small_image(key);
|
||||
}
|
||||
if let Some(text) = &self.data.small_image_text {
|
||||
assets = assets.small_text(text);
|
||||
}
|
||||
|
||||
let buttons = if let Some(btn) = &self.data.dynamic_button {
|
||||
vec![
|
||||
Button::new(&btn.label, &btn.url),
|
||||
Button::new("Join EZPPFarm", "https://ez-pp.farm/discord"),
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
Button::new("Download the Launcher", "https://git.ez-pp.farm/EZPPFarm/EZPPLauncher/releases/latest"),
|
||||
Button::new("Join EZPPFarm", "https://ez-pp.farm/discord"),
|
||||
]
|
||||
};
|
||||
|
||||
let activity = Activity::new()
|
||||
.state(&self.data.state)
|
||||
.details(&self.data.details)
|
||||
.timestamps(Timestamps::new().start(self.start_timestamp))
|
||||
.assets(assets)
|
||||
.buttons(buttons);
|
||||
|
||||
if let Err(e) = client.set_activity(activity) {
|
||||
eprintln!("Presence: set_activity failed ({:?}); will reconnect.", e);
|
||||
self.client = None;
|
||||
self.spawn_reconnect_task();
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_reconnect_task(&mut self) {
|
||||
if self.reconnecting {
|
||||
return;
|
||||
}
|
||||
self.reconnecting = true;
|
||||
|
||||
let tx = self.reconnect_tx.clone();
|
||||
tokio::spawn(async move {
|
||||
const MAX_ATTEMPTS: u32 = 5;
|
||||
for attempt in 1..=MAX_ATTEMPTS {
|
||||
let delay = Duration::from_secs(5 * attempt as u64);
|
||||
println!(
|
||||
"Presence: reconnect attempt {}/{} in {:?}…",
|
||||
attempt, MAX_ATTEMPTS, delay
|
||||
);
|
||||
tokio::time::sleep(delay).await;
|
||||
|
||||
if let Some(client) = try_connect_once() {
|
||||
let _ = tx.send(ReconnectResult::Connected(client)).await;
|
||||
return;
|
||||
}
|
||||
self.client = Some(new_client);
|
||||
println!("Actor: Connected successfully.");
|
||||
self.handle_update().await;
|
||||
let _ = responder.send(true);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Failed to create Discord client: {:?}", e);
|
||||
let _ = responder.send(false);
|
||||
}
|
||||
}
|
||||
let _ = tx.send(ReconnectResult::Failed).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_disconnect(&mut self, responder: oneshot::Sender<()>) {
|
||||
if let Some(mut client) = self.client.take() {
|
||||
println!("Actor: Disconnecting...");
|
||||
let _ = client.clear_activity().map_err(|e| e.to_string());
|
||||
let _ = client.close().map_err(|e| e.to_string());
|
||||
println!("Actor: Disconnected successfully.");
|
||||
fn try_connect_once() -> Option<DiscordIpcClient> {
|
||||
let mut client = DiscordIpcClient::new("1032772293220384808");
|
||||
match client.connect() {
|
||||
Ok(()) => {
|
||||
println!("Presence: IPC connected.");
|
||||
Some(client)
|
||||
}
|
||||
let _ = responder.send(());
|
||||
}
|
||||
|
||||
async fn handle_update(&mut self) {
|
||||
if let Some(client) = self.client.as_mut() {
|
||||
let mut assets = Assets::new()
|
||||
.large_image(&self.data.large_image_key)
|
||||
.large_text(&self.data.large_image_text);
|
||||
|
||||
if let Some(key) = &self.data.small_image_key {
|
||||
assets = assets.small_image(key);
|
||||
}
|
||||
if let Some(text) = &self.data.small_image_text {
|
||||
assets = assets.small_text(text);
|
||||
}
|
||||
|
||||
let activity = Activity::new()
|
||||
.state(&self.data.state)
|
||||
.details(&self.data.details)
|
||||
.timestamps(Timestamps::new().start(self.start_timestamp))
|
||||
.assets(assets)
|
||||
.buttons(vec![
|
||||
Button::new(
|
||||
"Download the Launcher",
|
||||
"https://git.ez-pp.farm/EZPPFarm/EZPPLauncher/releases/latest",
|
||||
),
|
||||
Button::new("Join EZPPFarm", "https://ez-pp.farm/discord"),
|
||||
]);
|
||||
|
||||
if let Err(e) = client.set_activity(activity).map_err(|e| e.to_string()) {
|
||||
eprintln!("Failed to set activity, disconnecting: {:?}", e);
|
||||
if let Some(mut client) = self.client.take() {
|
||||
let _ = client.clear_activity();
|
||||
let _ = client.close();
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Presence: IPC connect error: {:?}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PRESENCE_TX: Lazy<mpsc::Sender<PresenceCommand>> = Lazy::new(|| {
|
||||
let (tx, rx) = mpsc::channel(10);
|
||||
let (tx, rx) = mpsc::channel(32);
|
||||
let mut actor = PresenceActor::new(rx);
|
||||
tokio::spawn(async move { actor.run().await });
|
||||
tx
|
||||
});
|
||||
|
||||
pub static PRESENCE_DATA: Lazy<StdMutex<PresenceData>> = Lazy::new(|| {
|
||||
StdMutex::new(PresenceData {
|
||||
state: "Idle in Launcher...".to_string(),
|
||||
details: " ".to_string(),
|
||||
large_image_key: "ezppfarm".to_string(),
|
||||
large_image_text: "EZPPFarm".to_string(),
|
||||
small_image_key: None,
|
||||
small_image_text: None,
|
||||
})
|
||||
});
|
||||
pub static PRESENCE_DATA: Lazy<StdMutex<PresenceData>> =
|
||||
Lazy::new(|| StdMutex::new(PresenceData::default()));
|
||||
|
||||
pub async fn connect() -> bool {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
@@ -187,45 +258,82 @@ pub async fn connect() -> bool {
|
||||
pub async fn disconnect() {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
if PRESENCE_TX.send(PresenceCommand::Disconnect(tx)).await.is_ok() {
|
||||
let _ = rx.await;
|
||||
} else {
|
||||
println!("Could not send disconnect command; actor may not be running.");
|
||||
let _ = tokio::time::timeout(Duration::from_secs(2), rx).await;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn has_presence() -> bool {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
if PRESENCE_TX.send(PresenceCommand::IsConnected(tx)).await.is_ok() {
|
||||
if PRESENCE_TX
|
||||
.send(PresenceCommand::IsConnected(tx))
|
||||
.await
|
||||
.is_ok()
|
||||
{
|
||||
return rx.await.unwrap_or(false);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn update_status(state: Option<&str>, details: Option<&str>, large_image_key: Option<&str>) {
|
||||
let mut data = PRESENCE_DATA.lock().unwrap();
|
||||
if let Some(s) = state {
|
||||
data.state = s.to_string();
|
||||
}
|
||||
if let Some(d) = details {
|
||||
data.details = d.to_string();
|
||||
}
|
||||
if let Some(img) = large_image_key {
|
||||
data.large_image_key = img.to_string();
|
||||
}
|
||||
let data_clone = data.clone();
|
||||
let data = {
|
||||
let mut guard = PRESENCE_DATA.lock().unwrap();
|
||||
if let Some(s) = state {
|
||||
guard.state = s.to_string();
|
||||
}
|
||||
if let Some(d) = details {
|
||||
guard.details = d.to_string();
|
||||
}
|
||||
if let Some(img) = large_image_key {
|
||||
guard.large_image_key = img.to_string();
|
||||
}
|
||||
guard.clone()
|
||||
};
|
||||
|
||||
let tx = PRESENCE_TX.clone();
|
||||
tokio::spawn(async move {
|
||||
let _ = tx.send(PresenceCommand::UpdateData(data_clone)).await;
|
||||
let _ = tx.send(PresenceCommand::UpdateData(data)).await;
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_button(label: &str, url: &str) {
|
||||
let data = {
|
||||
let mut guard = PRESENCE_DATA.lock().unwrap();
|
||||
guard.dynamic_button = Some(PresenceButton {
|
||||
label: label.to_string(),
|
||||
url: url.to_string(),
|
||||
});
|
||||
guard.clone()
|
||||
};
|
||||
|
||||
let tx = PRESENCE_TX.clone();
|
||||
tokio::spawn(async move {
|
||||
let _ = tx.send(PresenceCommand::UpdateData(data)).await;
|
||||
});
|
||||
}
|
||||
|
||||
pub fn clear_button() {
|
||||
let data = {
|
||||
let mut guard = PRESENCE_DATA.lock().unwrap();
|
||||
guard.dynamic_button = None;
|
||||
guard.clone()
|
||||
};
|
||||
|
||||
let tx = PRESENCE_TX.clone();
|
||||
tokio::spawn(async move {
|
||||
let _ = tx.send(PresenceCommand::UpdateData(data)).await;
|
||||
});
|
||||
}
|
||||
|
||||
pub fn update_user(username: Option<&str>, id: Option<&str>) {
|
||||
let mut data = PRESENCE_DATA.lock().unwrap();
|
||||
data.small_image_key = id.map(|id_str| format!("https://a.ez-pp.farm/{}", id_str));
|
||||
data.small_image_text = username.map(|s| s.to_string());
|
||||
let data_clone = data.clone();
|
||||
let data = {
|
||||
let mut guard = PRESENCE_DATA.lock().unwrap();
|
||||
guard.small_image_key = id.map(|s| format!("https://a.ez-pp.farm/{}", s));
|
||||
guard.small_image_text = username.map(str::to_string);
|
||||
guard.clone()
|
||||
};
|
||||
|
||||
let tx = PRESENCE_TX.clone();
|
||||
tokio::spawn(async move {
|
||||
let _ = tx.send(PresenceCommand::UpdateData(data_clone)).await;
|
||||
let _ = tx.send(PresenceCommand::UpdateData(data)).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -286,8 +286,18 @@ pub fn get_window_title_by_pid(pid: Pid) -> String {
|
||||
}
|
||||
|
||||
pub async fn is_net8_installed() -> bool {
|
||||
use std::process::Command;
|
||||
let output_result = Command::new("dotnet").arg("--list-runtimes").output();
|
||||
use tokio::process::Command;
|
||||
|
||||
let mut command = Command::new("dotnet");
|
||||
command.arg("--list-runtimes");
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||
command.creation_flags(CREATE_NO_WINDOW);
|
||||
}
|
||||
|
||||
let output_result = command.output().await;
|
||||
match output_result {
|
||||
Ok(output) => {
|
||||
if !output.status.success() {
|
||||
@@ -300,9 +310,7 @@ pub async fn is_net8_installed() -> bool {
|
||||
}
|
||||
|
||||
let stdout_str = String::from_utf8_lossy(&output.stdout);
|
||||
stdout_str
|
||||
.lines()
|
||||
.any(|line| line.starts_with("Microsoft.WindowsDesktop.App 8."))
|
||||
stdout_str.lines().any(|line| line.starts_with("Microsoft.WindowsDesktop.App 8."))
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "ezpplauncher",
|
||||
"version": "3.0.3",
|
||||
"identifier": "farm.ezpp.launcher",
|
||||
"productName": "EZPPLauncher",
|
||||
"version": "3.2.0",
|
||||
"identifier": "farm.EZPPFarm.Launcher",
|
||||
"mainBinaryName": "ezpplauncher",
|
||||
"build": {
|
||||
"beforeDevCommand": "bun run vite:dev",
|
||||
"devUrl": "http://localhost:1420",
|
||||
"beforeBuildCommand": "bun run vite:build",
|
||||
"beforeBuildCommand": "",
|
||||
"frontendDist": "../build"
|
||||
},
|
||||
"app": {
|
||||
@@ -14,7 +15,7 @@
|
||||
{
|
||||
"title": "EZPPLauncher",
|
||||
"width": 1000,
|
||||
"height": 700,
|
||||
"height": 650,
|
||||
"decorations": false,
|
||||
"resizable": false,
|
||||
"maximizable": false
|
||||
@@ -22,7 +23,13 @@
|
||||
],
|
||||
"withGlobalTauri": true,
|
||||
"security": {
|
||||
"csp": null
|
||||
"csp": null,
|
||||
"assetProtocol": {
|
||||
"enable": true,
|
||||
"scope": [
|
||||
"$HOME/.ezpplauncher/themes/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
@@ -32,20 +39,36 @@
|
||||
"license": "GPL-3.0",
|
||||
"active": true,
|
||||
"targets": [
|
||||
"app"
|
||||
"nsis",
|
||||
"appimage"
|
||||
],
|
||||
"fileAssociations": [
|
||||
{
|
||||
"ext": ["ezpplauncher-theme"],
|
||||
"name": "ezppLauncher Theme",
|
||||
"description": "ezppLauncher Theme File",
|
||||
"role": "Viewer",
|
||||
"mimeType": "application/x-ezpplauncher-theme"
|
||||
}
|
||||
],
|
||||
"windows": {
|
||||
"webviewInstallMode": {
|
||||
"silent": true,
|
||||
"type": "downloadBootstrapper"
|
||||
},
|
||||
"nsis": {
|
||||
"installMode": "currentUser",
|
||||
"compression": "lzma",
|
||||
"installerIcon": "icons/icon.ico",
|
||||
"installerHooks": "./nsis/nsis-hooks.nsh"
|
||||
}
|
||||
},
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"windows": {
|
||||
"webviewInstallMode": {
|
||||
"silent": true,
|
||||
"type": "downloadBootstrapper"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
@import "tw-animate-css";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
@@ -55,7 +55,7 @@
|
||||
--card-foreground: oklch(89.24% 0.079 263.24);
|
||||
--popover: oklch(20.3% 0.05 282.86);
|
||||
--popover-foreground: oklch(89.24% 0.079 263.24);
|
||||
--primary: oklch(81.45% 0.159 300.53);
|
||||
--primary: oklch(72.08% 0.196 356.34);
|
||||
--primary-foreground: oklch(20.22% 0.048 282.86);
|
||||
--secondary: oklch(42.99% 0.031 270.49);
|
||||
--secondary-foreground: oklch(89.24% 0.079 263.24);
|
||||
@@ -67,8 +67,8 @@
|
||||
--destructive-foreground: oklch(20.22% 0.048 282.86);
|
||||
--border: oklch(27.7% 0.041 276.87);
|
||||
--input: oklch(27.7% 0.041 276.87);
|
||||
--ring: oklch(81.45% 0.159 300.53);
|
||||
--chart-1: oklch(81.45% 0.159 300.53);
|
||||
--ring: oklch(72.08% 0.196 356.34);
|
||||
--chart-1: oklch(72.08% 0.196 356.34);
|
||||
--chart-2: oklch(77.19% 0.121 223.01);
|
||||
--chart-3: oklch(79.1% 0.119 150.21);
|
||||
--chart-4: oklch(79.74% 0.167 57.97);
|
||||
@@ -76,12 +76,12 @@
|
||||
--sidebar: oklch(13.29% 0.036 282.86);
|
||||
--sidebar-background: oklch(13.29% 0.036 282.86);
|
||||
--sidebar-foreground: oklch(89.24% 0.079 263.24);
|
||||
--sidebar-primary: oklch(81.45% 0.159 300.53);
|
||||
--sidebar-primary: oklch(72.08% 0.196 356.34);
|
||||
--sidebar-primary-foreground: oklch(20.22% 0.048 282.86);
|
||||
--sidebar-accent: oklch(75.21% 0.121 293.01);
|
||||
--sidebar-accent-foreground: oklch(20.22% 0.048 282.86);
|
||||
--sidebar-border: oklch(35.13% 0.03 273.31);
|
||||
--sidebar-ring: oklch(81.45% 0.159 300.53);
|
||||
--sidebar-ring: oklch(72.08% 0.196 356.34);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
@@ -108,20 +108,18 @@
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-50: #fefdff;
|
||||
--color-primary-100: #faf6fe;
|
||||
--color-primary-200: #f2e9fc;
|
||||
--color-primary-300: #e9dbfa;
|
||||
--color-primary-400: #e1cef9;
|
||||
--color-primary-500: #d9c0f7;
|
||||
--color-primary-600: #c6a0f3;
|
||||
--color-primary-700: #b381ef;
|
||||
--color-primary-800: #a061eb;
|
||||
--color-primary-900: #8d41e7;
|
||||
--color-primary-950: #8331e5;
|
||||
--color-primary-50: #ffe5f1;
|
||||
--color-primary-100: #ffcce2;
|
||||
--color-primary-200: #ff99c5;
|
||||
--color-primary-300: #ff66a8;
|
||||
--color-primary-400: #ff338b;
|
||||
--color-primary-500: #ff006e;
|
||||
--color-primary-600: #cc0058;
|
||||
--color-primary-700: #990042;
|
||||
--color-primary-800: #66002c;
|
||||
--color-primary-900: #330016;
|
||||
--color-primary-950: #24000f;
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-primary-50: #fefdff;
|
||||
--color-primary-100: #faf6fe;
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
@@ -147,6 +145,62 @@
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
}
|
||||
|
||||
main[data-theme="execution_clap"] {
|
||||
--primary: #fc112b;
|
||||
--primary-foreground: #fff;
|
||||
--ring: #fc112b;
|
||||
--color-primary-50: #fef2f2;
|
||||
--color-primary-100: #fee2e2;
|
||||
--color-primary-200: #fecaca;
|
||||
--color-primary-300: #fca5a5;
|
||||
--color-primary-400: #f87171;
|
||||
--color-primary-500: #ef4444;
|
||||
--color-primary-600: #dc2626;
|
||||
--color-primary-700: #b91c1c;
|
||||
--color-primary-800: #991b1b;
|
||||
--color-primary-900: #7f1d1d;
|
||||
--color-primary-950: #450a0a;
|
||||
--bg-primary-50: #fef2f2;
|
||||
--bg-primary-100: #fee2e2;
|
||||
--bg-primary-200: #fecaca;
|
||||
--bg-primary-300: #fca5a5;
|
||||
--bg-primary-400: #f87171;
|
||||
--bg-primary-500: #ef4444;
|
||||
--bg-primary-600: #dc2626;
|
||||
--bg-primary-700: #b91c1c;
|
||||
--bg-primary-800: #991b1b;
|
||||
--bg-primary-900: #7f1d1d;
|
||||
--bg-primary-950: #450a0a;
|
||||
}
|
||||
|
||||
main[data-theme="lost_umbrella"] {
|
||||
--primary: #e5e5e5;
|
||||
--primary-foreground: #000;
|
||||
--ring: #e5e5e5;
|
||||
--color-primary-50: #0d0d0d;
|
||||
--color-primary-100: #1a1a1a;
|
||||
--color-primary-200: #333333;
|
||||
--color-primary-300: #4d4d4d;
|
||||
--color-primary-400: #666666;
|
||||
--color-primary-500: #808080;
|
||||
--color-primary-600: #999999;
|
||||
--color-primary-700: #b3b3b3;
|
||||
--color-primary-800: #cccccc;
|
||||
--color-primary-900: #e6e6e6;
|
||||
--color-primary-950: #f2f2f2;
|
||||
--bg-primary-50: #0d0d0d;
|
||||
--bg-primary-100: #1a1a1a;
|
||||
--bg-primary-200: #333333;
|
||||
--bg-primary-300: #4d4d4d;
|
||||
--bg-primary-400: #666666;
|
||||
--bg-primary-500: #808080;
|
||||
--bg-primary-600: #999999;
|
||||
--bg-primary-700: #b3b3b3;
|
||||
--bg-primary-800: #cccccc;
|
||||
--bg-primary-900: #e6e6e6;
|
||||
--bg-primary-950: #f2f2f2;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
|
||||
|
After Width: | Height: | Size: 173 KiB |
@@ -0,0 +1,86 @@
|
||||
<script lang="ts">
|
||||
import { reduceAnimations } from '@/userSettings';
|
||||
|
||||
//TODO: maybe dynamic background images fetched from ezpp?
|
||||
|
||||
const COUNT = 60;
|
||||
|
||||
function rand(min: number, max: number) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
||||
const streaks = Array.from({ length: COUNT })
|
||||
.map((_, i) => {
|
||||
const depth = rand(0, 2);
|
||||
|
||||
const scale = 0.6 + depth * 0.8;
|
||||
const speed = 0.4 + depth * 1.35;
|
||||
|
||||
const distance = 150;
|
||||
const duration = distance / speed;
|
||||
|
||||
return {
|
||||
width: rand(300, 320) * scale,
|
||||
height: 32 * scale,
|
||||
x: (i / COUNT) * 200 - 50,
|
||||
y: ((i * 137.5) % 100) - 20,
|
||||
opacity: 0.25 + depth * 0.65,
|
||||
duration,
|
||||
delay: rand(0, duration),
|
||||
scale,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.scale - b.scale);
|
||||
</script>
|
||||
|
||||
<div class="absolute bg blur-[2px]">
|
||||
<div
|
||||
class="relative h-full w-full from-0% to-90% bg-gradient-to-b from-transparent to-black z-50"
|
||||
></div>
|
||||
{#each streaks as s, index (index)}
|
||||
<div
|
||||
class="streak drop-shadow-lg transition-opacity duration-1000"
|
||||
style="
|
||||
width:{s.width}px;
|
||||
height:{s.height}px;
|
||||
left:{s.x}%;
|
||||
top:{s.y}%;
|
||||
opacity:{$reduceAnimations ? 0 : s.opacity};
|
||||
animation-duration:{s.duration}s;
|
||||
animation-delay:-{s.delay}s;
|
||||
"
|
||||
></div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.bg {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
var(--color-primary-300) 0%,
|
||||
var(--color-primary-600) 40%,
|
||||
var(--color-primary-900) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.streak {
|
||||
position: absolute;
|
||||
background: #d6f3ff;
|
||||
border-radius: 999px;
|
||||
transform: rotate(-35deg);
|
||||
animation: move linear infinite;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
@keyframes move {
|
||||
from {
|
||||
transform: translate(-150vw, 150vh) rotate(-35deg);
|
||||
}
|
||||
to {
|
||||
transform: translate(150vw, -150vh) rotate(-35deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,91 @@
|
||||
<script lang="ts">
|
||||
import NyanCat from '$assets/themes/nyan_cat/image.gif';
|
||||
import { reduceAnimations } from '@/userSettings';
|
||||
|
||||
//TODO: maybe dynamic background images fetched from ezpp?
|
||||
|
||||
const COUNT = 18;
|
||||
|
||||
function rand(min: number, max: number) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
||||
const streaks = Array.from({ length: COUNT })
|
||||
.map((_, i) => {
|
||||
const depth = rand(0, 2);
|
||||
|
||||
const scale = 0.6 + depth * 0.8;
|
||||
const speed = 0.4 + depth * 1.35;
|
||||
|
||||
const distance = 150;
|
||||
const duration = distance / speed;
|
||||
|
||||
return {
|
||||
width: 290 * scale,
|
||||
height: 140 * scale,
|
||||
x: (i / COUNT) * 200 - 50,
|
||||
y: ((i * 137.5) % 100) - 20,
|
||||
opacity: 0.25 + depth * 0.65,
|
||||
duration,
|
||||
delay: rand(0, duration),
|
||||
scale,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.scale - b.scale);
|
||||
</script>
|
||||
|
||||
<div class="absolute bg blur-[2px]">
|
||||
<div
|
||||
class="relative h-full w-full from-0% to-90% bg-gradient-to-b from-transparent to-black z-50"
|
||||
></div>
|
||||
{#each streaks as s, index (index)}
|
||||
<div
|
||||
class="streak drop-shadow-lg transition-opacity duration-1000"
|
||||
style="
|
||||
width:{s.width}px;
|
||||
height:{s.height}px;
|
||||
left:{s.x}%;
|
||||
top:{s.y}%;
|
||||
opacity:{$reduceAnimations ? 0 : s.opacity};
|
||||
animation-duration:{s.duration}s;
|
||||
animation-delay:-{s.delay}s;
|
||||
"
|
||||
>
|
||||
<img
|
||||
src={NyanCat}
|
||||
alt="nyan cat"
|
||||
class="w-full h-full"
|
||||
style="opacity:{$reduceAnimations ? 0 : s.opacity};"
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.bg {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
var(--color-blue-800) 0%,
|
||||
var(--color-blue-600) 40%,
|
||||
var(--color-blue-900) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.streak {
|
||||
position: absolute;
|
||||
animation: move linear infinite;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
@keyframes move {
|
||||
from {
|
||||
transform: translate(-250vw, 0);
|
||||
}
|
||||
to {
|
||||
transform: translate(250vw, 0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,91 @@
|
||||
<script lang="ts">
|
||||
import Ellipsis from 'lucide-svelte/icons/ellipsis';
|
||||
import Play from 'lucide-svelte/icons/play';
|
||||
|
||||
const prop: {
|
||||
downloading: boolean;
|
||||
progress: number;
|
||||
text: string;
|
||||
subtext?: string;
|
||||
disabled?: boolean;
|
||||
onClick?: () => void;
|
||||
} = $props();
|
||||
|
||||
const radius = 16;
|
||||
const circumference = 2 * Math.PI * radius;
|
||||
const strokeDashoffset = $derived(circumference - (prop.progress / 100) * circumference);
|
||||
</script>
|
||||
|
||||
<button
|
||||
class="group flex items-center h-12 rounded-full bg-primary disabled:bg-primary/70 shadow-lg shadow-primary/25 transition-all not-disabled:hover:shadow-primary/40 not-disabled:hover:brightness-110 not-disabled:active:scale-[0.98] cursor-pointer w-fit"
|
||||
disabled={prop.disabled}
|
||||
onclick={prop.onClick}
|
||||
>
|
||||
<div class="relative size-12 shrink-0 flex items-center justify-center">
|
||||
{#if prop.downloading}
|
||||
{#if prop.progress === -1}
|
||||
<svg class="absolute inset-0 animate-spin" viewBox="0 0 48 48">
|
||||
<circle class="stroke-black/10" cx="24" cy="24" r={radius} fill="none" stroke-width="3" />
|
||||
<circle
|
||||
class="stroke-pink-950"
|
||||
cx="24"
|
||||
cy="24"
|
||||
r={radius}
|
||||
fill="none"
|
||||
stroke-width="3"
|
||||
stroke-linecap="round"
|
||||
stroke-dasharray={circumference}
|
||||
stroke-dashoffset={circumference * 0.7}
|
||||
/>
|
||||
</svg>
|
||||
{:else}
|
||||
<svg class="absolute inset-0 -rotate-90" viewBox="0 0 48 48">
|
||||
<circle
|
||||
cx="24"
|
||||
cy="24"
|
||||
r={radius}
|
||||
fill="none"
|
||||
stroke="rgba(0,0,0,0.2)"
|
||||
stroke-width="3"
|
||||
/>
|
||||
<circle
|
||||
cx="24"
|
||||
cy="24"
|
||||
r={radius}
|
||||
fill="none"
|
||||
stroke="rgba(0,0,0,0.7)"
|
||||
stroke-width="3"
|
||||
stroke-linecap="round"
|
||||
stroke-dasharray={circumference}
|
||||
stroke-dashoffset={strokeDashoffset}
|
||||
class="transition-[stroke-dashoffset] duration-100"
|
||||
/>
|
||||
</svg>
|
||||
{/if}
|
||||
{/if}
|
||||
<div class="size-9 rounded-full bg-black/30 flex items-center justify-center relative z-10">
|
||||
{#if prop.downloading}
|
||||
{#if prop.progress === -1}
|
||||
<Ellipsis class="size-4 text-primary-foreground fill-current animate-pulse" />
|
||||
{:else}
|
||||
<span class="text-[10px] font-bold text-primary-foreground">
|
||||
{prop.progress.toFixed()}
|
||||
</span>
|
||||
{/if}
|
||||
{:else}
|
||||
<Play class="size-4 text-primary-foreground fill-current ml-0.5" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pr-6 pl-1 text-center w-52">
|
||||
<p class="text-sm font-bold text-primary-foreground leading-tight">
|
||||
{prop.text}
|
||||
</p>
|
||||
{#if prop.subtext}
|
||||
<p class="text-[10px] text-primary-foreground/70 leading-tight">
|
||||
{prop.subtext}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
|
||||
import Check from 'lucide-svelte/icons/check';
|
||||
import Minus from 'lucide-svelte/icons/minus';
|
||||
import Check from '@lucide/svelte/icons/check';
|
||||
import Minus from '@lucide/svelte/icons/minus';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<DropdownMenuPrimitive.Item
|
||||
bind:ref
|
||||
class={cn(
|
||||
'data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
'data-[highlighted]:bg-primary data-[highlighted]:text-primary-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
inset && 'pl-8',
|
||||
className
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive, type WithoutChild } from 'bits-ui';
|
||||
import Circle from 'lucide-svelte/icons/circle';
|
||||
import Circle from '@lucide/svelte/icons/circle';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||
import ChevronRight from 'lucide-svelte/icons/chevron-right';
|
||||
import ChevronRight from '@lucide/svelte/icons/chevron-right';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
const computed = getComputedStyle(el);
|
||||
if (
|
||||
['button', 'a', 'input', 'select', 'textarea', 'label', 'option'].includes(tag) ||
|
||||
(role && ['button', 'link', 'checkbox', 'combobox'].includes(role)) ||
|
||||
(role && ['button', 'link', 'checkbox', 'combobox', 'menuitem', 'option'].includes(role)) ||
|
||||
computed.cursor === 'pointer'
|
||||
) {
|
||||
return true;
|
||||
@@ -85,7 +85,7 @@
|
||||
animate(cursor, {
|
||||
duration: smoothCursor ? $cursorSmoothness : 0,
|
||||
translateX: mouseX,
|
||||
translateY: mouseY - 50,
|
||||
translateY: mouseY,
|
||||
ease: (t: number) => (t - 1) ** 5 + 1,
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
<script lang="ts">
|
||||
// Props
|
||||
let { children, class: className = '', topOffset = 0 } = $props();
|
||||
|
||||
let wrapper: HTMLDivElement;
|
||||
let container: HTMLDivElement;
|
||||
let thumb: HTMLDivElement;
|
||||
|
||||
// Thumb state
|
||||
let thumbHeight = $state(20);
|
||||
let thumbTop = $state(0);
|
||||
|
||||
// Drag state
|
||||
let dragging = false;
|
||||
let startY = 0;
|
||||
let startScroll = 0;
|
||||
|
||||
/** Update thumb height & position */
|
||||
function updateScrollbar() {
|
||||
if (!container) return;
|
||||
|
||||
const { scrollTop, scrollHeight, clientHeight } = container;
|
||||
const scrollable = scrollHeight - clientHeight;
|
||||
|
||||
if (scrollable <= 0) {
|
||||
thumbHeight = 0;
|
||||
thumbTop = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
thumbHeight = Math.max((clientHeight / scrollHeight) * clientHeight, 24);
|
||||
|
||||
const trackHeight = clientHeight - thumbHeight - topOffset;
|
||||
thumbTop = (scrollTop / scrollable) * trackHeight;
|
||||
}
|
||||
|
||||
/** Start dragging the thumb */
|
||||
function startDrag(e: PointerEvent) {
|
||||
dragging = true;
|
||||
startY = e.clientY;
|
||||
startScroll = container.scrollTop;
|
||||
thumb.setPointerCapture(e.pointerId);
|
||||
}
|
||||
|
||||
/** Drag the thumb */
|
||||
function drag(e: PointerEvent) {
|
||||
if (!dragging) return;
|
||||
|
||||
const delta = e.clientY - startY;
|
||||
const { scrollHeight, clientHeight } = container;
|
||||
const scrollable = scrollHeight - clientHeight;
|
||||
const trackHeight = clientHeight - thumbHeight - topOffset;
|
||||
|
||||
container.scrollTop = startScroll + (delta / trackHeight) * scrollable;
|
||||
}
|
||||
|
||||
/** End dragging */
|
||||
function endDrag(e: PointerEvent) {
|
||||
dragging = false;
|
||||
thumb.releasePointerCapture(e.pointerId);
|
||||
}
|
||||
|
||||
// Reactive effect to update scrollbar
|
||||
$effect(() => updateScrollbar());
|
||||
|
||||
// ResizeObserver for dynamic content
|
||||
$effect(() => {
|
||||
if (!container) return;
|
||||
const observer = new ResizeObserver(updateScrollbar);
|
||||
observer.observe(container);
|
||||
return () => observer.disconnect();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="wrapper" bind:this={wrapper}>
|
||||
<!-- Scrollable content -->
|
||||
<div
|
||||
class={`content ${className}`}
|
||||
bind:this={container}
|
||||
onscroll={updateScrollbar}
|
||||
id="scrollable-content"
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
<!-- Custom scrollbar -->
|
||||
<div class="scrollbar" style="top: {topOffset}px;">
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div
|
||||
class="thumb"
|
||||
bind:this={thumb}
|
||||
onpointerdown={startDrag}
|
||||
onpointermove={drag}
|
||||
onpointerup={endDrag}
|
||||
onpointercancel={endDrag}
|
||||
aria-controls="scrollable-content"
|
||||
style="height:{thumbHeight}px; transform:translateY({thumbTop}px);"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.wrapper {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Scrollable content */
|
||||
.content {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
||||
.content::-webkit-scrollbar {
|
||||
display: none; /* Chrome, Safari, Edge */
|
||||
}
|
||||
|
||||
/* Scrollbar track */
|
||||
.scrollbar {
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
bottom: 0;
|
||||
width: 8px;
|
||||
background: transparent;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
/* Thumb */
|
||||
.thumb {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
background: var(--color-theme-700);
|
||||
border-radius: 999px;
|
||||
cursor: grab;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
.thumb:active {
|
||||
cursor: grabbing;
|
||||
background: var(--color-theme-600);
|
||||
}
|
||||
|
||||
.thumb:hover {
|
||||
background: var(--color-theme-700);
|
||||
}
|
||||
</style>
|
||||
@@ -17,7 +17,7 @@
|
||||
bind:ref
|
||||
{value}
|
||||
class={cn(
|
||||
'data-[highlighted]:bg-primary-800/30 data-[highlighted]:text-accent-foreground relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
'data-[highlighted]:bg-primary data-[highlighted]:text-primary-foreground relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { createElement } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import type { SileoOptions } from 'sileo';
|
||||
|
||||
let props: SileoOptions = $props();
|
||||
let rootEl: HTMLElement;
|
||||
|
||||
$effect(() => {
|
||||
const root = createRoot(rootEl);
|
||||
|
||||
import('sileo').then(({ Toaster }) => {
|
||||
const sileo = createElement(Toaster, { ...props });
|
||||
root.render(sileo);
|
||||
});
|
||||
|
||||
return () => root.unmount();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div bind:this={rootEl}></div>
|
||||
@@ -0,0 +1,7 @@
|
||||
import Root from './switch.svelte';
|
||||
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Switch,
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
<script lang="ts">
|
||||
import { Switch as SwitchPrimitive, type WithoutChildrenOrChild } from 'bits-ui';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
checked = $bindable(false),
|
||||
...restProps
|
||||
}: WithoutChildrenOrChild<SwitchPrimitive.RootProps> = $props();
|
||||
</script>
|
||||
|
||||
<SwitchPrimitive.Root
|
||||
bind:ref
|
||||
bind:checked
|
||||
class={cn(
|
||||
'focus-visible:ring-ring focus-visible:ring-offset-background data-[state=checked]:bg-primary data-[state=unchecked]:bg-input peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
<SwitchPrimitive.Thumb
|
||||
class={cn(
|
||||
'bg-background pointer-events-none block size-5 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0'
|
||||
)}
|
||||
/>
|
||||
</SwitchPrimitive.Root>
|
||||
@@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import Minimize from 'lucide-svelte/icons/minus';
|
||||
import Close from 'lucide-svelte/icons/x';
|
||||
|
||||
import Logo from '$assets/logo.png';
|
||||
import Volume2 from 'lucide-svelte/icons/volume-2';
|
||||
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||
import { onMount } from 'svelte';
|
||||
import { launcherVersion } from '@/global';
|
||||
import Badge from '../badge/badge.svelte';
|
||||
import { custom_theme_audio_playing, custom_theme_volume } from '@/global';
|
||||
import { reduceAnimations, userSettings } from '@/userSettings';
|
||||
import { Volume, Volume1, VolumeOff } from 'lucide-svelte';
|
||||
|
||||
onMount(() => {
|
||||
const appWindow = getCurrentWindow();
|
||||
@@ -19,32 +19,93 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div data-tauri-drag-region class="titlebar z-[60] border-b border-theme-800/90">
|
||||
<div
|
||||
class="mr-auto ms-2 flex flex-row gap-2 items-center text-[1.05rem] font-semibold pointer-events-none"
|
||||
>
|
||||
<img src={Logo} alt="EZPP Launcher Logo" class="h-11 w-11 inline-block" />
|
||||
<span>EZPPLauncher</span>
|
||||
<Badge class="!text-[0.6rem] py-[0.5px] bg-primary-500 hover:bg-primary-500"
|
||||
>{$launcherVersion}</Badge
|
||||
>
|
||||
<div data-tauri-drag-region class="titlebar z-[100]">
|
||||
{#if $custom_theme_audio_playing}
|
||||
{#if $custom_theme_audio_playing}
|
||||
<div class="relative flex items-center justify-center group">
|
||||
<div class="relative flex items-center justify-center p-1 cursor-pointer">
|
||||
<div
|
||||
class="absolute inset-0 bg-background rounded
|
||||
scale-80 opacity-0
|
||||
group-hover:opacity-100
|
||||
group-hover:scale-100
|
||||
{$reduceAnimations ? '' : 'transition-all duration-200 ease-out'}"
|
||||
></div>
|
||||
|
||||
{#if $custom_theme_volume > 0.7}
|
||||
<Volume2 class="z-10 pointer-events-none" size={14} />
|
||||
{:else if $custom_theme_volume >= 0.15}
|
||||
<Volume1 class="z-10 pointer-events-none" size={14} />
|
||||
{:else if $custom_theme_volume > 0}
|
||||
<Volume class="z-10 pointer-events-none" size={14} />
|
||||
{:else}
|
||||
<VolumeOff class="z-10 pointer-events-none" size={14} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="absolute top-full right-0 translate-x-[7px]
|
||||
opacity-0 invisible pointer-events-none -translate-y-2
|
||||
group-hover:opacity-100 group-hover:visible group-hover:pointer-events-auto group-hover:translate-y-0
|
||||
{$reduceAnimations ? '' : 'transition-all duration-200 ease-out'}
|
||||
z-50"
|
||||
>
|
||||
<div class="h-2 w-full"></div>
|
||||
|
||||
<div
|
||||
class="flex items-center justify-center h-[120px] w-[35px]
|
||||
bg-black/20 backdrop-blur-sm border border-white/10 rounded-xl"
|
||||
>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.01"
|
||||
bind:value={$custom_theme_volume}
|
||||
on:input={() => {
|
||||
$userSettings.value('volume').set($custom_theme_volume);
|
||||
$userSettings.save();
|
||||
}}
|
||||
class="volume-slider"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
<div class="relative flex items-center justify-center p-1 group" id="titlebar-minimize">
|
||||
<div
|
||||
class="absolute inset-0 bg-background rounded
|
||||
scale-80 opacity-0
|
||||
group-hover:opacity-100
|
||||
group-hover:scale-100
|
||||
{$reduceAnimations ? '' : 'transition-all duration-200 ease-out'}
|
||||
origin-center"
|
||||
></div>
|
||||
|
||||
<Minimize class="z-10 pointer-events-none" size={14} />
|
||||
</div>
|
||||
<div class="titlebar-button rounded-lg transition-colors duration-75" id="titlebar-minimize">
|
||||
<Minimize size={18} />
|
||||
</div>
|
||||
<div class="titlebar-button close rounded-lg transition-colors duration-75" id="titlebar-close">
|
||||
<Close size={18} />
|
||||
<div class="relative flex items-center justify-center p-1 group" id="titlebar-close">
|
||||
<div
|
||||
class="absolute inset-0 bg-red-500 rounded
|
||||
scale-80 opacity-0
|
||||
group-hover:opacity-100
|
||||
group-hover:scale-100
|
||||
{$reduceAnimations ? '' : 'transition-all duration-200 ease-out'}
|
||||
origin-center"
|
||||
></div>
|
||||
|
||||
<Close class="z-10 pointer-events-none" size={14} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.titlebar {
|
||||
height: 50px;
|
||||
/* background: #040612; */
|
||||
height: 35px;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -52,21 +113,54 @@
|
||||
right: 0;
|
||||
margin-bottom: 10px;
|
||||
padding-right: 5px;
|
||||
pointer-events: all !important;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.titlebar-button {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
||||
.volume-slider {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
|
||||
width: 100px; /* becomes vertical */
|
||||
height: 6px;
|
||||
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.titlebar-button:hover {
|
||||
&.close {
|
||||
background: #c22e2e;
|
||||
}
|
||||
background: #2d3049;
|
||||
|
||||
/* track */
|
||||
.volume-slider::-webkit-slider-runnable-track {
|
||||
height: 6px;
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
/* thumb */
|
||||
.volume-slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
|
||||
margin-top: -4px; /* center thumb */
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
.volume-slider::-moz-range-track {
|
||||
height: 6px;
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.volume-slider::-moz-range-thumb {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -44,8 +44,7 @@ export class Config {
|
||||
this.encrypt && this.crypto ? this.crypto.decrypt(fileStream) : fileStream
|
||||
) as Record<string, unknown>;
|
||||
this.config = decryptedJSON;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
} catch {
|
||||
this.config = {};
|
||||
await this.save();
|
||||
}
|
||||
@@ -69,6 +68,9 @@ export class Config {
|
||||
set: <T>(val: T) => {
|
||||
this.config[key] = val;
|
||||
},
|
||||
exists: () => {
|
||||
return this.config[key] !== undefined;
|
||||
},
|
||||
get: <T>(fallback: T): T => {
|
||||
return (this.config[key] as T) ?? fallback;
|
||||
},
|
||||
|
||||
@@ -8,8 +8,7 @@ export function estimateRefreshRate(): Promise<number> {
|
||||
frames++;
|
||||
|
||||
if (now - last >= 1000) {
|
||||
console.log(`Estimated Refresh Rate: ${frames - 2} FPS`);
|
||||
resolve(frames - 2); // estimated Hz
|
||||
resolve(frames - 2);
|
||||
} else {
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import { onDestroy } from 'svelte';
|
||||
|
||||
type TauriDragDropEvent = {
|
||||
paths: string[];
|
||||
position: { x: number; y: number };
|
||||
};
|
||||
|
||||
export const useDropZone = ({ onDrop }: { onDrop: (paths: string[]) => void }) => {
|
||||
let element = $state<HTMLDivElement | null>(null);
|
||||
let dragIn = $state(false);
|
||||
let isDraggingOverApp = $state(false);
|
||||
|
||||
const isOver = (x: number, y: number) => {
|
||||
if (!element) return false;
|
||||
const el = document.elementFromPoint(x, y);
|
||||
return element === el || element.contains(el); // ← fix
|
||||
};
|
||||
|
||||
const dropUnlisten = listen<TauriDragDropEvent>('tauri://drag-drop', (e) => {
|
||||
const { x, y } = e.payload.position;
|
||||
if (isOver(x, y)) {
|
||||
onDrop(e.payload.paths);
|
||||
}
|
||||
dragIn = false;
|
||||
isDraggingOverApp = false;
|
||||
});
|
||||
|
||||
const overUnlisten = listen<TauriDragDropEvent>('tauri://drag-over', (e) => {
|
||||
const { x, y } = e.payload.position;
|
||||
isDraggingOverApp = true;
|
||||
dragIn = isOver(x, y);
|
||||
});
|
||||
|
||||
const leaveUnlisten = listen('tauri://drag-leave', () => {
|
||||
dragIn = false;
|
||||
isDraggingOverApp = false;
|
||||
});
|
||||
|
||||
onDestroy(async () => {
|
||||
(await dropUnlisten)();
|
||||
(await overUnlisten)();
|
||||
(await leaveUnlisten)();
|
||||
});
|
||||
|
||||
return {
|
||||
get ref() {
|
||||
return element;
|
||||
},
|
||||
set ref(el: HTMLDivElement | null) {
|
||||
element = el;
|
||||
},
|
||||
get dragIn() {
|
||||
return dragIn;
|
||||
},
|
||||
get isDraggingOverApp() {
|
||||
return isDraggingOverApp;
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -3,7 +3,9 @@ import { ezppfarm } from './api/ezpp';
|
||||
import type { Component } from 'svelte';
|
||||
import Loading from '../screens/Loading.svelte';
|
||||
import type { Release } from './types';
|
||||
|
||||
import type { Theme } from './themes';
|
||||
import { browser } from '$app/environment';
|
||||
import { setGlobalVolume } from './utils';
|
||||
export const currentView = writable<Component>(Loading);
|
||||
|
||||
export const platform = writable<string>('');
|
||||
@@ -14,6 +16,8 @@ export const newVersion = writable<Release | undefined>(undefined);
|
||||
export const launcherStreams = writable<string[]>(['stable']);
|
||||
export const launcherStream = writable<string>('stable');
|
||||
|
||||
export const trackingEnabled = writable<boolean>(false);
|
||||
|
||||
export const discordPresence = writable<boolean>(false);
|
||||
export const presenceLoading = writable<boolean>(false);
|
||||
|
||||
@@ -22,6 +26,16 @@ export const currentLoadingInfo = writable<string>('Initializing...');
|
||||
export const firstStartup = writable<boolean>(false);
|
||||
|
||||
export const launching = writable<boolean>(false);
|
||||
export const custom_themes = writable<Theme[]>([]);
|
||||
export const custom_theme_container = writable<HTMLElement | undefined>(undefined);
|
||||
export const active_custom_theme = writable<Theme | undefined>(undefined);
|
||||
export const custom_theme_audio_playing = writable<boolean>(false);
|
||||
export const custom_theme_volume = writable<number>(0.15);
|
||||
custom_theme_volume.subscribe((val) => {
|
||||
if (browser) {
|
||||
setGlobalVolume(val);
|
||||
}
|
||||
});
|
||||
|
||||
export const serverPing = writable<number | undefined>(undefined);
|
||||
export const serverConnectionFails = writable(0);
|
||||
@@ -29,7 +43,8 @@ export const serverConnectionFails = writable(0);
|
||||
export const onlineFriends = writable<number | undefined>(undefined);
|
||||
|
||||
export const beatmapSets = writable<number | undefined>(undefined);
|
||||
export const skins = writable<number | undefined>(undefined);
|
||||
export const skinsCount = writable<number | undefined>(undefined);
|
||||
export const skins = writable<{ name: string; author: string | undefined; modified: number }[]>([]);
|
||||
|
||||
export const osuStream = writable<string | undefined>(undefined);
|
||||
export const osuBuild = writable<string | undefined>(undefined);
|
||||
|
||||
@@ -3,22 +3,28 @@ import type { UpdateFile, UpdateStatus } from './types';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import { betterFetch } from '@better-fetch/fetch';
|
||||
|
||||
const updateUrl = 'https://next.ez-pp.farm/api/ezpplauncher';
|
||||
const updateUrl = 'https://ez-pp.farm/api/ezpplauncher';
|
||||
|
||||
export const getHWID = async () => {
|
||||
const hwid = await invoke('get_hwid');
|
||||
return typeof hwid === 'string' ? hwid : undefined;
|
||||
};
|
||||
export function normalizeOsuName(name: string): string {
|
||||
return (
|
||||
name
|
||||
.trim()
|
||||
// Remove leading symbols/spaces
|
||||
.replace(/^[^a-zA-Z0-9]+/, '')
|
||||
// Normalize spacing
|
||||
.replace(/\s+/g, ' ')
|
||||
.toLowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
export const isValidOsuFolder = async (folder: string): Promise<boolean> => {
|
||||
const result = await invoke('valid_osu_folder', { folder });
|
||||
return typeof result === 'boolean' ? result : false;
|
||||
};
|
||||
export const getHWID = async (): Promise<string | undefined> =>
|
||||
await invoke<string | undefined>('get_hwid');
|
||||
|
||||
export const autoDetectOsuInstallFolder = async () => {
|
||||
const result = await invoke('find_osu_installation');
|
||||
return typeof result === 'string' ? result : undefined;
|
||||
};
|
||||
export const isValidOsuFolder = async (folder: string): Promise<boolean | undefined> =>
|
||||
await invoke<boolean | undefined>('valid_osu_folder', { folder });
|
||||
|
||||
export const autoDetectOsuInstallFolder = async () =>
|
||||
await invoke<string | undefined>('find_osu_installation');
|
||||
|
||||
export const setUserConfigValues = async (
|
||||
osuFolderPath: string,
|
||||
@@ -38,36 +44,23 @@ export const setConfigValues = async (
|
||||
entries,
|
||||
});
|
||||
|
||||
export const getReleaseStream = async (folder: string) => {
|
||||
const result = await invoke('get_osu_release_stream', { folder });
|
||||
return typeof result === 'string' ? result : undefined;
|
||||
};
|
||||
export const getReleaseStream = async (folder: string): Promise<string | undefined> =>
|
||||
await invoke<string | undefined>('get_osu_release_stream', { folder });
|
||||
|
||||
export const getVersion = async (folder: string) => {
|
||||
const result = await invoke('get_osu_version', { folder });
|
||||
return typeof result === 'string' ? result : undefined;
|
||||
};
|
||||
export const getVersion = async (folder: string): Promise<string | undefined> =>
|
||||
await invoke<string | undefined>('get_osu_version', { folder });
|
||||
|
||||
export const getBeatmapSetsCount = async (folder: string) => {
|
||||
const result = await invoke('get_beatmapsets_count', {
|
||||
export const getBeatmapSetsCount = async (folder: string): Promise<number | undefined> =>
|
||||
await invoke<number | undefined>('get_beatmapsets_count', {
|
||||
folder,
|
||||
});
|
||||
return typeof result === 'number' ? result : 0;
|
||||
};
|
||||
|
||||
export const getSkinsCount = async (folder: string) => {
|
||||
const result = await invoke('get_skins_count', {
|
||||
folder,
|
||||
});
|
||||
return typeof result === 'number' ? result : 0;
|
||||
};
|
||||
|
||||
export const getSkin = async (folder: string) => {
|
||||
const result = await invoke('get_osu_skin', {
|
||||
const result = await invoke<string | undefined>('get_osu_skin', {
|
||||
folder,
|
||||
});
|
||||
|
||||
return typeof result === 'string' ? result : 'Default';
|
||||
return result || 'Default';
|
||||
};
|
||||
|
||||
export const runUpdater = async (folder: string) => await invoke('run_osu_updater', { folder });
|
||||
@@ -82,7 +75,6 @@ export const getEZPPLauncherStreams = async () => {
|
||||
if (!resp.error) {
|
||||
return resp.data.streams;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@@ -109,8 +101,8 @@ export const downloadEZPPLauncherUpdateFiles = async (
|
||||
allFiles: UpdateFile[],
|
||||
progressCallback: (file: UpdateStatus) => void
|
||||
) => {
|
||||
const downloadStatusListen = await listen('download-progress', (event) =>
|
||||
progressCallback(event.payload as UpdateStatus)
|
||||
const downloadStatusListen = await listen<UpdateStatus>('download-progress', (event) =>
|
||||
progressCallback(event.payload)
|
||||
);
|
||||
try {
|
||||
await invoke('download_ezpp_launcher_update_files', { folder, updateFiles, allFiles });
|
||||
@@ -123,18 +115,34 @@ export const replaceUIFiles = async (folder: string, revert: boolean) => {
|
||||
await invoke('replace_ui_files', { folder, revert });
|
||||
};
|
||||
|
||||
export const isOsuRunning = async () => {
|
||||
const result = await invoke('is_osu_running');
|
||||
return typeof result === 'boolean' ? result : false;
|
||||
};
|
||||
export const isOsuRunning = async (): Promise<boolean> => await invoke<boolean>('is_osu_running');
|
||||
|
||||
export const getLauncherVersion = async () => await invoke<string>('get_launcher_version');
|
||||
export const exit = async () => await invoke('exit');
|
||||
export const getPlatform = async () => await invoke<string>('get_platform');
|
||||
export const isOsuCorrupted = async (folder: string) =>
|
||||
export const getPlatform = async (): Promise<string> => await invoke<string>('get_platform');
|
||||
export const isOsuCorrupted = async (folder: string): Promise<boolean> =>
|
||||
await invoke<boolean>('check_for_corruption', { folder });
|
||||
export const hasWMCTRL = async () => await invoke<boolean>('has_wmctrl');
|
||||
export const hasOsuWinello = async () => await invoke<boolean>('has_osuwinello');
|
||||
export const hasNet8 = async () => await invoke<boolean>('has_net8');
|
||||
export const encryptString = async (str: string, entropy: string) =>
|
||||
export const hasWMCTRL = async (): Promise<boolean> => await invoke<boolean>('has_wmctrl');
|
||||
export const hasOsuWinello = async (): Promise<boolean> => await invoke<boolean>('has_osuwinello');
|
||||
export const hasNet8 = async (): Promise<boolean> => await invoke<boolean>('has_net8');
|
||||
export const encryptString = async (str: string, entropy: string): Promise<string> =>
|
||||
await invoke<string>('encrypt_string', { string: str, entropy });
|
||||
export const downloadUpdate = async (
|
||||
url: string,
|
||||
progressCallback: (file: UpdateStatus) => void
|
||||
) => {
|
||||
const downloadStatusListen = await listen('download-progress', (event) =>
|
||||
progressCallback(event.payload as UpdateStatus)
|
||||
);
|
||||
try {
|
||||
await invoke<string>('download_ezpp_launcher_update', { url });
|
||||
} finally {
|
||||
downloadStatusListen();
|
||||
}
|
||||
};
|
||||
export const installUpdate = async () => await invoke('install_ezpp_launcher_update');
|
||||
export const getSkins = async (folder: string) =>
|
||||
await invoke<{ name: string; author: string | undefined; modified: number }[] | undefined>(
|
||||
'get_skins',
|
||||
{ folder }
|
||||
);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
const specialOrder = "'-!#$%&(),;@[]^_`{}~+=";
|
||||
|
||||
const priority = Object.fromEntries([...specialOrder].map((c, i) => [c, i]));
|
||||
|
||||
const osuSkinsCollator = new Intl.Collator(undefined, {
|
||||
numeric: true,
|
||||
sensitivity: 'base',
|
||||
});
|
||||
|
||||
export const sortSkins = (
|
||||
skins: { name: string; author: string | undefined; modified: number }[]
|
||||
) =>
|
||||
skins.sort((a, b) => {
|
||||
const pa = priority[a.name[0]];
|
||||
const pb = priority[b.name[0]];
|
||||
|
||||
if (pa !== undefined || pb !== undefined) {
|
||||
if (pa === undefined) return 1;
|
||||
if (pb === undefined) return -1;
|
||||
return pa - pb;
|
||||
}
|
||||
|
||||
return osuSkinsCollator.compare(a.name, b.name);
|
||||
});
|
||||
@@ -0,0 +1,528 @@
|
||||
import * as path from '@tauri-apps/api/path';
|
||||
import * as fs from '@tauri-apps/plugin-fs';
|
||||
import { convertFileSrc } from '@tauri-apps/api/core';
|
||||
import { active_custom_theme, custom_themes } from './global';
|
||||
import { calculateGitBlobSha, setGlobalVolume } from './utils';
|
||||
import { betterFetch } from '@better-fetch/fetch';
|
||||
import zip from 'jszip';
|
||||
import { SemVer } from 'semver';
|
||||
|
||||
export type Theme = {
|
||||
folder_name: string;
|
||||
name: string;
|
||||
version: string;
|
||||
author: string;
|
||||
scriptUrl: string;
|
||||
assets: string;
|
||||
preview: string;
|
||||
status: 'installed' | 'downloading' | 'extracting' | 'deleting' | 'not-installed';
|
||||
progress: number;
|
||||
updateAvailable: boolean;
|
||||
};
|
||||
|
||||
export type ThemeInfo = {
|
||||
name: string;
|
||||
version: string;
|
||||
apiVersion: string;
|
||||
author: string;
|
||||
entry: string;
|
||||
style: string;
|
||||
preview: string;
|
||||
};
|
||||
|
||||
export const getDownloadableThemes = async () => {
|
||||
const themes: Theme[] = [];
|
||||
|
||||
const downloadableThemes = await betterFetch<
|
||||
{
|
||||
name: string;
|
||||
version: string;
|
||||
author: string;
|
||||
}[]
|
||||
>('https://git.ez-pp.farm/EZPPFarm/EZPPLauncher-Themes/raw/branch/main/themes.json', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
|
||||
},
|
||||
});
|
||||
if (downloadableThemes.data) {
|
||||
for (const theme of downloadableThemes.data) {
|
||||
themes.push({
|
||||
folder_name: `${toSafeName(theme.name)}-${generateRandomString(16)}`,
|
||||
name: theme.name,
|
||||
version: theme.version,
|
||||
author: theme.author,
|
||||
scriptUrl: '',
|
||||
assets: '',
|
||||
preview: `https://git.ez-pp.farm/EZPPFarm/EZPPLauncher-Themes/raw/branch/main/previews/${toSafeName(theme.name)}.png`,
|
||||
status: 'not-installed',
|
||||
progress: 0,
|
||||
updateAvailable: false,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.error('Failed to fetch downloadable themes');
|
||||
console.error(downloadableThemes.error);
|
||||
}
|
||||
return themes;
|
||||
};
|
||||
|
||||
export const getThemes = async (): Promise<Theme[]> => {
|
||||
const themes: Theme[] = [];
|
||||
themes.push({
|
||||
folder_name: 'default',
|
||||
author: 'EZPPFarm',
|
||||
name: 'Default',
|
||||
version: '1.0.0',
|
||||
scriptUrl: '',
|
||||
assets: '',
|
||||
preview: '',
|
||||
status: 'installed',
|
||||
progress: 0,
|
||||
updateAvailable: false,
|
||||
});
|
||||
const folderPath = await path.join(await path.homeDir(), '.ezpplauncher', 'themes');
|
||||
if (await fs.exists(folderPath)) {
|
||||
const themeFolders = await fs.readDir(folderPath);
|
||||
for (const themeFolder of themeFolders) {
|
||||
const themeFolderPath = await path.join(folderPath, themeFolder.name);
|
||||
const themeConfigFilePath = await path.join(folderPath, themeFolder.name, 'theme.json');
|
||||
if (await fs.exists(themeConfigFilePath)) {
|
||||
const themeConfig = await fs.readTextFile(themeConfigFilePath);
|
||||
const theme = JSON.parse(themeConfig) as ThemeInfo;
|
||||
const scriptFile = await path.join(folderPath, themeFolder.name, theme.entry);
|
||||
if (await fs.exists(scriptFile)) {
|
||||
themes.push({
|
||||
folder_name: themeFolder.name,
|
||||
name: theme.name,
|
||||
version: theme.version,
|
||||
author: theme.author,
|
||||
scriptUrl: convertFileSrc(await path.normalize(`${themeFolderPath}/${theme.entry}`)),
|
||||
assets: convertFileSrc(await path.normalize(`${themeFolderPath}/assets`)),
|
||||
preview: convertFileSrc(
|
||||
await path.normalize(`${themeFolderPath}/assets/${theme.preview}`)
|
||||
),
|
||||
status: 'installed',
|
||||
progress: 0,
|
||||
updateAvailable: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return themes;
|
||||
};
|
||||
|
||||
function combineChunks(chunks: Uint8Array[], totalLength: number): Uint8Array {
|
||||
const result = new Uint8Array(totalLength);
|
||||
|
||||
let offset = 0;
|
||||
for (const chunk of chunks) {
|
||||
result.set(chunk, offset);
|
||||
offset += chunk.length;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export const downloadTheme = async (
|
||||
theme: Theme,
|
||||
force = false
|
||||
): Promise<{ success: boolean; error?: string }> => {
|
||||
if (theme.status !== 'not-installed' && !force) return { success: false };
|
||||
|
||||
custom_themes.update((themes) => {
|
||||
const matchedTheme = themes.find((t) => t.name === theme.name);
|
||||
if (matchedTheme) {
|
||||
matchedTheme.status = 'downloading';
|
||||
}
|
||||
return themes;
|
||||
});
|
||||
const themeFileName = `${toSafeName(theme.name)}.ezpplauncher-theme`;
|
||||
const themeContents = await betterFetch<{
|
||||
file_contents: {
|
||||
sha: string;
|
||||
download_url: string;
|
||||
};
|
||||
}>(
|
||||
`https://git.ez-pp.farm/api/v1/repos/EZPPFarm/EZPPLauncher-Themes/contents-ext/themes/${themeFileName}?ref=main`
|
||||
);
|
||||
if (themeContents.error) {
|
||||
custom_themes.update((themes) => {
|
||||
const matchedTheme = themes.find((t) => t.name === theme.name);
|
||||
if (matchedTheme) {
|
||||
matchedTheme.status = 'not-installed';
|
||||
}
|
||||
return themes;
|
||||
});
|
||||
return {
|
||||
success: false,
|
||||
error: themeContents.error.message ?? 'An unknown error occurred',
|
||||
};
|
||||
}
|
||||
const downloadUrl = `https://git.ez-pp.farm/EZPPFarm/EZPPLauncher-Themes/raw/branch/main/themes/${themeFileName}`;
|
||||
const downloadReq = await fetch(downloadUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
|
||||
},
|
||||
});
|
||||
|
||||
if (!downloadReq.ok || downloadReq.body === null) {
|
||||
custom_themes.update((themes) => {
|
||||
const matchedTheme = themes.find((t) => t.name === theme.name);
|
||||
if (matchedTheme) {
|
||||
matchedTheme.status = 'not-installed';
|
||||
}
|
||||
return themes;
|
||||
});
|
||||
return {
|
||||
success: false,
|
||||
error: 'Failed to download theme file.',
|
||||
};
|
||||
}
|
||||
const total = Number(downloadReq.headers.get('content-length')) || 0;
|
||||
const reader = downloadReq.body.getReader();
|
||||
let received = 0;
|
||||
const chunks = [];
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
chunks.push(value);
|
||||
received += value.length;
|
||||
const progress = received / total;
|
||||
custom_themes.update((themes) => {
|
||||
const matchedTheme = themes.find((t) => t.name === theme.name);
|
||||
if (matchedTheme) {
|
||||
matchedTheme.progress = progress;
|
||||
}
|
||||
return themes;
|
||||
});
|
||||
}
|
||||
|
||||
const fileBuffer = combineChunks(chunks, total);
|
||||
|
||||
const sha = calculateGitBlobSha(Buffer.from(fileBuffer));
|
||||
if (sha !== themeContents.data.file_contents.sha) {
|
||||
custom_themes.update((themes) => {
|
||||
const matchedTheme = themes.find((t) => t.name === theme.name);
|
||||
if (matchedTheme) {
|
||||
matchedTheme.status = 'not-installed';
|
||||
}
|
||||
return themes;
|
||||
});
|
||||
return {
|
||||
success: false,
|
||||
error: 'Failed to verify downloaded theme file hash.',
|
||||
};
|
||||
}
|
||||
|
||||
//TODO: check file hash
|
||||
|
||||
custom_themes.update((themes) => {
|
||||
const matchedTheme = themes.find((t) => t.name === theme.name);
|
||||
if (matchedTheme) {
|
||||
matchedTheme.status = 'extracting';
|
||||
}
|
||||
return themes;
|
||||
});
|
||||
const baseThemeFolder = await path.join(await path.homeDir(), '.ezpplauncher', 'themes');
|
||||
const themeFolder = await path.join(baseThemeFolder, toSafeName(theme.name));
|
||||
if (!(await fs.exists(baseThemeFolder))) await fs.mkdir(baseThemeFolder, { recursive: true });
|
||||
if (!(await fs.exists(themeFolder))) await fs.mkdir(themeFolder, { recursive: true });
|
||||
|
||||
const zipFile = await zip.loadAsync(fileBuffer);
|
||||
const totalFiles = Object.keys(zipFile.files).length;
|
||||
let extractedFiles = 0;
|
||||
for (const zipEntry of Object.keys(zipFile.files)) {
|
||||
const file = zipFile.file(zipEntry);
|
||||
if (file) {
|
||||
try {
|
||||
const fileData = await file.async('uint8array');
|
||||
const filePath = await path.join(themeFolder, zipEntry);
|
||||
const dirPath = await path.dirname(filePath);
|
||||
if (!(await fs.exists(dirPath))) await fs.mkdir(dirPath, { recursive: true });
|
||||
await new Promise((res) => setTimeout(res, 250));
|
||||
await fs.writeFile(filePath, fileData);
|
||||
extractedFiles++;
|
||||
custom_themes.update((themes) => {
|
||||
const matchedTheme = themes.find((t) => t.name === theme.name);
|
||||
if (matchedTheme) {
|
||||
matchedTheme.progress = extractedFiles / totalFiles;
|
||||
}
|
||||
return themes;
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
custom_themes.update((themes) => {
|
||||
const matchedTheme = themes.find((t) => t.name === theme.name);
|
||||
if (matchedTheme) {
|
||||
matchedTheme.status = 'not-installed';
|
||||
}
|
||||
return themes;
|
||||
});
|
||||
return {
|
||||
success: false,
|
||||
error: 'Failed to extract theme file.',
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
const themeInfo = await fs.readTextFile(await path.join(themeFolder, 'theme.json'));
|
||||
const themeInfoObj = JSON.parse(themeInfo) as ThemeInfo;
|
||||
const themeScriptUrl = convertFileSrc(
|
||||
await path.normalize(`${themeFolder}/${themeInfoObj.entry}`)
|
||||
);
|
||||
const themeAssets = convertFileSrc(await path.normalize(`${themeFolder}/assets`));
|
||||
const themePreview = convertFileSrc(
|
||||
await path.normalize(`${themeFolder}/assets/${themeInfoObj.preview}`)
|
||||
);
|
||||
|
||||
const downloadableThemes = await getDownloadableThemes();
|
||||
custom_themes.update((themes) => {
|
||||
const reloadedThemes = [...themes];
|
||||
for (const theme of downloadableThemes) {
|
||||
if (!reloadedThemes.find((t) => t.name === theme.name)) reloadedThemes.push(theme);
|
||||
|
||||
const installedTheme = reloadedThemes.find((t) => t.name === theme.name);
|
||||
if (installedTheme) {
|
||||
const installedThemeVersion = new SemVer(installedTheme.version);
|
||||
const downloadableThemeVersion = new SemVer(theme.version);
|
||||
if (downloadableThemeVersion.compare(installedThemeVersion) > 0) {
|
||||
installedTheme.updateAvailable = true;
|
||||
const index = reloadedThemes.findIndex((t) => t.name === theme.name);
|
||||
reloadedThemes[index] = installedTheme;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const installedThemes of reloadedThemes) {
|
||||
if (installedThemes.name === theme.name) {
|
||||
installedThemes.name = themeInfoObj.name;
|
||||
installedThemes.author = themeInfoObj.author;
|
||||
installedThemes.version = themeInfoObj.version;
|
||||
installedThemes.scriptUrl = themeScriptUrl;
|
||||
installedThemes.assets = themeAssets;
|
||||
installedThemes.preview = themePreview;
|
||||
installedThemes.status = 'installed';
|
||||
}
|
||||
}
|
||||
return reloadedThemes.sort((a, b) => {
|
||||
if (a.name === 'Default') return -1;
|
||||
if (b.name === 'Default') return 1;
|
||||
if (a.status === 'installed' && b.status !== 'installed') return -1;
|
||||
if (a.status !== 'installed' && b.status === 'installed') return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
});
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
};
|
||||
|
||||
export const loadTheme = async (theme: Theme, themeContainer: HTMLElement, volume = 0.15) => {
|
||||
active_custom_theme.set(theme);
|
||||
themeContainer.innerHTML = '';
|
||||
if (theme.scriptUrl.length > 0) {
|
||||
/* @vite-ignore */
|
||||
const themeScript = await import(theme.scriptUrl);
|
||||
themeScript.mountTheme(themeContainer, { assets: theme.assets });
|
||||
}
|
||||
setGlobalVolume(volume);
|
||||
};
|
||||
|
||||
export const deleteTheme = async (themeToUninstall: Theme) => {
|
||||
if (themeToUninstall.status !== 'installed') return false;
|
||||
const baseThemeFolder = await path.join(await path.homeDir(), '.ezpplauncher', 'themes');
|
||||
if (!(await fs.exists(baseThemeFolder))) return false;
|
||||
const themeFolder = await path.join(baseThemeFolder, themeToUninstall.folder_name);
|
||||
if (!(await fs.exists(themeFolder))) return false;
|
||||
custom_themes.update((themes) => {
|
||||
const matchedTheme = themes.find((t) => t.name === themeToUninstall.name);
|
||||
if (matchedTheme) {
|
||||
matchedTheme.status = 'deleting';
|
||||
}
|
||||
return themes;
|
||||
});
|
||||
await fs.remove(themeFolder, { recursive: true });
|
||||
const downloadableThemes = await getDownloadableThemes();
|
||||
custom_themes.update((themes) => {
|
||||
const reloadedThemes = [...themes];
|
||||
for (const theme of downloadableThemes) {
|
||||
if (theme.name === themeToUninstall.name) {
|
||||
const themeIndex = reloadedThemes.findIndex((t) => t.name === theme.name);
|
||||
if (themeIndex) {
|
||||
reloadedThemes.splice(themeIndex, 1);
|
||||
reloadedThemes.push(theme);
|
||||
}
|
||||
}
|
||||
|
||||
const installedTheme = reloadedThemes.find((t) => t.name === theme.name);
|
||||
if (installedTheme) {
|
||||
const installedThemeVersion = new SemVer(installedTheme.version);
|
||||
const downloadableThemeVersion = new SemVer(theme.version);
|
||||
if (downloadableThemeVersion.compare(installedThemeVersion) > 0) {
|
||||
installedTheme.updateAvailable = true;
|
||||
const index = reloadedThemes.findIndex((t) => t.name === theme.name);
|
||||
reloadedThemes[index] = installedTheme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return reloadedThemes.sort((a, b) => {
|
||||
if (a.name === 'Default') return -1;
|
||||
if (b.name === 'Default') return 1;
|
||||
if (a.status === 'installed' && b.status !== 'installed') return -1;
|
||||
if (a.status !== 'installed' && b.status === 'installed') return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
export const checkThemeFromFile = async (filePath: string) => {
|
||||
const normalizedFilePath = await path.normalize(filePath);
|
||||
if (!(await fs.exists(normalizedFilePath))) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'File not found',
|
||||
};
|
||||
}
|
||||
const fileBuffer = await fs.readFile(normalizedFilePath);
|
||||
|
||||
let themeInfo: ThemeInfo | undefined = undefined;
|
||||
|
||||
try {
|
||||
const zipFile = await zip.loadAsync(fileBuffer);
|
||||
|
||||
const themeConfig = zipFile.file('theme.json');
|
||||
if (!themeConfig) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Theme config file not found',
|
||||
};
|
||||
}
|
||||
const themeConfigData = await themeConfig.async('string');
|
||||
themeInfo = JSON.parse(themeConfigData) as {
|
||||
name: string;
|
||||
version: string;
|
||||
apiVersion: string;
|
||||
author: string;
|
||||
entry: string;
|
||||
style: string;
|
||||
preview: string;
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Could not read theme file',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: !!themeInfo,
|
||||
themeInfo,
|
||||
};
|
||||
};
|
||||
|
||||
export const importThemeFromFile = async (themeName: string, filePath: string) => {
|
||||
const baseThemeFolder = await path.join(await path.homeDir(), '.ezpplauncher', 'themes');
|
||||
const themeFolder = await path.join(baseThemeFolder, toSafeName(themeName));
|
||||
if (!(await fs.exists(baseThemeFolder))) await fs.mkdir(baseThemeFolder, { recursive: true });
|
||||
if (!(await fs.exists(themeFolder))) await fs.mkdir(themeFolder, { recursive: true });
|
||||
|
||||
const fileBuffer = await fs.readFile(filePath);
|
||||
const zipFile = await zip.loadAsync(fileBuffer);
|
||||
for (const zipEntry of Object.keys(zipFile.files)) {
|
||||
const file = zipFile.file(zipEntry);
|
||||
if (file) {
|
||||
try {
|
||||
const fileData = await file.async('uint8array');
|
||||
const filePath = await path.join(themeFolder, zipEntry);
|
||||
const dirPath = await path.dirname(filePath);
|
||||
if (!(await fs.exists(dirPath))) await fs.mkdir(dirPath, { recursive: true });
|
||||
await new Promise((res) => setTimeout(res, 250));
|
||||
await fs.writeFile(filePath, fileData);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return {
|
||||
success: false,
|
||||
error: 'Failed to extract theme file.',
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
const themeInfo = await fs.readTextFile(await path.join(themeFolder, 'theme.json'));
|
||||
const themeInfoObj = JSON.parse(themeInfo) as ThemeInfo;
|
||||
const themeScriptUrl = convertFileSrc(
|
||||
await path.normalize(`${themeFolder}/${themeInfoObj.entry}`)
|
||||
);
|
||||
const themeAssets = convertFileSrc(await path.normalize(`${themeFolder}/assets`));
|
||||
const themePreview = convertFileSrc(
|
||||
await path.normalize(`${themeFolder}/assets/${themeInfoObj.preview}`)
|
||||
);
|
||||
|
||||
const downloadableThemes = await getDownloadableThemes();
|
||||
custom_themes.update((themes) => {
|
||||
const reloadedThemes = [...themes];
|
||||
for (const theme of downloadableThemes) {
|
||||
if (!reloadedThemes.find((t) => t.name === theme.name)) reloadedThemes.push(theme);
|
||||
|
||||
const installedTheme = reloadedThemes.find((t) => t.name === theme.name);
|
||||
if (installedTheme) {
|
||||
const installedThemeVersion = new SemVer(installedTheme.version);
|
||||
const downloadableThemeVersion = new SemVer(theme.version);
|
||||
if (downloadableThemeVersion.compare(installedThemeVersion) > 0) {
|
||||
installedTheme.updateAvailable = true;
|
||||
const index = reloadedThemes.findIndex((t) => t.name === theme.name);
|
||||
reloadedThemes[index] = installedTheme;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const installedThemes of reloadedThemes) {
|
||||
if (installedThemes.name === themeName) {
|
||||
installedThemes.name = themeInfoObj.name;
|
||||
installedThemes.author = themeInfoObj.author;
|
||||
installedThemes.version = themeInfoObj.version;
|
||||
installedThemes.scriptUrl = themeScriptUrl;
|
||||
installedThemes.assets = themeAssets;
|
||||
installedThemes.preview = themePreview;
|
||||
installedThemes.status = 'installed';
|
||||
}
|
||||
}
|
||||
return reloadedThemes.sort((a, b) => {
|
||||
if (a.name === 'Default') return -1;
|
||||
if (b.name === 'Default') return 1;
|
||||
if (a.status === 'installed' && b.status !== 'installed') return -1;
|
||||
if (a.status !== 'installed' && b.status === 'installed') return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
});
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
};
|
||||
|
||||
export const toSafeName = (name: string) => {
|
||||
return (
|
||||
name
|
||||
.toLowerCase()
|
||||
.replace(/[<>:"/\\|?*]/g, '_')
|
||||
// eslint-disable-next-line no-control-regex
|
||||
.replace(/[\x00-\x1F\x7F]/g, '_')
|
||||
.replace(/[\s-]+/g, '_')
|
||||
.replace(/_+/g, '_')
|
||||
.replace(/[. ]+$/g, '_')
|
||||
);
|
||||
};
|
||||
|
||||
const generateRandomString = (length: number) => {
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
return Array.from({ length }, () =>
|
||||
characters.charAt(Math.floor(Math.random() * characters.length))
|
||||
).join('');
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
declare global {
|
||||
const umami: Umami;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {@link https://umami.is/docs/tracker-functions|Umami Docs}
|
||||
*/
|
||||
interface Umami {
|
||||
track(): Promise<string> | undefined;
|
||||
track(event_name: string, event_data?: Record<string, unknown>): Promise<string> | undefined;
|
||||
track(custom_payload: { website: string; [key: string]: unknown }): Promise<string> | undefined;
|
||||
track(
|
||||
callback: (props: {
|
||||
hostname: string;
|
||||
language: string;
|
||||
referrer: string;
|
||||
screen: string;
|
||||
title: string;
|
||||
url: string;
|
||||
website: string;
|
||||
}) => { website: string; [key: string]: unknown }
|
||||
): Promise<string> | undefined;
|
||||
|
||||
/** Pass in your own ID to identify a user. */
|
||||
identify(identity_id: string): Promise<void>;
|
||||
|
||||
/** Save data about the current session. */
|
||||
identify(identity_id: string, data: Record<string, unknown>): Promise<void>;
|
||||
|
||||
/** To save data without a unique ID, pass in only a JSON object. */
|
||||
identify(data: Record<string, unknown>): Promise<void>;
|
||||
}
|
||||
|
||||
export {};
|
||||
@@ -1,6 +1,8 @@
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { type ClassValue, clsx } from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import { custom_theme_audio_playing } from './global';
|
||||
import * as crypto from 'crypto-js';
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
@@ -44,7 +46,6 @@ export const formatTimeReadable = (initialSeconds: number) => {
|
||||
};
|
||||
|
||||
export const releaseStreamToReadable = (releaseStream: string) => {
|
||||
console.log(releaseStream.replaceAll(' ', '').toLowerCase());
|
||||
if (releaseStream.replaceAll(' ', '').toLowerCase() === 'cuttingedge') return 'Cutting Edge';
|
||||
return 'Stable';
|
||||
};
|
||||
@@ -100,3 +101,111 @@ export const urlIsValidImage = async (url: string) => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export function toURL(data: Buffer, type: string) {
|
||||
return URL.createObjectURL(new Blob([new Uint8Array(data)], { type }));
|
||||
}
|
||||
|
||||
export function setGlobalVolume(volume: number) {
|
||||
const mediaElements: NodeListOf<HTMLMediaElement> = document.querySelectorAll('audio, video');
|
||||
mediaElements.forEach((element) => {
|
||||
element.volume = volume;
|
||||
});
|
||||
}
|
||||
|
||||
export function fadeGlobalVolume(
|
||||
volumeFrom: number,
|
||||
volumeTo: number,
|
||||
duration: number,
|
||||
onDone?: () => void
|
||||
) {
|
||||
const mediaElements: NodeListOf<HTMLMediaElement> = document.querySelectorAll('audio, video');
|
||||
|
||||
const startTime = performance.now();
|
||||
|
||||
function animate() {
|
||||
const currentTime = performance.now();
|
||||
const elapsedTime = currentTime - startTime;
|
||||
const progress = Math.min(elapsedTime / duration, 1);
|
||||
|
||||
const interpolatedVolume = volumeFrom + (volumeTo - volumeFrom) * progress;
|
||||
|
||||
mediaElements.forEach((element) => {
|
||||
element.volume = interpolatedVolume;
|
||||
});
|
||||
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(animate);
|
||||
} else {
|
||||
if (onDone) onDone();
|
||||
}
|
||||
}
|
||||
|
||||
animate();
|
||||
}
|
||||
|
||||
export const pauseGlobalMedia = () => {
|
||||
const mediaElements: NodeListOf<HTMLMediaElement> = document.querySelectorAll('audio, video');
|
||||
mediaElements.forEach((element) => element.pause());
|
||||
};
|
||||
|
||||
export const resumeGlobalMedia = () => {
|
||||
const mediaElements: NodeListOf<HTMLMediaElement> = document.querySelectorAll('audio, video');
|
||||
mediaElements.forEach((element) => element.play());
|
||||
};
|
||||
|
||||
export const setCurrentTimeGlobalMedia = (time: number) => {
|
||||
const mediaElements: NodeListOf<HTMLMediaElement> = document.querySelectorAll('audio, video');
|
||||
mediaElements.forEach((element) => (element.currentTime = time));
|
||||
};
|
||||
|
||||
export function trackMediaContainer(node: HTMLElement) {
|
||||
const media = new Set<HTMLMediaElement>();
|
||||
|
||||
function update() {
|
||||
custom_theme_audio_playing.set(Array.from(media).some((el) => !el.paused));
|
||||
}
|
||||
|
||||
function register(el: HTMLMediaElement) {
|
||||
media.add(el);
|
||||
|
||||
const handler = () => update();
|
||||
el.addEventListener('play', handler);
|
||||
el.addEventListener('pause', handler);
|
||||
|
||||
return () => {
|
||||
media.delete(el);
|
||||
el.removeEventListener('play', handler);
|
||||
el.removeEventListener('pause', handler);
|
||||
};
|
||||
}
|
||||
|
||||
// find existing media inside the div
|
||||
node.querySelectorAll<HTMLMediaElement>('video, audio').forEach(register);
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
for (const m of mutations) {
|
||||
m.addedNodes.forEach((n) => {
|
||||
if (n instanceof HTMLMediaElement) register(n);
|
||||
if (n instanceof HTMLElement) {
|
||||
n.querySelectorAll<HTMLMediaElement>('video, audio').forEach(register);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(node, { childList: true, subtree: true });
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
observer.disconnect();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function calculateGitBlobSha(fileBuffer: Buffer): string {
|
||||
const header = Buffer.from(`blob ${fileBuffer.length}\0`);
|
||||
const store = Buffer.concat([header, fileBuffer]);
|
||||
|
||||
return crypto.SHA1(crypto.lib.WordArray.create(store)).toString(crypto.enc.Hex);
|
||||
}
|
||||
|
||||
@@ -5,13 +5,18 @@
|
||||
import Titlebar from '@/components/ui/titlebar/titlebar.svelte';
|
||||
import * as AlertDialog from '@/components/ui/alert-dialog';
|
||||
import {
|
||||
active_custom_theme,
|
||||
currentLoadingInfo,
|
||||
custom_theme_container,
|
||||
custom_theme_volume,
|
||||
custom_themes,
|
||||
discordPresence,
|
||||
firstStartup,
|
||||
launcherVersion,
|
||||
platform,
|
||||
presenceLoading,
|
||||
setupValues,
|
||||
trackingEnabled,
|
||||
} from '@/global';
|
||||
import { onMount } from 'svelte';
|
||||
import OsuCursor from '@/components/ui/osu-cursor/OsuCursor.svelte';
|
||||
@@ -24,14 +29,20 @@
|
||||
userSettings,
|
||||
} from '@/userSettings';
|
||||
import { Buffer } from 'buffer';
|
||||
import { Toaster } from '@/components/ui/sonner';
|
||||
import SileoToast from '@/components/ui/sileo/sileo-toast.svelte';
|
||||
import { userAuth } from '@/userAuthentication';
|
||||
import { encryptString, exit, getLauncherVersion, getPlatform } from '@/osuUtil';
|
||||
import { exit, getLauncherVersion, getPlatform } from '@/osuUtil';
|
||||
import Button from '@/components/ui/button/button.svelte';
|
||||
import * as presence from '@/presence';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
import '@fontsource/sora';
|
||||
import '@fontsource/space-mono';
|
||||
import { getDownloadableThemes, getThemes, loadTheme } from '@/themes';
|
||||
import { sileo } from 'sileo';
|
||||
import AnimatedBg from '@/components/ui/animated-bg/AnimatedBg.svelte';
|
||||
import { SemVer } from 'semver';
|
||||
import { trackMediaContainer } from '@/utils';
|
||||
|
||||
let { children } = $props();
|
||||
|
||||
@@ -94,8 +105,51 @@
|
||||
platform.set(await getPlatform());
|
||||
if ($platform !== 'windows' && $platform !== 'linux') unsupported_platform = true;
|
||||
const isFirstStartup = await $userSettings.init();
|
||||
firstStartup.set(isFirstStartup);
|
||||
$userAuth.init();
|
||||
|
||||
try {
|
||||
const themeVolume = $userSettings.value('volume').get(0.15);
|
||||
custom_theme_volume.set(themeVolume);
|
||||
currentLoadingInfo.set('Loading themes...');
|
||||
const downloadableThemes = await getDownloadableThemes();
|
||||
const themes = await getThemes();
|
||||
const combinedThemes = [...themes];
|
||||
for (const theme of downloadableThemes) {
|
||||
if (!combinedThemes.find((t) => t.name === theme.name)) combinedThemes.push(theme);
|
||||
const installedTheme = themes.find((t) => t.name === theme.name);
|
||||
if (installedTheme) {
|
||||
const installedThemeVersion = new SemVer(installedTheme.version);
|
||||
const downloadableThemeVersion = new SemVer(theme.version);
|
||||
if (downloadableThemeVersion.compare(installedThemeVersion) > 0) {
|
||||
installedTheme.updateAvailable = true;
|
||||
const index = combinedThemes.findIndex((t) => t.name === theme.name);
|
||||
combinedThemes[index] = installedTheme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
custom_themes.set(combinedThemes);
|
||||
const activeTheme = $userSettings.value('theme').get('Default');
|
||||
const theme = themes.find((theme) => theme.name === activeTheme);
|
||||
if (!theme) {
|
||||
$userSettings.value('theme').set('Default');
|
||||
await $userSettings.save();
|
||||
loadTheme(themes[0], $custom_theme_container!, themeVolume);
|
||||
} else {
|
||||
loadTheme(theme, $custom_theme_container!, themeVolume);
|
||||
}
|
||||
} catch {
|
||||
sileo.error({
|
||||
title: 'An error occured!',
|
||||
description: 'Failed to load theme',
|
||||
fill: '#181825',
|
||||
styles: {
|
||||
description: 'text-center!',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
currentLoadingInfo.set('Loading config...');
|
||||
const config_patching = $userSettings.value('patching');
|
||||
const config_custom_cursor = $userSettings.value('custom_cursor');
|
||||
@@ -103,6 +157,7 @@
|
||||
const config_reduce_animations = $userSettings.value('reduce_animations');
|
||||
const config_osu_installation_path = $userSettings.value('osu_installation_path');
|
||||
const config_discord_presence = $userSettings.value('discord_presence');
|
||||
const config_tracking_enabled = $userSettings.value('tracking_consent');
|
||||
|
||||
patch.set(config_patching.get(true));
|
||||
customCursor.set(config_custom_cursor.get(true));
|
||||
@@ -110,6 +165,9 @@
|
||||
reduceAnimations.set(config_reduce_animations.get(false));
|
||||
osuInstallationPath.set(config_osu_installation_path.get(''));
|
||||
discordPresence.set(config_discord_presence.get(true));
|
||||
if (config_tracking_enabled.exists()) {
|
||||
trackingEnabled.set(config_tracking_enabled.get(false));
|
||||
}
|
||||
|
||||
patch.subscribe((val) => config_patching.set(val));
|
||||
customCursor.subscribe((val) => config_custom_cursor.set(val));
|
||||
@@ -136,8 +194,6 @@
|
||||
presenceLoading.set(false);
|
||||
}
|
||||
} catch {}
|
||||
|
||||
firstStartup.set(isFirstStartup);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -145,7 +201,7 @@
|
||||
<OsuCursor smoothCursor={$cursorSmoothening} />
|
||||
{/if}
|
||||
|
||||
<Toaster richColors closeButton />
|
||||
<SileoToast position="top-center" fill="black" />
|
||||
|
||||
<Titlebar />
|
||||
|
||||
@@ -173,5 +229,19 @@
|
||||
</AlertDialog.Root>
|
||||
|
||||
<main>
|
||||
<div class="opacity-30">
|
||||
<div transition:fade={{ duration: $reduceAnimations ? 0 : 500 }}>
|
||||
<div
|
||||
class={$active_custom_theme && $active_custom_theme.name === 'Default'
|
||||
? 'hidden'
|
||||
: 'absolute z-0 top-0 left-0 w-full h-full object-cover object-center aspect-video'}
|
||||
bind:this={$custom_theme_container}
|
||||
use:trackMediaContainer
|
||||
></div>
|
||||
{#if ($active_custom_theme && $active_custom_theme.name === 'Default') || !$active_custom_theme}
|
||||
<AnimatedBg />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{@render children()}
|
||||
</main>
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { currentView } from '@/global';
|
||||
import { currentView, launcherVersion, trackingEnabled } from '@/global';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
const View = $derived($currentView);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
{#if $launcherVersion !== '' && $trackingEnabled}
|
||||
<script
|
||||
defer
|
||||
src="https://analytics.ez-pp.farm/script.js"
|
||||
data-website-id="b03f0013-64f0-42ce-85c0-abd56e8b3c64"
|
||||
data-tag={$launcherVersion}
|
||||
></script>
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
{#key View}
|
||||
<div in:fade={{ duration: 300 }}>
|
||||
<View />
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
osuBuild,
|
||||
osuStream,
|
||||
skins,
|
||||
skinsCount,
|
||||
} from '@/global';
|
||||
import {
|
||||
cursorSmoothness,
|
||||
@@ -28,25 +29,24 @@
|
||||
import Launch from './Launch.svelte';
|
||||
import { currentUser, userAuth } from '@/userAuthentication';
|
||||
import { ezppfarm } from '@/api/ezpp';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { currentUserInfo } from '@/data';
|
||||
import {
|
||||
getBeatmapSetsCount,
|
||||
getEZPPLauncherStreams,
|
||||
getReleaseStream,
|
||||
getSkin,
|
||||
getSkinsCount,
|
||||
getSkins,
|
||||
getVersion,
|
||||
isValidOsuFolder,
|
||||
} from '@/osuUtil';
|
||||
import { git } from '@/api/git';
|
||||
import { sileo } from 'sileo';
|
||||
import type { EZPPUser } from '@/types';
|
||||
|
||||
let ezppLogo: HTMLImageElement;
|
||||
let spinnerCircle: SVGCircleElement;
|
||||
let animateInterval: number | undefined;
|
||||
|
||||
//TODO: use this to check for updates upon launch
|
||||
|
||||
const doBPMAnimation = () => {
|
||||
if (animateInterval) return;
|
||||
animateInterval = window.setInterval(async () => {
|
||||
@@ -84,47 +84,69 @@
|
||||
|
||||
const username = $userAuth.value('username').get('');
|
||||
const password = $userAuth.value('password').get('');
|
||||
if (username.length > 0 && password.length > 0) {
|
||||
|
||||
const shouldLogin = username.length > 0 && password.length > 0;
|
||||
let userLoginResult: { message: string; user?: EZPPUser } = {
|
||||
message: 'An unknown error occured!',
|
||||
};
|
||||
|
||||
if (shouldLogin) {
|
||||
currentLoadingInfo.set('Logging in...');
|
||||
try {
|
||||
const loginResult = await ezppfarm.login(username, password);
|
||||
if (loginResult && loginResult.user) {
|
||||
toast.success('Login successful!', {
|
||||
description: `Welcome back, ${loginResult.user.name}!`,
|
||||
});
|
||||
userLoginResult = {
|
||||
message: `Welcome back, ${loginResult.user.name}!`,
|
||||
user: loginResult.user,
|
||||
};
|
||||
|
||||
currentUser.set(loginResult.user);
|
||||
} else {
|
||||
toast.error('Login failed!', {
|
||||
description: 'Please check your username and password.',
|
||||
});
|
||||
userLoginResult = {
|
||||
message: 'Please check your username and password.',
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
toast.error('Server error occurred during login.', {
|
||||
description: 'There was an issue connecting to the server. Please try again later.',
|
||||
});
|
||||
userLoginResult = {
|
||||
message: 'There was an issue connecting to the server. Please try again later.',
|
||||
};
|
||||
}
|
||||
}
|
||||
if ($currentUser) {
|
||||
currentLoadingInfo.set('Loading user info...');
|
||||
const userInfo = await ezppfarm.getUserInfo($currentUser.id);
|
||||
if (userInfo) {
|
||||
currentUserInfo.set(userInfo.player);
|
||||
try {
|
||||
currentLoadingInfo.set('Loading user info...');
|
||||
const userInfo = await ezppfarm.getUserInfo($currentUser.id);
|
||||
if (userInfo) {
|
||||
currentUserInfo.set(userInfo.player);
|
||||
|
||||
preferredMode.set(userInfo.player.info.preferred_mode);
|
||||
preferredType.set(userInfo.player.info.preferred_type);
|
||||
preferredMode.set(userInfo.player.info.preferred_mode);
|
||||
preferredType.set(userInfo.player.info.preferred_type);
|
||||
}
|
||||
} catch {
|
||||
userLoginResult = {
|
||||
message: 'There was an issue connecting to the server. Please try again later.',
|
||||
};
|
||||
currentUser.set(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$firstStartup) {
|
||||
/* const launcherTheme = $userSettings.value('launcherTheme').get('default');
|
||||
const them = THEMES.find((theme) => theme.name === launcherTheme);
|
||||
if (them) theme.set(them); */
|
||||
currentLoadingInfo.set('Checking osu installation path...');
|
||||
const validFolder = await isValidOsuFolder($osuInstallationPath);
|
||||
if (!validFolder) {
|
||||
osuInstallationPath.set('');
|
||||
$userSettings.value('osu_installation_path').del();
|
||||
await $userSettings.save();
|
||||
toast.error('Oops...', {
|
||||
sileo.error({
|
||||
title: 'Hmm...',
|
||||
description: 'Your previously set osu! installation path seems to be invalid.',
|
||||
fill: '#181825',
|
||||
styles: {
|
||||
description: 'text-center!',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
currentLoadingInfo.set('Getting osu version...');
|
||||
@@ -138,8 +160,14 @@
|
||||
if (beatmapSetCount !== null) beatmapSets.set(beatmapSetCount);
|
||||
|
||||
currentLoadingInfo.set('Counting skins...');
|
||||
const skinCount = await getSkinsCount($osuInstallationPath);
|
||||
if (skinCount !== null) skins.set(skinCount);
|
||||
const skins_list = await getSkins($osuInstallationPath);
|
||||
if (skins_list) {
|
||||
skins.set(skins_list);
|
||||
skinsCount.set(skins_list.length);
|
||||
} else {
|
||||
skinsCount.set(0);
|
||||
}
|
||||
|
||||
const skin: string = await getSkin($osuInstallationPath);
|
||||
currentSkin.set(skin);
|
||||
}
|
||||
@@ -174,7 +202,31 @@
|
||||
});
|
||||
setTimeout(() => {
|
||||
if ($firstStartup) currentView.set(SetupWizard);
|
||||
else currentView.set(Launch);
|
||||
else {
|
||||
currentView.set(Launch);
|
||||
if (shouldLogin) {
|
||||
if (userLoginResult.user) {
|
||||
sileo.success({
|
||||
title: 'Login successful!',
|
||||
description: userLoginResult.message,
|
||||
fill: '#181825',
|
||||
styles: {
|
||||
description: 'text-center!',
|
||||
},
|
||||
duration: 2500,
|
||||
});
|
||||
} else {
|
||||
sileo.error({
|
||||
title: 'Login failed!',
|
||||
description: userLoginResult.message,
|
||||
fill: '#181825',
|
||||
styles: {
|
||||
description: 'text-center!',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 250);
|
||||
};
|
||||
|
||||
@@ -202,19 +254,19 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col items-center justify-center mt-[50px] h-[calc(100vh-50px)] w-full">
|
||||
<div class="relative w-80 h-80 flex items-center justify-center">
|
||||
<div class="flex flex-col items-center justify-center h-[100vh] w-full z-10">
|
||||
<div class="relative w-80 h-80 flex items-center justify-center z-10">
|
||||
<svg
|
||||
class="absolute top-0 left-0 w-full h-full animate-spin"
|
||||
style="animation-duration: 5s;"
|
||||
viewBox="0 0 208 208"
|
||||
>
|
||||
<circle
|
||||
class="stroke-primary"
|
||||
cx="104"
|
||||
cy="104"
|
||||
r="90"
|
||||
fill="none"
|
||||
stroke="#ff0098"
|
||||
stroke-width="8"
|
||||
stroke-linecap="round"
|
||||
stroke-dasharray="180 385"
|
||||
@@ -229,5 +281,5 @@
|
||||
bind:this={ezppLogo}
|
||||
/>
|
||||
</div>
|
||||
<span class="text-theme-200 text-sm mt-5">{$currentLoadingInfo}</span>
|
||||
<span class="text-theme-200 text-sm mt-5 z-10">{$currentLoadingInfo}</span>
|
||||
</div>
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Logo from '$assets/logo.png';
|
||||
import { ezppfarm } from '@/api/ezpp';
|
||||
import Button from '@/components/ui/button/button.svelte';
|
||||
import Input from '@/components/ui/input/input.svelte';
|
||||
import Label from '@/components/ui/label/label.svelte';
|
||||
import { currentView } from '@/global';
|
||||
import { currentUser, userAuth } from '@/userAuthentication';
|
||||
import { animate } from 'animejs';
|
||||
import { LoaderCircle } from 'lucide-svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import Launch from './Launch.svelte';
|
||||
import { currentUserInfo } from '@/data';
|
||||
import { preferredMode, preferredType } from '@/userSettings';
|
||||
|
||||
let username = $state('');
|
||||
let password = $state('');
|
||||
let isLoading = $state(false);
|
||||
|
||||
let ezppLogo: HTMLImageElement | undefined = $state(undefined);
|
||||
|
||||
const logo_mouseenter = () => {
|
||||
if (ezppLogo) {
|
||||
animate(ezppLogo, {
|
||||
duration: 700,
|
||||
scale: 1.2,
|
||||
ease: (t: number) => Math.pow(2, -5 * t) * Math.sin((t - 0.075) * 20.94) + 1 - 0.0005 * t,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const logo_mouseleave = () => {
|
||||
if (ezppLogo) {
|
||||
animate(ezppLogo, {
|
||||
duration: 700,
|
||||
scale: 1,
|
||||
ease: (t: number) => (t - 1) ** 7 + 1,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const performLogin = async () => {
|
||||
isLoading = true;
|
||||
|
||||
try {
|
||||
const loginResult = await ezppfarm.login(username, password);
|
||||
if (loginResult && loginResult.user) {
|
||||
toast.success('Login successful!', {
|
||||
description: `Welcome back, ${loginResult.user.name}!`,
|
||||
});
|
||||
|
||||
$userAuth.value('username').set(username);
|
||||
$userAuth.value('password').set(password);
|
||||
await $userAuth.save();
|
||||
|
||||
currentUser.set(loginResult.user);
|
||||
currentView.set(Launch);
|
||||
} else {
|
||||
toast.error('Login failed!', {
|
||||
description: 'Please check your username and password.',
|
||||
});
|
||||
isLoading = false;
|
||||
}
|
||||
} catch {
|
||||
toast.error('Server error occurred during login.', {
|
||||
description: 'There was an issue connecting to the server. Please try again later.',
|
||||
});
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
if ($currentUser) {
|
||||
const userInfo = await ezppfarm.getUserInfo($currentUser.id);
|
||||
if (userInfo) {
|
||||
currentUserInfo.set(userInfo.player);
|
||||
|
||||
preferredMode.set(userInfo.player.info.preferred_mode);
|
||||
preferredType.set(userInfo.player.info.preferred_type);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="mt-[50px] h-[calc(100vh-50px)] w-full">
|
||||
<div class="w-full h-full flex flex-col items-center justify-center">
|
||||
<img
|
||||
src={Logo}
|
||||
alt="EZPPLauncher Logo"
|
||||
class="w-52 h-52 mb-2"
|
||||
bind:this={ezppLogo}
|
||||
onmouseenter={logo_mouseenter}
|
||||
onmouseleave={logo_mouseleave}
|
||||
/>
|
||||
<form onsubmit={performLogin} class="w-full max-w-sm">
|
||||
<div class="mb-4">
|
||||
<Label for="username" class="block text-sm font-medium">Username</Label>
|
||||
<Input
|
||||
class="mt-4 w-full bg-theme-900 border-theme-800"
|
||||
type="text"
|
||||
id="username"
|
||||
bind:value={username}
|
||||
disabled={isLoading}
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<Label for="password" class="block text-sm font-medium">Password</Label>
|
||||
<Input
|
||||
class="mt-4 w-full bg-theme-900 border-theme-800"
|
||||
type="password"
|
||||
id="password"
|
||||
bind:value={password}
|
||||
disabled={isLoading}
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
/>
|
||||
</div>
|
||||
<Button class="w-full" type="submit" disabled={isLoading}>
|
||||
{#if isLoading}
|
||||
<LoaderCircle class="animate-spin" />
|
||||
{:else}
|
||||
Login
|
||||
{/if}
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -5,7 +5,7 @@
|
||||
import { animate } from 'animejs';
|
||||
import { onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { Check, CheckCircle, CircleOff, Settings2 } from 'lucide-svelte';
|
||||
import { Check, CircleCheckBig, CircleOff, LoaderCircle } from 'lucide-svelte';
|
||||
import { open } from '@tauri-apps/plugin-dialog';
|
||||
import Checkbox from '@/components/ui/checkbox/checkbox.svelte';
|
||||
import {
|
||||
@@ -17,7 +17,18 @@
|
||||
userSettings,
|
||||
} from '@/userSettings';
|
||||
import Label from '@/components/ui/label/label.svelte';
|
||||
import { beatmapSets, currentSkin, currentView, osuBuild, osuStream, skins } from '@/global';
|
||||
import {
|
||||
beatmapSets,
|
||||
currentSkin,
|
||||
currentView,
|
||||
discordPresence,
|
||||
osuBuild,
|
||||
osuStream,
|
||||
platform,
|
||||
presenceLoading,
|
||||
skins,
|
||||
skinsCount,
|
||||
} from '@/global';
|
||||
import Launch from './Launch.svelte';
|
||||
import Confetti from 'svelte-confetti';
|
||||
import {
|
||||
@@ -25,10 +36,11 @@
|
||||
getBeatmapSetsCount,
|
||||
getReleaseStream,
|
||||
getSkin,
|
||||
getSkinsCount,
|
||||
getSkins,
|
||||
getVersion,
|
||||
isValidOsuFolder,
|
||||
} from '@/osuUtil';
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
let selectedStep = $state(1);
|
||||
const steps = ['Welcome', 'Locate your osu! Installation', 'Appearance Settings'];
|
||||
@@ -92,9 +104,12 @@
|
||||
beatmapSets.set(beatmapSetCount);
|
||||
}
|
||||
|
||||
const skinsCount: number | null = await getSkinsCount(osuInstallPath);
|
||||
if (skinsCount) {
|
||||
skins.set(skinsCount);
|
||||
const skins_list = await getSkins(osuInstallPath);
|
||||
if (skins_list) {
|
||||
skins.set(skins_list);
|
||||
skinsCount.set(skins_list.length);
|
||||
} else {
|
||||
skinsCount.set(0);
|
||||
}
|
||||
|
||||
const skin: string = await getSkin(osuInstallPath);
|
||||
@@ -119,7 +134,7 @@
|
||||
</script>
|
||||
|
||||
{#if wizardFinished}
|
||||
<div class="relative flex flex-col items-center justify-center mt-[50px] h-[calc(100vh-50px)]">
|
||||
<div class="relative flex flex-col items-center justify-center h-[100vh] z-50">
|
||||
<div class="absolute h-fit w-fit top-1/2 left-1/2">
|
||||
<Confetti amount={200} y={[-1, 1.5]} x={[-2.3, 2.3]} colorArray={['#C6A0F3']} />
|
||||
</div>
|
||||
@@ -128,15 +143,17 @@
|
||||
<Button class="mt-4" onclick={saveConfig}>Finish</Button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="grid grid-cols-[0.41fr_1fr] mt-[50px] h-[calc(100vh-50px)]">
|
||||
<div class="w-full h-full border-r border-theme-800/90 flex flex-col gap-6 p-3">
|
||||
<div class="grid grid-cols-[0.41fr_1fr] h-[100vh] z-50">
|
||||
<div
|
||||
class="w-full h-full border-r border-black/40 bg-black/40 backdrop-blur-md flex flex-col gap-6 p-3 z-50"
|
||||
>
|
||||
{#each steps as step, i (step)}
|
||||
<div
|
||||
class="flex flex-row items-center gap-2 border {selectedStep === i + 1
|
||||
? 'border-primary-800/30 bg-primary-900/30'
|
||||
? 'border-primary-600/30 bg-primary-700/30'
|
||||
: selectedStep > i
|
||||
? 'border-green-800/30 bg-green-900/30'
|
||||
: 'border-theme-800 bg-theme-900'} rounded-lg p-2 transition-all"
|
||||
: 'border-black/30 bg-black/30'} rounded-lg p-2 transition-all"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col items-center justify-center h-8 w-8 border-[2px] {selectedStep >
|
||||
@@ -160,10 +177,10 @@
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="flex flex-col gap-6 w-full h-full bg-theme-900/40 p-6">
|
||||
<div class="flex flex-col gap-6 w-full h-full backdrop-blur-md p-6 z-50">
|
||||
{#if selectedStep === 1}
|
||||
<div
|
||||
class="my-auto h-full w-full bg-theme-800/15 rounded-lg border border-900/60 p-6 flex flex-col items-center justify-center"
|
||||
class="my-auto h-full w-full bg-black/40 rounded-lg border border-black/40 p-6 mt-5 flex flex-col items-center justify-center"
|
||||
in:fade={{ duration: $reduceAnimations ? 0 : 200 }}
|
||||
>
|
||||
<img
|
||||
@@ -178,13 +195,13 @@
|
||||
<p class="text-muted-foreground mt-2">
|
||||
This setup wizard will guide you through the initial setup of EZPPLauncher.
|
||||
</p>
|
||||
<div class="bg-red-800/20 border border-red-900/20 text-red-500 p-4 rounded-lg mt-4">
|
||||
<div class="bg-red-800 border border-red-900 text-red-200 p-4 rounded-lg mt-4">
|
||||
Please make sure you have osu! installed on your system before proceeding.
|
||||
</div>
|
||||
</div>
|
||||
{:else if selectedStep === 2}
|
||||
<div
|
||||
class="my-auto h-full w-full bg-theme-800/15 rounded-lg border border-900/60 p-6 flex flex-col items-center justify-center"
|
||||
class="my-auto h-full w-full bg-black/40 rounded-lg border border-black/40 p-6 mt-5 flex flex-col items-center justify-center"
|
||||
in:fade={{ duration: $reduceAnimations ? 0 : 200 }}
|
||||
>
|
||||
<h1 class="text-3xl font-semibold">Locate your osu! Installation</h1>
|
||||
@@ -207,14 +224,14 @@
|
||||
{#if !manualSelect}
|
||||
{#if autoDetectedOsuPath}
|
||||
<div
|
||||
class="flex flex-row gap-3 bg-green-800/20 border border-green-900/20 text-green-500 p-4 rounded-lg mt-4"
|
||||
class="flex flex-row gap-3 bg-green-800 border border-green-900 text-green-500 p-4 rounded-lg mt-4"
|
||||
>
|
||||
<CheckCircle />
|
||||
<CircleCheckBig />
|
||||
<span>Auto-detected osu! installation path! Please check if its correct!</span>
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="flex flex-row gap-3 bg-red-800/20 border border-red-900/20 text-red-500 p-4 rounded-lg mt-4"
|
||||
class="flex flex-row gap-3 bg-red-800 border border-red-900 text-red-500 p-4 rounded-lg mt-4"
|
||||
>
|
||||
<CircleOff />
|
||||
<span>Could not auto-detect osu! installation path. Please select it manually.</span
|
||||
@@ -223,14 +240,14 @@
|
||||
{/if}
|
||||
{:else if manualSelectValid}
|
||||
<div
|
||||
class="flex flex-row gap-3 bg-green-800/20 border border-green-900/20 text-green-500 p-4 rounded-lg mt-4"
|
||||
class="flex flex-row gap-3 bg-green-800 border border-green-900 text-green-500 p-4 rounded-lg mt-4"
|
||||
>
|
||||
<CheckCircle />
|
||||
<CircleCheckBig />
|
||||
<span>Selected osu! installation path is valid!</span>
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="flex flex-row gap-3 bg-red-800/20 border border-red-900/20 text-red-500 p-4 rounded-lg mt-4"
|
||||
class="flex flex-row gap-3 bg-red-800 border border-red-900 text-red-500 p-4 rounded-lg mt-4"
|
||||
>
|
||||
<CircleOff />
|
||||
<span
|
||||
@@ -241,80 +258,103 @@
|
||||
{/if}
|
||||
</div>
|
||||
{:else if selectedStep === 3}
|
||||
<div
|
||||
class="bg-theme-900/90 flex flex-col justify-center gap-3 border border-theme-800/90 rounded-lg"
|
||||
in:fade={{ duration: $reduceAnimations ? 0 : 200 }}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-3 font-semibold text-xl px-3 pt-3">
|
||||
<Settings2 /> EZPPLauncher Settings
|
||||
</div>
|
||||
<div class="h-full w-full flex items-center justify-center">
|
||||
<div
|
||||
class="grid grid-cols-[1fr_auto] gap-y-5 items-center border-t border-theme-800 py-3 px-6"
|
||||
class="bg-black/40 backdrop-blur-sm py-8 px-8 rounded-lg"
|
||||
in:fade={{ duration: $reduceAnimations ? 0 : 200 }}
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-custom-cursor">Patching</Label>
|
||||
<div class="text-muted-foreground text-xs">Shows misses in Relax and Autopilot</div>
|
||||
</div>
|
||||
<Checkbox
|
||||
id="setting-custom-cursor"
|
||||
checked={$patch}
|
||||
onCheckedChange={async (e) => {
|
||||
patch.set(e);
|
||||
$userSettings.save();
|
||||
}}
|
||||
class="flex items-center justify-center w-5 h-5"
|
||||
></Checkbox>
|
||||
<div class="grid grid-cols-[1fr_auto] gap-y-5 items-center px-6">
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-patch">Patching</Label>
|
||||
<div class="text-muted-foreground text-xs">
|
||||
Shows misses in Relax and Autopilot {#if $platform !== 'windows'}<span
|
||||
class="text-red-500 bg-red-800/20 border border-red-600/20 p-0.5 mx-1 px-2 rounded-lg !text-[0.55rem]"
|
||||
>currently only on windows!</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<Checkbox
|
||||
id="setting-patch"
|
||||
checked={$platform === 'windows' ? $patch : false}
|
||||
disabled={$platform !== 'windows'}
|
||||
onCheckedChange={async (e) => {
|
||||
patch.set(e);
|
||||
}}
|
||||
class="flex items-center justify-center w-5 h-5"
|
||||
></Checkbox>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-custom-cursor">Lazer-Style Cursor</Label>
|
||||
<div class="text-muted-foreground text-xs">
|
||||
Enable a custom cursor in the Launcher like in the lazer build of osu!
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-custom-cursor">Lazer-Style Cursor</Label>
|
||||
<div class="text-muted-foreground text-xs">
|
||||
Enable a custom cursor in the Launcher like in the lazer build of osu!
|
||||
</div>
|
||||
</div>
|
||||
<Checkbox
|
||||
id="setting-custom-cursor"
|
||||
checked={$customCursor}
|
||||
onCheckedChange={async (e) => {
|
||||
if (!e) {
|
||||
cursorSmoothening.set(false);
|
||||
}
|
||||
customCursor.set(e);
|
||||
}}
|
||||
class="flex items-center justify-center w-5 h-5"
|
||||
></Checkbox>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-cursor-smoothening">Cursor Smoothening</Label>
|
||||
<div class="text-muted-foreground text-xs">
|
||||
Makes the custom cursor movement smoother.
|
||||
</div>
|
||||
</div>
|
||||
<Checkbox
|
||||
id="setting-cursor-smoothening"
|
||||
checked={$cursorSmoothening}
|
||||
onCheckedChange={async (e) => {
|
||||
if (!$customCursor) return;
|
||||
cursorSmoothening.set(e);
|
||||
}}
|
||||
disabled={!$customCursor}
|
||||
class="flex items-center justify-center w-5 h-5"
|
||||
></Checkbox>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-reduce-animations">Reduce Animations</Label>
|
||||
<div class="text-muted-foreground text-xs">
|
||||
Disables some animations in the Launcher to improve performance on low-end
|
||||
devices.
|
||||
</div>
|
||||
</div>
|
||||
<Checkbox
|
||||
id="setting-reduce-animations"
|
||||
checked={$reduceAnimations}
|
||||
onCheckedChange={async (e) => {
|
||||
reduceAnimations.set(e);
|
||||
}}
|
||||
class="flex items-center justify-center w-5 h-5"
|
||||
></Checkbox>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-rich-presence">Discord Rich Presence</Label>
|
||||
<div class="text-muted-foreground text-xs">
|
||||
Let other discord users show what you are doing right now 👀
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative">
|
||||
{#if $presenceLoading}
|
||||
<div class="-left-8 absolute" transition:fade>
|
||||
<LoaderCircle class="animate-spin" />
|
||||
</div>
|
||||
{/if}
|
||||
<Checkbox
|
||||
id="setting-rich-presence"
|
||||
bind:checked={$discordPresence}
|
||||
disabled={$presenceLoading}
|
||||
class="flex items-center justify-center w-5 h-5"
|
||||
></Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<Checkbox
|
||||
id="setting-custom-cursor"
|
||||
checked={$customCursor}
|
||||
onCheckedChange={async (e) => {
|
||||
if (!e) {
|
||||
cursorSmoothening.set(false);
|
||||
}
|
||||
customCursor.set(e);
|
||||
}}
|
||||
class="flex items-center justify-center w-5 h-5"
|
||||
></Checkbox>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-cursor-smoothening">Cursor Smoothening</Label>
|
||||
<div class="text-muted-foreground text-xs">
|
||||
Makes the custom cursor movement smoother.
|
||||
</div>
|
||||
</div>
|
||||
<Checkbox
|
||||
id="setting-cursor-smoothening"
|
||||
checked={$cursorSmoothening}
|
||||
onCheckedChange={async (e) => {
|
||||
if (!$customCursor) return;
|
||||
cursorSmoothening.set(e);
|
||||
}}
|
||||
disabled={!$customCursor}
|
||||
class="flex items-center justify-center w-5 h-5"
|
||||
></Checkbox>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-cursor-smoothening">Reduce Animations</Label>
|
||||
<div class="text-muted-foreground text-xs">
|
||||
Disables some animations in the Launcher to improve performance on low-end devices.
|
||||
</div>
|
||||
</div>
|
||||
<Checkbox
|
||||
id="setting-cursor-smoothening"
|
||||
checked={$reduceAnimations}
|
||||
onCheckedChange={async (e) => {
|
||||
reduceAnimations.set(e);
|
||||
}}
|
||||
disabled={!$customCursor}
|
||||
class="flex items-center justify-center w-5 h-5"
|
||||
></Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -332,7 +372,7 @@
|
||||
else selectedStep = Math.min(selectedStep + 1, steps.length);
|
||||
}}
|
||||
disabled={selectedStep > steps.length ||
|
||||
(selectedStep === 2 && osuInstallPath.length <= 0)}
|
||||
(selectedStep === 2 && !dev && osuInstallPath.length <= 0)}
|
||||
>{selectedStep >= steps.length ? 'Finish' : 'Next'}</Button
|
||||
>
|
||||
</div>
|
||||
|
||||