7 Commits
2.1.1 ... 2.3.2

Author SHA1 Message Date
acdd761652 UPDATE: Change proxy 2025-12-12 18:49:30 +07:00
e08b265ae8 FIX: Fail to start game 2025-11-05 23:33:34 +07:00
52134c2200 UPDATE: handler before start game 2025-11-05 20:44:41 +07:00
892ea44c17 UPDATE: Fix ui and add License 2025-10-20 18:11:37 +07:00
ca612797ee FIX: Drag drop, ui/ux 2025-10-20 17:20:16 +07:00
787962c6d0 UPDATE: Backgroud setting, Remake ui/ux 2025-10-19 23:37:04 +07:00
09434fcc5b UPDATE: System tray 2025-10-13 09:09:55 +07:00
49 changed files with 713 additions and 349 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Firefly Shelter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -22,6 +22,11 @@ build:
wails3 build wails3 build
@echo Done! @echo Done!
generate:
@echo Generating bindings...
wails3 generate bindings -ts
@echo Done!
release: release:
@echo Building release application... @echo Building release application...
wails3 package wails3 package

View File

@@ -15,7 +15,7 @@
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security> <security>
<requestedPrivileges> <requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/> <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges> </requestedPrivileges>
</security> </security>
</trustInfo> </trustInfo>

View File

@@ -28,9 +28,30 @@ export function GetCurrentLauncherVersion() {
return $Call.ByID(3575133982); return $Call.ByID(3575133982);
} }
/**
* @returns {$CancellablePromise<[boolean, string]>}
*/
export function HideApp() {
return $Call.ByID(88003266);
}
/**
* @returns {$CancellablePromise<[boolean, string]>}
*/
export function MaximizeApp() {
return $Call.ByID(1257306588);
}
/** /**
* @returns {$CancellablePromise<[boolean, string]>} * @returns {$CancellablePromise<[boolean, string]>}
*/ */
export function MinimizeApp() { export function MinimizeApp() {
return $Call.ByID(3434614194); return $Call.ByID(3434614194);
} }
/**
* @returns {$CancellablePromise<[boolean, string]>}
*/
export function RestoreApp() {
return $Call.ByID(3115625834);
}

View File

@@ -31,6 +31,22 @@ export function FileExistsInZip(archivePath, fileInside) {
return $Call.ByID(2509699047, archivePath, fileInside); return $Call.ByID(2509699047, archivePath, fileInside);
} }
/**
* @param {string} path
* @returns {$CancellablePromise<string>}
*/
export function GetDir(path) {
return $Call.ByID(1744445742, path);
}
/**
* @param {string[]} paths
* @returns {$CancellablePromise<string>}
*/
export function Join(...paths) {
return $Call.ByID(2460588289, paths);
}
/** /**
* @param {string} path * @param {string} path
* @returns {$CancellablePromise<[boolean, string]>} * @returns {$CancellablePromise<[boolean, string]>}
@@ -56,7 +72,15 @@ export function PickFolder() {
/** /**
* @param {string} path * @param {string} path
* @returns {$CancellablePromise<boolean>} * @returns {$CancellablePromise<void>}
*/
export function RemoveFile(path) {
return $Call.ByID(3206735043, path);
}
/**
* @param {string} path
* @returns {$CancellablePromise<[boolean, string]>}
*/ */
export function StartApp(path) { export function StartApp(path) {
return $Call.ByID(1267568402, path); return $Call.ByID(1267568402, path);
@@ -64,7 +88,7 @@ export function StartApp(path) {
/** /**
* @param {string} path * @param {string} path
* @returns {$CancellablePromise<boolean>} * @returns {$CancellablePromise<[boolean, string]>}
*/ */
export function StartWithConsole(path) { export function StartWithConsole(path) {
return $Call.ByID(3249271428, path); return $Call.ByID(3249271428, path);

View File

@@ -43,13 +43,6 @@ export function GetLatestServerVersion() {
return $Call.ByID(2918980975); return $Call.ByID(2918980975);
} }
/**
* @returns {$CancellablePromise<void>}
*/
export function UnzipProxy() {
return $Call.ByID(2563246729);
}
/** /**
* @returns {$CancellablePromise<void>} * @returns {$CancellablePromise<void>}
*/ */

View File

@@ -0,0 +1,9 @@
//@ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import { Create as $Create } from "@wailsio/runtime";
Object.freeze($Create.Events);

View File

@@ -0,0 +1,2 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" data-theme="dracula">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
@@ -9,7 +9,7 @@
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
</body> </body>

View File

@@ -8,7 +8,7 @@
"name": "react-ts-latest", "name": "react-ts-latest",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@tailwindcss/vite": "^4.1.14", "@tailwindcss/vite": "^4.1.16",
"@tanstack/react-router": "^1.131.27", "@tanstack/react-router": "^1.131.27",
"@tanstack/react-router-devtools": "^1.131.27", "@tanstack/react-router-devtools": "^1.131.27",
"lucide-react": "^0.541.0", "lucide-react": "^0.541.0",
@@ -16,8 +16,9 @@
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"react": "^19.1.1", "react": "^19.1.1",
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"react-easy-crop": "^5.5.3",
"react-toastify": "^11.0.5", "react-toastify": "^11.0.5",
"tailwindcss": "^4.1.14", "tailwindcss": "^4.1.16",
"zustand": "^5.0.8" "zustand": "^5.0.8"
}, },
"devDependencies": { "devDependencies": {
@@ -30,7 +31,7 @@
"@typescript-eslint/parser": "^8.40.0", "@typescript-eslint/parser": "^8.40.0",
"@vitejs/plugin-react": "^5.0.1", "@vitejs/plugin-react": "^5.0.1",
"@wailsio/runtime": "^3.0.0-alpha.66", "@wailsio/runtime": "^3.0.0-alpha.66",
"daisyui": "^5.1.27", "daisyui": "^5.4.4",
"eslint": "^9.34.0", "eslint": "^9.34.0",
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-react-refresh": "^0.4.20",
@@ -1160,18 +1161,6 @@
"url": "https://github.com/sponsors/nzakas" "url": "https://github.com/sponsors/nzakas"
} }
}, },
"node_modules/@isaacs/fs-minipass": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
"license": "ISC",
"dependencies": {
"minipass": "^7.0.4"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@jridgewell/gen-mapping": { "node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13", "version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@@ -1285,52 +1274,47 @@
] ]
}, },
"node_modules/@tailwindcss/node": { "node_modules/@tailwindcss/node": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.16.tgz",
"integrity": "sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==", "integrity": "sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/remapping": "^2.3.4", "@jridgewell/remapping": "^2.3.4",
"enhanced-resolve": "^5.18.3", "enhanced-resolve": "^5.18.3",
"jiti": "^2.6.0", "jiti": "^2.6.1",
"lightningcss": "1.30.1", "lightningcss": "1.30.2",
"magic-string": "^0.30.19", "magic-string": "^0.30.19",
"source-map-js": "^1.2.1", "source-map-js": "^1.2.1",
"tailwindcss": "4.1.14" "tailwindcss": "4.1.16"
} }
}, },
"node_modules/@tailwindcss/oxide": { "node_modules/@tailwindcss/oxide": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.16.tgz",
"integrity": "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==", "integrity": "sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg==",
"hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": {
"detect-libc": "^2.0.4",
"tar": "^7.5.1"
},
"engines": { "engines": {
"node": ">= 10" "node": ">= 10"
}, },
"optionalDependencies": { "optionalDependencies": {
"@tailwindcss/oxide-android-arm64": "4.1.14", "@tailwindcss/oxide-android-arm64": "4.1.16",
"@tailwindcss/oxide-darwin-arm64": "4.1.14", "@tailwindcss/oxide-darwin-arm64": "4.1.16",
"@tailwindcss/oxide-darwin-x64": "4.1.14", "@tailwindcss/oxide-darwin-x64": "4.1.16",
"@tailwindcss/oxide-freebsd-x64": "4.1.14", "@tailwindcss/oxide-freebsd-x64": "4.1.16",
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.16",
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.14", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.16",
"@tailwindcss/oxide-linux-arm64-musl": "4.1.14", "@tailwindcss/oxide-linux-arm64-musl": "4.1.16",
"@tailwindcss/oxide-linux-x64-gnu": "4.1.14", "@tailwindcss/oxide-linux-x64-gnu": "4.1.16",
"@tailwindcss/oxide-linux-x64-musl": "4.1.14", "@tailwindcss/oxide-linux-x64-musl": "4.1.16",
"@tailwindcss/oxide-wasm32-wasi": "4.1.14", "@tailwindcss/oxide-wasm32-wasi": "4.1.16",
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.14", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.16",
"@tailwindcss/oxide-win32-x64-msvc": "4.1.14" "@tailwindcss/oxide-win32-x64-msvc": "4.1.16"
} }
}, },
"node_modules/@tailwindcss/oxide-android-arm64": { "node_modules/@tailwindcss/oxide-android-arm64": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.16.tgz",
"integrity": "sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==", "integrity": "sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1344,9 +1328,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-darwin-arm64": { "node_modules/@tailwindcss/oxide-darwin-arm64": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.16.tgz",
"integrity": "sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==", "integrity": "sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1360,9 +1344,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-darwin-x64": { "node_modules/@tailwindcss/oxide-darwin-x64": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.16.tgz",
"integrity": "sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==", "integrity": "sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1376,9 +1360,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-freebsd-x64": { "node_modules/@tailwindcss/oxide-freebsd-x64": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.16.tgz",
"integrity": "sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==", "integrity": "sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1392,9 +1376,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.16.tgz",
"integrity": "sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==", "integrity": "sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -1408,9 +1392,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": { "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.16.tgz",
"integrity": "sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==", "integrity": "sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1424,9 +1408,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-linux-arm64-musl": { "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.16.tgz",
"integrity": "sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==", "integrity": "sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1440,9 +1424,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-linux-x64-gnu": { "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.16.tgz",
"integrity": "sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==", "integrity": "sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1456,9 +1440,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-linux-x64-musl": { "node_modules/@tailwindcss/oxide-linux-x64-musl": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.16.tgz",
"integrity": "sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==", "integrity": "sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1472,9 +1456,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-wasm32-wasi": { "node_modules/@tailwindcss/oxide-wasm32-wasi": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.16.tgz",
"integrity": "sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==", "integrity": "sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q==",
"bundleDependencies": [ "bundleDependencies": [
"@napi-rs/wasm-runtime", "@napi-rs/wasm-runtime",
"@emnapi/core", "@emnapi/core",
@@ -1492,7 +1476,7 @@
"@emnapi/core": "^1.5.0", "@emnapi/core": "^1.5.0",
"@emnapi/runtime": "^1.5.0", "@emnapi/runtime": "^1.5.0",
"@emnapi/wasi-threads": "^1.1.0", "@emnapi/wasi-threads": "^1.1.0",
"@napi-rs/wasm-runtime": "^1.0.5", "@napi-rs/wasm-runtime": "^1.0.7",
"@tybys/wasm-util": "^0.10.1", "@tybys/wasm-util": "^0.10.1",
"tslib": "^2.4.0" "tslib": "^2.4.0"
}, },
@@ -1501,9 +1485,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.16.tgz",
"integrity": "sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==", "integrity": "sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1517,9 +1501,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-win32-x64-msvc": { "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.16.tgz",
"integrity": "sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==", "integrity": "sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1533,14 +1517,14 @@
} }
}, },
"node_modules/@tailwindcss/vite": { "node_modules/@tailwindcss/vite": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.14.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.16.tgz",
"integrity": "sha512-BoFUoU0XqgCUS1UXWhmDJroKKhNXeDzD7/XwabjkDIAbMnc4ULn5e2FuEuBbhZ6ENZoSYzKlzvZ44Yr6EUDUSA==", "integrity": "sha512-bbguNBcDxsRmi9nnlWJxhfDWamY3lmcyACHcdO1crxfzuLpOhHLLtEIN/nCbbAtj5rchUgQD17QVAKi1f7IsKg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tailwindcss/node": "4.1.14", "@tailwindcss/node": "4.1.16",
"@tailwindcss/oxide": "4.1.14", "@tailwindcss/oxide": "4.1.16",
"tailwindcss": "4.1.14" "tailwindcss": "4.1.16"
}, },
"peerDependencies": { "peerDependencies": {
"vite": "^5.2.0 || ^6 || ^7" "vite": "^5.2.0 || ^6 || ^7"
@@ -2440,15 +2424,6 @@
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
"node_modules/chownr": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/clsx": { "node_modules/clsx": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
@@ -2520,9 +2495,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/daisyui": { "node_modules/daisyui": {
"version": "5.1.27", "version": "5.4.4",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.1.27.tgz", "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.4.4.tgz",
"integrity": "sha512-oCC2RwjrGRPTeEpaXoNmYydzVfSRdyJCthFsi/Q5PErAvaoD8kDarxlW+wiPAx2WmM8W8lXvyAHJUqjObCMWOQ==", "integrity": "sha512-FEfdwmGdb3ZbtYN3OqaZn/RMarlZTPOv6mWpGUo7KX42RkcBanEZk5tgYp2ZgirKl7QvH8pCiwpuy55wi2dHyQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
@@ -3356,9 +3331,9 @@
} }
}, },
"node_modules/lightningcss": { "node_modules/lightningcss": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
"license": "MPL-2.0", "license": "MPL-2.0",
"dependencies": { "dependencies": {
"detect-libc": "^2.0.3" "detect-libc": "^2.0.3"
@@ -3371,22 +3346,43 @@
"url": "https://opencollective.com/parcel" "url": "https://opencollective.com/parcel"
}, },
"optionalDependencies": { "optionalDependencies": {
"lightningcss-darwin-arm64": "1.30.1", "lightningcss-android-arm64": "1.30.2",
"lightningcss-darwin-x64": "1.30.1", "lightningcss-darwin-arm64": "1.30.2",
"lightningcss-freebsd-x64": "1.30.1", "lightningcss-darwin-x64": "1.30.2",
"lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-freebsd-x64": "1.30.2",
"lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.2",
"lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.2",
"lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.2",
"lightningcss-linux-x64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.2",
"lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-linux-x64-musl": "1.30.2",
"lightningcss-win32-x64-msvc": "1.30.1" "lightningcss-win32-arm64-msvc": "1.30.2",
"lightningcss-win32-x64-msvc": "1.30.2"
}
},
"node_modules/lightningcss-android-arm64": {
"version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
"integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
"cpu": [
"arm64"
],
"license": "MPL-2.0",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
} }
}, },
"node_modules/lightningcss-darwin-arm64": { "node_modules/lightningcss-darwin-arm64": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
"integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -3404,9 +3400,9 @@
} }
}, },
"node_modules/lightningcss-darwin-x64": { "node_modules/lightningcss-darwin-x64": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
"integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -3424,9 +3420,9 @@
} }
}, },
"node_modules/lightningcss-freebsd-x64": { "node_modules/lightningcss-freebsd-x64": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
"integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -3444,9 +3440,9 @@
} }
}, },
"node_modules/lightningcss-linux-arm-gnueabihf": { "node_modules/lightningcss-linux-arm-gnueabihf": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
"integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -3464,9 +3460,9 @@
} }
}, },
"node_modules/lightningcss-linux-arm64-gnu": { "node_modules/lightningcss-linux-arm64-gnu": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
"integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -3484,9 +3480,9 @@
} }
}, },
"node_modules/lightningcss-linux-arm64-musl": { "node_modules/lightningcss-linux-arm64-musl": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
"integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -3504,9 +3500,9 @@
} }
}, },
"node_modules/lightningcss-linux-x64-gnu": { "node_modules/lightningcss-linux-x64-gnu": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
"integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -3524,9 +3520,9 @@
} }
}, },
"node_modules/lightningcss-linux-x64-musl": { "node_modules/lightningcss-linux-x64-musl": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
"integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -3544,9 +3540,9 @@
} }
}, },
"node_modules/lightningcss-win32-arm64-msvc": { "node_modules/lightningcss-win32-arm64-msvc": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
"integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -3564,9 +3560,9 @@
} }
}, },
"node_modules/lightningcss-win32-x64-msvc": { "node_modules/lightningcss-win32-x64-msvc": {
"version": "1.30.1", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
"integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -3626,9 +3622,9 @@
} }
}, },
"node_modules/magic-string": { "node_modules/magic-string": {
"version": "0.30.19", "version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5" "@jridgewell/sourcemap-codec": "^1.5.5"
@@ -3674,27 +3670,6 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/minizlib": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
"integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
"license": "MIT",
"dependencies": {
"minipass": "^7.1.2"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/motion": { "node_modules/motion": {
"version": "12.23.22", "version": "12.23.22",
"resolved": "https://registry.npmjs.org/motion/-/motion-12.23.22.tgz", "resolved": "https://registry.npmjs.org/motion/-/motion-12.23.22.tgz",
@@ -3783,6 +3758,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/normalize-wheel": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
"integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==",
"license": "BSD-3-Clause"
},
"node_modules/optionator": { "node_modules/optionator": {
"version": "0.9.4", "version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -4000,6 +3981,20 @@
"react": "^19.2.0" "react": "^19.2.0"
} }
}, },
"node_modules/react-easy-crop": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.5.3.tgz",
"integrity": "sha512-iKwFTnAsq+IVuyF6N0Q3zjRx9DG1NMySkwWxVfM/xAOeHYH1vhvM+V2kFiq5HOIQGWouITjfltCx54mbDpMpmA==",
"license": "MIT",
"dependencies": {
"normalize-wheel": "^1.0.1",
"tslib": "^2.0.1"
},
"peerDependencies": {
"react": ">=16.4.0",
"react-dom": ">=16.4.0"
}
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.17.0", "version": "0.17.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
@@ -4261,9 +4256,9 @@
} }
}, },
"node_modules/tailwindcss": { "node_modules/tailwindcss": {
"version": "4.1.14", "version": "4.1.16",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.14.tgz", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.16.tgz",
"integrity": "sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==", "integrity": "sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/tapable": { "node_modules/tapable": {
@@ -4279,31 +4274,6 @@
"url": "https://opencollective.com/webpack" "url": "https://opencollective.com/webpack"
} }
}, },
"node_modules/tar": {
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.1.tgz",
"integrity": "sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==",
"license": "ISC",
"dependencies": {
"@isaacs/fs-minipass": "^4.0.0",
"chownr": "^3.0.0",
"minipass": "^7.1.2",
"minizlib": "^3.1.0",
"yallist": "^5.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/tar/node_modules/yallist": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/tiny-invariant": { "node_modules/tiny-invariant": {
"version": "1.3.3", "version": "1.3.3",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",

View File

@@ -11,7 +11,7 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/vite": "^4.1.14", "@tailwindcss/vite": "^4.1.16",
"@tanstack/react-router": "^1.131.27", "@tanstack/react-router": "^1.131.27",
"@tanstack/react-router-devtools": "^1.131.27", "@tanstack/react-router-devtools": "^1.131.27",
"lucide-react": "^0.541.0", "lucide-react": "^0.541.0",
@@ -19,8 +19,9 @@
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"react": "^19.1.1", "react": "^19.1.1",
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"react-easy-crop": "^5.5.3",
"react-toastify": "^11.0.5", "react-toastify": "^11.0.5",
"tailwindcss": "^4.1.14", "tailwindcss": "^4.1.16",
"zustand": "^5.0.8" "zustand": "^5.0.8"
}, },
"devDependencies": { "devDependencies": {
@@ -33,7 +34,7 @@
"@typescript-eslint/parser": "^8.40.0", "@typescript-eslint/parser": "^8.40.0",
"@vitejs/plugin-react": "^5.0.1", "@vitejs/plugin-react": "^5.0.1",
"@wailsio/runtime": "^3.0.0-alpha.66", "@wailsio/runtime": "^3.0.0-alpha.66",
"daisyui": "^5.1.27", "daisyui": "^5.4.4",
"eslint": "^9.34.0", "eslint": "^9.34.0",
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-react-refresh": "^0.4.20",

BIN
frontend/public/bg-1.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

BIN
frontend/public/bg-10.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

BIN
frontend/public/bg-11.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

BIN
frontend/public/bg-12.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

BIN
frontend/public/bg-13.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

BIN
frontend/public/bg-16.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

BIN
frontend/public/bg-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
frontend/public/bg-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
frontend/public/bg-5.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

BIN
frontend/public/bg-6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
frontend/public/bg-7.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

BIN
frontend/public/bg-8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
frontend/public/bg-9.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -0,0 +1,180 @@
'use client'
import { useState, useRef } from 'react'
import { X, Image as ImageIcon, Plus, Upload, Check } from 'lucide-react'
import useSettingStore from '@/stores/settingStore'
import Cropper from 'react-easy-crop'
import getCroppedImg from '@/utils/cropImage'
const initialImages = {
"bg-1": "bg-1.jpeg",
"bg-2": "bg-2.png",
"bg-3": "bg-3.png",
"bg-6": "bg-6.png",
"bg-7": "bg-7.jpeg",
"bg-8": "bg-8.png",
"bg-9": "bg-9.jpeg",
"bg-10": "bg-10.jpg",
"bg-11": "bg-11.jpeg",
"bg-12": "bg-12.jpg",
"bg-13": "bg-13.jpg",
"bg-16": "bg-16.jpg",
}
export const BackgroundSelector = () => {
const [isOpen, setIsOpen] = useState(false)
const [newUrl, setNewUrl] = useState('')
const [croppingImage, setCroppingImage] = useState<string | null>(null)
const [crop, setCrop] = useState({ x: 0, y: 0 })
const [zoom, setZoom] = useState(1)
const [croppedAreaPixels, setCroppedAreaPixels] = useState<any>(null)
const { background, setBackground, extraBackgrounds, setExtraBackgrounds } = useSettingStore()
const fileInputRef = useRef<HTMLInputElement>(null)
const handleSelect = (img: string) => {
setIsOpen(false)
setBackground(img)
}
const handleAddUrl = () => {
if (!newUrl.trim()) return setCroppingImage(newUrl)
setNewUrl('')
}
const handleRemoveExtra = (url: string) => {
setExtraBackgrounds(extraBackgrounds.filter(bg => bg !== url))
}
const handleUploadFile = (file: File) => {
const reader = new FileReader()
reader.onload = () => setCroppingImage(reader.result as string)
reader.readAsDataURL(file)
}
const handleCropComplete = async () => {
if (!croppingImage || !croppedAreaPixels) return
const croppedBase64 = await getCroppedImg(croppingImage, croppedAreaPixels)
setExtraBackgrounds([croppedBase64, ...extraBackgrounds])
setCroppingImage(null)
}
const allBackgrounds = [...extraBackgrounds, ...Object.values(initialImages)]
return (
<div className="flex flex-col items-center justify-center gap-4">
<div className="tooltip tooltip-right" data-tip="Select Background">
<button
className="group btn btn-primary btn-circle flex items-center justify-center shadow-md transition-all duration-300 hover:scale-110 hover:shadow-lg hover:bg-primary/80"
onClick={() => setIsOpen(true)}
>
<ImageIcon size={22} className="text-white transition-all duration-300 group-hover:rotate-6 group-hover:scale-110 group-hover:text-yellow-300" />
</button>
</div>
{isOpen && (
<div className="fixed inset-0 z-40 flex items-center justify-center bg-base-200/60 pt-10">
<div className="bg-base-200 text-white rounded-xl shadow-xl p-6 w-[90%] max-w-2xl relative">
<button className="btn btn-ghost btn-circle absolute top-3 right-3" onClick={() => setIsOpen(false)}>
<X size={20} />
</button>
<h2 className="text-lg font-semibold mb-4">Choose Background</h2>
{/* Add via URL */}
<div className="flex gap-2 mb-4">
<input
type="text"
placeholder="Paste image URL (https://...)"
className="input input-bordered w-full text-info"
value={newUrl}
onChange={(e) => setNewUrl(e.target.value)}
/>
<button className="btn btn-success flex items-center gap-1" onClick={handleAddUrl}>
<Plus size={16} /> Add
</button>
</div>
{/* Upload from computer */}
<div className="flex mb-4">
<button
className="btn btn-warning flex items-center gap-1"
onClick={() => fileInputRef.current?.click()}
>
<Upload size={16} /> Upload from computer
</button>
<input
type="file"
accept="image/*"
className="hidden"
ref={fileInputRef}
onChange={(e) => {
const file = e.target.files?.[0]
if (file) handleUploadFile(file)
e.target.value = ''
}}
/>
</div>
{/* Crop Modal */}
{croppingImage && (
<div className="fixed inset-0 z-60 flex flex-col items-center justify-center bg-black/70 p-4">
<div className="relative w-full max-w-3xl h-[400px] bg-gray-800 rounded-lg">
<Cropper
image={croppingImage}
crop={crop}
zoom={zoom}
aspect={16 / 9}
onCropChange={setCrop}
onZoomChange={setZoom}
onCropComplete={(_, croppedAreaPixels) => setCroppedAreaPixels(croppedAreaPixels)}
/>
<button
className="absolute bottom-4 left-1/2 -translate-x-1/2 btn btn-success"
onClick={handleCropComplete}
>
<Check size={20} /> Done
</button>
<button
className="absolute top-2 right-2 btn btn-ghost btn-circle"
onClick={() => setCroppingImage(null)}
>
<X size={20} />
</button>
</div>
</div>
)}
<div className="grid grid-cols-3 gap-4 max-h-[60vh] overflow-y-auto">
{allBackgrounds.map((value, i) => {
const isExtra = i < extraBackgrounds.length
return (
<div
key={i}
className={`relative rounded-lg overflow-hidden cursor-pointer border-2 transition-all duration-200 ${
value === background ? 'border-blue-500' : 'border-transparent hover:border-gray-500'
}`}
onClick={() => handleSelect(value)}
>
<img src={value} alt={`bg-${i}`} loading="lazy" className="w-full h-28 object-cover" />
{isExtra && (
<button
className="absolute top-1 right-1 bg-black/50 hover:bg-black/70 text-white rounded-full p-1"
onClick={(e) => {
e.stopPropagation()
handleRemoveExtra(value)
}}
>
<X size={14} />
</button>
)}
</div>
)
})}
</div>
</div>
</div>
)}
</div>
)
}

View File

@@ -53,7 +53,7 @@ export default function CloseModal({
className="btn btn-warning" className="btn btn-warning"
onClick={async () => { onClick={async () => {
onClose() onClose()
const [success, message] = await AppService.MinimizeApp() const [success, message] = await AppService.HideApp()
if (!success) toast.error(message) if (!success) toast.error(message)
if (!closingOption.isAsk) { if (!closingOption.isAsk) {
setClosingOption({ isMinimize: true, isAsk: false }) setClosingOption({ isMinimize: true, isAsk: false })

View File

@@ -1,12 +1,31 @@
import { Link } from "@tanstack/react-router"; import { Link } from "@tanstack/react-router";
import ThemeController from "../themeController";
import useModalStore from "@/stores/modalStore"; import useModalStore from "@/stores/modalStore";
import { Settings2 } from "lucide-react"; import { Blend, BookOpen, Diff, Home, Info, Languages, Minus, Puzzle, Settings, TrendingUpDown, Wrench, X } from "lucide-react";
import { AppService } from "@bindings/firefly-launcher/internal/app-service";
export default function Header() { export default function Header() {
const { setIsOpenSettingModal } = useModalStore() const { setIsOpenSettingModal } = useModalStore()
const controlButtons = [
{
icon: <Settings className="w-5 h-5" />,
action: () => setIsOpenSettingModal(true),
tip: "Settings",
},
{
icon: <Minus className="w-5 h-5" />,
action: () => AppService.MinimizeApp(),
tip: "Minimize",
},
{
icon: <X className="w-5 h-5" />,
action: () => AppService.CloseApp(),
tip: "Close",
},
]
return ( return (
<div className="navbar bg-base-100 shadow-sm sticky top-0 z-50 px-3"> <div className="navbar sticky top-0 z-50 px-3" style={{ '--wails-draggable': 'drag' } as any}>
<div className="navbar-start"> <div className="navbar-start">
<div className="dropdown"> <div className="dropdown">
<div tabIndex={0} role="button" className="btn btn-ghost md:hidden"> <div tabIndex={0} role="button" className="btn btn-ghost md:hidden">
@@ -14,7 +33,7 @@ export default function Header() {
</div> </div>
<ul <ul
tabIndex={0} tabIndex={0}
className="menu menu-sm dropdown-content bg-base-100 rounded-box z-1 mt-3 w-52 p-2 shadow"> className="menu menu-sm dropdown-content bg-black/50 backdrop-blur-md rounded-box z-1 mt-3 w-52 p-2 shadow">
<li><Link to="/">Home</Link></li> <li><Link to="/">Home</Link></li>
<li> <li>
@@ -35,51 +54,109 @@ export default function Header() {
<li><Link to="/about">About</Link></li> <li><Link to="/about">About</Link></li>
</ul> </ul>
</div> </div>
<Link to="/" className="grid grid-cols-1 items-start text-left gap-0 hover:scale-105 px-2"> <Link to="/" className="grid grid-cols-1 items-start text-left gap-0">
<div className="flex items-center justify-center"> <div className="flex items-center justify-center">
<img src="/appicon.png" alt="Logo" className='w-13 h-13 rounded-lg mx-2' /> <img src="/appicon.png" alt="Logo" className='w-13 h-13 rounded-lg mx-2' />
<div className="flex flex-col justify-center items-start"> <div className="flex flex-col justify-center items-start">
<h1 className="text-xl font-bold"> <h1 className="text-xl font-bold">
<span className="text-emerald-500">Firefly </span> <span className="text-emerald-500"
<span className="bg-clip-text text-transparent bg-gradient-to-r from-emerald-400 via-orange-500 to-red-500"> style={{
textShadow: '0 1px 2px rgba(255, 255, 255, 0.2)',
}}
>Firefly </span>
<span className="bg-clip-text text-transparent bg-gradient-to-r from-emerald-400 via-orange-500 to-red-500"
style={{
textShadow: '0 1px 2px rgba(255, 255, 255, 0.2)',
}}
>
Launcher Launcher
</span> </span>
</h1> </h1>
<p className="text-sm text-gray-500">By Kain</p> <p
className="text-white text-sm"
style={{
textShadow: '0 1px 2px rgba(0, 0, 0, 0.8)',
}}
>
By Kain
</p>
</div> </div>
</div> </div>
</Link> </Link>
</div> </div>
<div className="navbar-center hidden md:flex"> <div className="navbar-center hidden md:flex bg-black/40 backdrop-blur-sm rounded-lg shadow-lg">
<ul className="menu menu-horizontal px-1 gap-4"> <ul className="menu menu-horizontal px-1 gap-4 text-white">
<li><Link to="/">Home</Link></li> <li>
<Link to="/" className="flex items-center gap-2 hover:text-cyan-300 transition-colors">
<Home size={18} /> Home
</Link>
</li>
<li> <li>
<details> <details>
<summary>Tools</summary> <summary className="flex items-center gap-2 cursor-pointer hover:text-cyan-300 transition-colors">
<ul className="p-2"> <Wrench size={18} /> Tools
<li><Link to="/language">Language</Link></li> </summary>
<li><Link to="/diff">Diff</Link></li> <ul className="p-2 bg-black/75 text-white rounded-lg">
<li>
<Link to="/language" className="flex items-center gap-2 hover:text-cyan-300">
<Languages size={18} /> Language
</Link>
</li>
<li>
<Link to="/diff" className="flex items-center gap-2 hover:text-cyan-300">
<Diff size={18} /> Client update
</Link>
</li>
</ul> </ul>
</details> </details>
</li> </li>
<li> <li>
<details> <details>
<summary>Plugins</summary> <summary className="flex items-center gap-2 cursor-pointer hover:text-cyan-300 transition-colors">
<ul className="p-2"> <Puzzle size={18} /> Plugins
<li><Link to="/analysis">Analysis (Veritas)</Link></li> </summary>
<li><Link to="/srtools">Firefly Tools</Link></li> <ul className="p-2 bg-black/75 text-white rounded-lg">
<li>
<Link to="/analysis" className="flex items-center gap-2 hover:text-cyan-300">
<TrendingUpDown size={18} /> Analysis (Veritas)
</Link>
</li>
<li>
<Link to="/srtools" className="flex items-center gap-2 hover:text-cyan-300">
<Blend size={18} /> Firefly Tools
</Link>
</li>
</ul> </ul>
</details> </details>
</li> </li>
<li><Link to="/howto">How to?</Link></li> <li>
<li><Link to="/about">About</Link></li> <Link to="/howto" className="flex items-center gap-2 hover:text-cyan-300 transition-colors">
<BookOpen size={18} /> How to?
</Link>
</li>
<li>
<Link to="/about" className="flex items-center gap-2 hover:text-cyan-300 transition-colors">
<Info size={18} /> About
</Link>
</li>
</ul> </ul>
</div> </div>
<div className="navbar-end flex gap-2">
<ThemeController /> <div className="navbar-end flex gap-2 z-52">
<button className="btn btn-ghost btn-circle" onClick={() => setIsOpenSettingModal(true)}> <div className="flex items-center gap-2 bg-black/40 backdrop-blur-sm rounded-lg">
<Settings2 className="w-5 h-5" /> {controlButtons.map((btn, i) => (
</button> <div key={i} className="tooltip tooltip-bottom" data-tip={btn.tip}>
<button
onClick={btn.action}
className="btn btn-ghost btn-circle bg-transparent border-none flex items-center justify-center"
>
<div className="hover:text-cyan-300 transition-colors">
{btn.icon}
</div>
</button>
</div>
))}
</div>
</div> </div>
</div> </div>
) )

View File

@@ -14,8 +14,9 @@ export default function SettingModal({
if (!isOpen) return null if (!isOpen) return null
const { setIsOpenSelfUpdateModal } = useModalStore() const { setIsOpenSelfUpdateModal } = useModalStore()
const { closingOption, setClosingOption } = useSettingStore() const { closingOption, setClosingOption, serverVersion,
const { setUpdateData, updateData } = useLauncherStore() proxyVersion, } = useSettingStore()
const { setUpdateData, updateData, launcherVersion } = useLauncherStore()
const CheckUpdate = async () => { const CheckUpdate = async () => {
const launcherData = await CheckUpdateLauncher() const launcherData = await CheckUpdateLauncher()
if (!launcherData.isUpdate) { if (!launcherData.isUpdate) {
@@ -32,7 +33,7 @@ export default function SettingModal({
} }
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm"> <div className="fixed inset-0 z-10 flex items-center justify-center bg-black/40 backdrop-blur-sm">
<div className="relative w-[90%] max-w-md bg-base-100 text-base-content rounded-2xl border border-purple-500/30 shadow-2xl shadow-purple-500/30 p-6"> <div className="relative w-[90%] max-w-md bg-base-100 text-base-content rounded-2xl border border-purple-500/30 shadow-2xl shadow-purple-500/30 p-6">
{/* Header */} {/* Header */}
<div className="flex justify-between items-center mb-6"> <div className="flex justify-between items-center mb-6">
@@ -72,7 +73,6 @@ export default function SettingModal({
className="checkbox checkbox-primary w-5 h-5 mt-1" className="checkbox checkbox-primary w-5 h-5 mt-1"
checked={!closingOption.isAsk} checked={!closingOption.isAsk}
onChange={(e) => { onChange={(e) => {
console.log(!e.target.checked)
setClosingOption({ setClosingOption({
isMinimize: closingOption.isMinimize, isMinimize: closingOption.isMinimize,
isAsk: !e.target.checked isAsk: !e.target.checked
@@ -83,7 +83,7 @@ export default function SettingModal({
<span className="text-base font-medium text-info"> <span className="text-base font-medium text-info">
Set do not ask again Set do not ask again
</span> </span>
<span className="text-sm text-warning"> <span className="text-sm text-accent">
Next time you close the app, it will automatically{" "} Next time you close the app, it will automatically{" "}
{closingOption.isMinimize ? "minimize to system tray" : "quit the app"}{" "} {closingOption.isMinimize ? "minimize to system tray" : "quit the app"}{" "}
without asking. without asking.
@@ -91,6 +91,24 @@ export default function SettingModal({
</div> </div>
</label> </label>
</div> </div>
{/* Section 3: Launcher Version */}
<div className="p-4 bg-base-200 rounded-xl border border-purple-300 shadow-sm">
<h4 className="font-bold text-lg mb-2">Version</h4>
<div className="flex flex-wrap gap-2">
<p className="text-base text-info">
Server: {serverVersion}
</p>
<p className="text-base text-info">
Proxy: {proxyVersion}
</p>
<p className="text-base text-info">
Launcher: {launcherVersion}
</p>
</div>
</div>
</div> </div>
</div> </div>

View File

@@ -1,30 +0,0 @@
import { useEffect, useState } from "react";
export default function ThemeController() {
const [theme, setTheme] = useState(localStorage.getItem("theme") ?? "night");
const handleToggle = (e: any) => {
if (e.target.checked) {
setTheme("cupcake");
} else {
setTheme("night");
}
};
useEffect(() => {
localStorage.setItem('theme', theme!)
const localTheme = localStorage.getItem('theme')
document.querySelector('html')?.setAttribute('data-theme', localTheme!)
}, [theme]);
return (
<label className="toggle text-base-content">
<input type="checkbox" onChange={handleToggle} className="theme-controller" />
<svg aria-label="moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g strokeLinejoin="round" strokeLinecap="round" strokeWidth="2" fill="none" stroke="currentColor"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path></g></svg>
<svg aria-label="sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g strokeLinejoin="round" strokeLinecap="round" strokeWidth="2" fill="none" stroke="currentColor"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></g></svg>
</label>
)
}

View File

@@ -35,7 +35,7 @@ export default function UpdateModal({ isOpen, title, message, buttons, onClose }
<div className="px-6 pb-6"> <div className="px-6 pb-6">
<div className="mb-6"> <div className="mb-6">
<p className="text-warning text-lg">{message}</p> <p className="text-accent text-lg">{message}</p>
</div> </div>
<div className="flex justify-end gap-3"> <div className="flex justify-end gap-3">

View File

@@ -23,11 +23,9 @@ export async function UpdateProxy(proxyVersion: string) : Promise<void> {
setDownloadType("Downloading proxy...") setDownloadType("Downloading proxy...")
const [ok, error] = await GitService.DownloadProxyProgress(proxyVersion) const [ok, error] = await GitService.DownloadProxyProgress(proxyVersion)
if (ok) { if (ok) {
setDownloadType("Unzipping proxy...")
GitService.UnzipProxy()
setDownloadType("Download proxy successfully") setDownloadType("Download proxy successfully")
setProxyVersion(proxyVersion) setProxyVersion(proxyVersion)
setProxyPath("./proxy/FireflyProxy.exe") setProxyPath("./proxy/firefly-go-proxy.exe")
} else { } else {
toast.error(error) toast.error(error)
setDownloadType("Download proxy failed") setDownloadType("Download proxy failed")

View File

@@ -14,7 +14,7 @@ export default function AboutPage() {
I created a lightweight and modern <span className="font-semibold text-success">Game Launcher</span> to help users easily launch and manage their games with better performance and simplicity. I created a lightweight and modern <span className="font-semibold text-success">Game Launcher</span> to help users easily launch and manage their games with better performance and simplicity.
</p> </p>
<p className="text-lg leading-relaxed"> <p className="text-lg leading-relaxed">
The launcher is built using <span className="font-mono text-info">Go + Wails3</span>, with a clean and responsive interface styled with <span className="text-warning">Tailwind CSS</span> and <span className="text-warning">DaisyUI</span>. The launcher is built using <span className="font-mono text-info">Go + Wails3</span>, with a clean and responsive interface styled with <span className="text-accent">Tailwind CSS</span> and <span className="text-accent">DaisyUI</span>.
</p> </p>
<p className="text-lg leading-relaxed"> <p className="text-lg leading-relaxed">
My goal is to make tools that are fast, efficient, and enjoyable to use and this launcher is just the beginning. My goal is to make tools that are fast, efficient, and enjoyable to use and this launcher is just the beginning.

View File

@@ -64,7 +64,7 @@ export default function AnalysisPage() {
</div> </div>
<a <a
href="https://sranalysis.kain.id.vn/" href="https://sranalysis.kain.id.vn/"
className="link link-warning font-mono text-sm break-all" className="link link-accent font-mono text-sm break-all"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
@@ -79,7 +79,7 @@ export default function AnalysisPage() {
</div> </div>
<a <a
href="https://firefly-sranalysis.vercel.app/" href="https://firefly-sranalysis.vercel.app/"
className="link link-warning font-mono text-sm break-all" className="link link-accent font-mono text-sm break-all"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >

View File

@@ -309,7 +309,7 @@ export default function DiffPage() {
<div className="w-full p-4"> <div className="w-full p-4">
<div className="space-y-3"> <div className="space-y-3">
<div className="flex justify-center items-center text-sm text-white/80"> <div className="flex justify-center items-center text-sm text-white/80">
<span className="font-bold text-lg text-warning">{stageType}:</span> <span className="font-bold text-lg text-accent">{stageType}:</span>
<div className="flex items-center gap-4 ml-2"> <div className="flex items-center gap-4 ml-2">
{stageType !== 'Cut Data' && <span className="text-white font-bold">{progressUpdate.toFixed(0)} / {maxProgressUpdate.toFixed(0)}</span>} {stageType !== 'Cut Data' && <span className="text-white font-bold">{progressUpdate.toFixed(0)} / {maxProgressUpdate.toFixed(0)}</span>}
{stageType === 'Cut Data' && <span className="text-white font-bold truncate max-w-full overflow-hidden whitespace-nowrap">{messageUpdate}</span>} {stageType === 'Cut Data' && <span className="text-white font-bold truncate max-w-full overflow-hidden whitespace-nowrap">{messageUpdate}</span>}

View File

@@ -19,7 +19,7 @@ export default function FireflyToolsPage() {
This site is a another version of {" "} This site is a another version of {" "}
<span className="font-semibold text-success">Firefly Tools {" "}</span> <span className="font-semibold text-success">Firefly Tools {" "}</span>
developed by {" "} developed by {" "}
<span className="font-semibold text-warning">Me {"(Kain)"}</span> <span className="font-semibold text-accent">Me {"(Kain)"}</span>
</p> </p>
</div> </div>
<div className="grid md:grid-cols-2 gap-4"> <div className="grid md:grid-cols-2 gap-4">
@@ -30,7 +30,7 @@ export default function FireflyToolsPage() {
</div> </div>
<a <a
href="https://srtools.kain.id.vn/" href="https://srtools.kain.id.vn/"
className="link link-warning font-mono text-sm break-all" className="link link-accent font-mono text-sm break-all"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
@@ -45,7 +45,7 @@ export default function FireflyToolsPage() {
</div> </div>
<a <a
href="https://firefly-srtools.vercel.app/" href="https://firefly-srtools.vercel.app/"
className="link link-warning font-mono text-sm break-all" className="link link-accent font-mono text-sm break-all"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
@@ -55,14 +55,14 @@ export default function FireflyToolsPage() {
</div> </div>
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="text-blue-600 text-lg">👨💻</div> <div className="text-blue-600 text-lg">👨💻</div>
<p>The original tool was created by a third-party developer named <span className="font-semibold text-warning">Amazing</span>. This version is directly based on that work, without modification to core logic.</p> <p>The original tool was created by a third-party developer named <span className="font-semibold text-accent">Amazing</span>. This version is directly based on that work, without modification to core logic.</p>
</div> </div>
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="text-blue-600 text-lg">🔗</div> <div className="text-blue-600 text-lg">🔗</div>
<p>There is also a more modern version by the same author available at{" "} <p>There is also a more modern version by the same author available at{" "}
<a <a
href="https://srtools.neonteam.dev/" href="https://srtools.neonteam.dev/"
className="link link-warning" className="link link-accent"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
@@ -71,7 +71,7 @@ export default function FireflyToolsPage() {
{" "}and the original version at{" "} {" "}and the original version at{" "}
<a <a
href="https://srtools.pages.dev/" href="https://srtools.pages.dev/"
className="link link-warning" className="link link-accent"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
@@ -95,14 +95,14 @@ export default function FireflyToolsPage() {
</div> </div>
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="text-green-600 text-lg">🔌</div> <div className="text-green-600 text-lg">🔌</div>
<p>Instantly apply setups to <span className="font-semibold text-warning">Firefly GO Server</span> using <span className="font-semibold">Connect PS</span> no manual file uploads required.</p> <p>Instantly apply setups to <span className="font-semibold text-accent">Firefly GO Server</span> using <span className="font-semibold">Connect PS</span> no manual file uploads required.</p>
</div> </div>
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<div className="text-green-600 text-2xl"></div> <div className="text-green-600 text-2xl"></div>
<div> <div>
<h4 className="font-semibold text-green-800 text-lg">Extra Settings</h4> <h4 className="font-semibold text-green-800 text-lg">Extra Settings</h4>
<p className="text-green-700 mt-1"> <p className="text-green-700 mt-1">
Enhance your <span className="font-semibold text-warning">Firefly GO Server</span> experience with extra features: Enhance your <span className="font-semibold text-accent">Firefly GO Server</span> experience with extra features:
</p> </p>
<ul className="list-disc list-inside mt-2 space-y-1 text-green-700"> <ul className="list-disc list-inside mt-2 space-y-1 text-green-700">
<li>🎭 <span className="font-medium">Hidden Game UI</span> remove the entire game interface.</li> <li>🎭 <span className="font-medium">Hidden Game UI</span> remove the entire game interface.</li>

View File

@@ -56,7 +56,7 @@ export default function HowToPage() {
<p className="text-blue-700 mb-4"> <p className="text-blue-700 mb-4">
Below are in-game chat commands you can use. Some commands require you to enable{" "} Below are in-game chat commands you can use. Some commands require you to enable{" "}
<span className="font-semibold text-warning">Theorycraft Mode</span>. <span className="font-semibold text-accent">Theorycraft Mode</span>.
</p> </p>
{/* Theorycraft Mode Warning */} {/* Theorycraft Mode Warning */}

View File

@@ -208,10 +208,10 @@ export default function LanguagePage() {
<div className="bg-warning/5 rounded-lg p-2 border border-warning/30"> <div className="bg-warning/5 rounded-lg p-2 border border-warning/30">
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<Mic size={20} className="text-warning" /> <Mic size={20} className="text-accent" />
<span className="font-bold text-warning">Voice Language</span> <span className="font-bold text-accent">Voice Language</span>
</div> </div>
<p className="text-2xl font-bold text-warning"> <p className="text-2xl font-bold text-accent">
{getLanguageLabel(voiceLang)} {getLanguageLabel(voiceLang)}
</p> </p>
</div> </div>
@@ -250,7 +250,7 @@ export default function LanguagePage() {
{/* Voice Language */} {/* Voice Language */}
<div className="space-y-3"> <div className="space-y-3">
<label className="flex text-sm font-medium text-warning items-center gap-2"> <label className="flex text-sm font-medium text-accent items-center gap-2">
<Mic size={16} /> <Mic size={16} />
Voice Language Voice Language
</label> </label>

View File

@@ -11,9 +11,12 @@ import { motion } from 'motion/react';
import { Link } from '@tanstack/react-router'; import { Link } from '@tanstack/react-router';
import { CheckUpdateLauncher, CheckUpdateProxy, CheckUpdateServer, sleep, UpdateLauncher, UpdateProxy, UpdateServer } from '@/helper'; import { CheckUpdateLauncher, CheckUpdateProxy, CheckUpdateServer, sleep, UpdateLauncher, UpdateProxy, UpdateServer } from '@/helper';
import UpdateModal from '@/components/updateModal'; import UpdateModal from '@/components/updateModal';
import { BackgroundSelector } from '@/components/backgroudModal';
export default function LauncherPage() { export default function LauncherPage() {
const { gamePath, const {
gamePath,
setGamePath, setGamePath,
setGameDir, setGameDir,
serverPath, serverPath,
@@ -21,6 +24,7 @@ export default function LauncherPage() {
gameDir, gameDir,
serverVersion, serverVersion,
proxyVersion, proxyVersion,
background
} = useSettingStore() } = useSettingStore()
const { const {
@@ -44,7 +48,7 @@ export default function LauncherPage() {
progressDownload, progressDownload,
downloadSpeed, downloadSpeed,
updateData, updateData,
launcherVersion, // launcherVersion,
setLauncherVersion, setLauncherVersion,
setIsLoading, setIsLoading,
setDownloadType, setDownloadType,
@@ -174,8 +178,6 @@ export default function LauncherPage() {
} }
} }
const handleStartGame = async () => { const handleStartGame = async () => {
if (!gamePath) { if (!gamePath) {
return return
@@ -186,39 +188,46 @@ export default function LauncherPage() {
try { try {
setIsLoading(true) setIsLoading(true)
if (!proxyRunning && !gamePath.endsWith("launcher.exe")) { if (!proxyRunning && !gamePath.endsWith("launcher.exe")) {
const resultProxy = await FSService.StartWithConsole(proxyPath) const [resultProxy, error] = await FSService.StartWithConsole(proxyPath)
if (!resultProxy) { if (!resultProxy) {
toast.error('Failed to start proxy') toast.error('Failed to start proxy: ' + error)
return return
} }
setProxyRunning(true) setProxyRunning(true)
} }
await sleep(500) await sleep(500)
if (!serverRunning) { if (!serverRunning) {
const resultServer = await FSService.StartWithConsole(serverPath) const [resultServer, error] = await FSService.StartWithConsole(serverPath)
if (!resultServer) { if (!resultServer) {
toast.error('Failed to start server') toast.error('Failed to start server: ' + error)
return return
} }
setServerRunning(true) setServerRunning(true)
} }
await sleep(2000) await sleep(1000)
const gameFolder = await FSService.GetDir(gamePath)
const fileNeedRemove = await FSService.Join(gameFolder, "StarRail_Data", "Plugins", "x86_64", "AccountPlatNative.dll")
const fileExists = await FSService.FileExists(fileNeedRemove)
if (fileExists) {
await FSService.RemoveFile(fileNeedRemove)
}
if (gamePath.endsWith("launcher.exe")) { if (gamePath.endsWith("launcher.exe")) {
const resultGame = await FSService.StartWithConsole(gamePath) const [resultGame, error] = await FSService.StartWithConsole(gamePath)
if (!resultGame) { if (!resultGame) {
toast.error('Failed to start game') toast.error('Failed to start game: ' + error)
return return
} }
} else { } else {
const resultGame = await FSService.StartApp(gamePath) const [resultGame, error] = await FSService.StartApp(gamePath)
if (!resultGame) { if (!resultGame) {
toast.error('Failed to start game') toast.error('Failed to start game: ' + error)
return return
} }
} }
setGameRunning(true) setGameRunning(true)
} catch (err: any) { } catch (err: any) {
console.log(err)
toast.error('StartGame error:', err) toast.error('StartGame error:', err)
} finally { } finally {
setIsLoading(false) setIsLoading(false)
@@ -265,24 +274,24 @@ export default function LauncherPage() {
return ( return (
<div className="relative min-h-fit overflow-hidden"> <div className="relative min-h-fit overflow-hidden">
<div <img
className="fixed inset-0 z-0 w-full h-full" src={background}
style={{ alt="background"
backgroundImage: "url('/bg.jpg')", className="fixed inset-0 w-full h-full object-cover z-0"
backgroundSize: "cover", onError={(e) => {
backgroundPosition: "center", const target = e.currentTarget as HTMLImageElement
backgroundRepeat: "no-repeat" target.src = "bg-12.jpg"
}} }}
></div> />
{/* Header */} {/* Header */}
<header className="hidden sm:flex fixed z-10 items-center justify-between p-6"> <header className="hidden sm:flex fixed z-10 items-center justify-between py-6 px-4 ">
<div className="text-2xl font-bold text-white">Firefly GO</div> <div className="text-2xl font-bold text-white bg-gray-500/5 rounded-full p-1">Firefly GO</div>
</header> </header>
<div className="hidden sm:flex fixed top-1/4 left-4 z-10 flex-col space-y-3 bg-black/30 backdrop-blur-md rounded-xl p-3 shadow-lg"> <div className="hidden sm:flex fixed top-1/4 right-4 z-10 flex-col space-y-3 bg-white/5 rounded-xl p-3 shadow-lg">
{widgetLinks.map((link, idx) => ( {widgetLinks.map((link, idx) => (
<div key={idx} className="tooltip tooltip-right" data-tip={link.tooltip}> <div key={idx} className="tooltip tooltip-left" data-tip={link.tooltip}>
<a <a
className={`btn btn-circle ${link.btnClass}`} className={`btn btn-circle ${link.btnClass}`}
target="_blank" target="_blank"
@@ -297,7 +306,7 @@ export default function LauncherPage() {
</div> </div>
))} ))}
<div className="tooltip tooltip-right" data-tip="How to use all tools & commands"> <div className="tooltip tooltip-left" data-tip="How to use all tools & commands">
<Link <Link
to="/howto" to="/howto"
className="btn btn-warning btn-circle" className="btn btn-warning btn-circle"
@@ -307,6 +316,9 @@ export default function LauncherPage() {
</div> </div>
</div> </div>
<div className="hidden sm:flex fixed top-1/2 left-5 z-10 ">
<BackgroundSelector />
</div>
{/* Bottom Panel */} {/* Bottom Panel */}
{serverReady && proxyReady && !isDownloading && ( {serverReady && proxyReady && !isDownloading && (
@@ -392,7 +404,7 @@ export default function LauncherPage() {
|| !updateData.proxy.isExists || !updateData.proxy.isExists
|| !updateData.server.isExists || !updateData.server.isExists
) && ( ) && (
<div className="fixed bottom-4 left-1/2 transform -translate-x-1/2 z-10 w-[60vw] bg-black/20 backdrop-blur-sm rounded-lg p-4 shadow-lg"> <div className="fixed bottom-4 left-1/2 transform -translate-x-1/2 z-10 w-[60vw] bg-black/20 backdrop-blur-sm rounded-lg p-4 shadow-lg">
<div className="space-y-3"> <div className="space-y-3">
<div className="flex justify-center items-center text-sm text-white/80"> <div className="flex justify-center items-center text-sm text-white/80">
<span>{downloadType}</span> <span>{downloadType}</span>
@@ -459,15 +471,11 @@ export default function LauncherPage() {
</div> </div>
)} )}
{/* Version Info */} <div className="hidden md:block fixed bottom-4 left-5 z-10">
{serverReady && proxyReady && !isDownloading && (
<div className="hidden md:block fixed bottom-4 left-4 z-10 text-sm font-bold bg-black/20 backdrop-blur-sm rounded-lg p-2 shadow">
<p className="text-primary">Version server: {serverVersion}</p>
<p className="mt-2 text-secondary">Version proxy: {proxyVersion}</p>
<p className="mt-2 text-success">Version launcher: {launcherVersion}</p>
</div>
)}
<img src="/heart-hsr.gif" alt="firefly animation" className="rounded-lg w-24 h-24" />
</div>
{/* Modal */} {/* Modal */}
<UpdateModal <UpdateModal
isOpen={isOpenUpdateDataModal} isOpen={isOpenUpdateDataModal}

View File

@@ -14,6 +14,10 @@ interface SettingState {
isMinimize: boolean; isMinimize: boolean;
isAsk: boolean; isAsk: boolean;
} }
background: string;
extraBackgrounds: string[];
setExtraBackgrounds: (newExtraBackgrounds: string[]) => void;
setBackground: (newBackground: string) => void;
setClosingOption: (newClosingOption: { isMinimize: boolean; isAsk: boolean }) => void; setClosingOption: (newClosingOption: { isMinimize: boolean; isAsk: boolean }) => void;
setLocale: (newLocale: string) => void; setLocale: (newLocale: string) => void;
setGamePath: (newGamePath: string) => void; setGamePath: (newGamePath: string) => void;
@@ -38,6 +42,10 @@ const useSettingStore = create<SettingState>()(
isMinimize: false, isMinimize: false,
isAsk: true, isAsk: true,
}, },
background: "bg-12.jpg",
extraBackgrounds: [],
setExtraBackgrounds: (newExtraBackgrounds: string[]) => set({ extraBackgrounds: newExtraBackgrounds }),
setBackground: (newBackground: string) => set({ background: newBackground }),
setClosingOption: (newClosingOption: { isMinimize: boolean; isAsk: boolean }) => set({ closingOption: newClosingOption }), setClosingOption: (newClosingOption: { isMinimize: boolean; isAsk: boolean }) => set({ closingOption: newClosingOption }),
setLocale: (newLocale: string) => set({ locale: newLocale }), setLocale: (newLocale: string) => set({ locale: newLocale }),
setGamePath: (newGamePath: string) => set({ gamePath: newGamePath }), setGamePath: (newGamePath: string) => set({ gamePath: newGamePath }),

View File

@@ -1,4 +1,4 @@
@import "tailwindcss"; @import "tailwindcss";
@plugin "daisyui"{ @plugin "daisyui"{
themes: night --default, night --prefersdark, cupcake; themes: dracula --default;
} }

View File

@@ -0,0 +1,25 @@
export default function getCroppedImg(imageSrc: string, crop: any): Promise<string> {
const image = new Image()
image.src = imageSrc
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')!
canvas.width = crop.width
canvas.height = crop.height
return new Promise((resolve) => {
image.onload = () => {
ctx.drawImage(
image,
crop.x,
crop.y,
crop.width,
crop.height,
0,
0,
crop.width,
crop.height
)
resolve(canvas.toDataURL('image/jpeg'))
}
})
}

2
go.mod
View File

@@ -1,6 +1,6 @@
module firefly-launcher module firefly-launcher
go 1.25 go 1.25.5
require ( require (
github.com/klauspost/compress v1.18.0 github.com/klauspost/compress v1.18.0

View File

@@ -26,7 +26,7 @@ func (a *AppService) CloseApp() (bool, string) {
return true, "" return true, ""
} }
func (a *AppService) MinimizeApp() (bool, string) { func (a *AppService) HideApp() (bool, string) {
window := application.Get().Window.Current() window := application.Get().Window.Current()
if window == nil { if window == nil {
return false, "not found window" return false, "not found window"
@@ -35,3 +35,29 @@ func (a *AppService) MinimizeApp() (bool, string) {
return true, "" return true, ""
} }
func (a *AppService) MinimizeApp() (bool, string) {
window := application.Get().Window.Current()
if window == nil {
return false, "not found window"
}
window.Minimise()
return true, ""
}
func (a *AppService) MaximizeApp() (bool, string) {
window := application.Get().Window.Current()
if window == nil {
return false, "not found window"
}
window.Maximise()
return true, ""
}
func (a *AppService) RestoreApp() (bool, string) {
window := application.Get().Window.Current()
if window == nil {
return false, "not found window"
}
window.Restore()
return true, ""
}

View File

@@ -2,12 +2,12 @@ package fsService
import ( import (
"firefly-launcher/pkg/sevenzip" "firefly-launcher/pkg/sevenzip"
"fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
"github.com/wailsapp/wails/v3/pkg/application" "github.com/wailsapp/wails/v3/pkg/application"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
@@ -63,12 +63,25 @@ func (f *FSService) FileExists(path string) bool {
return false return false
} }
func (f *FSService) StartApp(path string) (bool, error) { func (f *FSService) GetDir(path string) string {
return filepath.Dir(path)
}
func (f *FSService) Join(paths ...string) string {
return filepath.Join(paths...)
}
func (f *FSService) RemoveFile(path string) error {
return os.Remove(path)
}
func (f *FSService) StartApp(path string) (bool, string) {
cmd := exec.Command(path) cmd := exec.Command(path)
err := cmd.Start() err := cmd.Start()
if err != nil { if err != nil {
return false, err return false, err.Error()
} }
if strings.HasSuffix(path, "StarRail.exe") { if strings.HasSuffix(path, "StarRail.exe") {
go func() { go func() {
_ = cmd.Wait() _ = cmd.Wait()
@@ -76,17 +89,17 @@ func (f *FSService) StartApp(path string) (bool, error) {
}() }()
} }
return true, nil return true, ""
} }
func (f *FSService) StartWithConsole(path string) (bool, error) { func (f *FSService) StartWithConsole(path string) (bool, string) {
absPath, err := filepath.Abs(path) absPath, err := filepath.Abs(path)
if err != nil { if err != nil {
return false, err return false, err.Error()
} }
if _, err := os.Stat(absPath); os.IsNotExist(err) { if _, err := os.Stat(absPath); os.IsNotExist(err) {
return false, fmt.Errorf("file not found: %s", absPath) return false, "file not found: " + absPath
} }
cmd := exec.Command(absPath) cmd := exec.Command(absPath)
cmd.Dir = filepath.Dir(absPath) cmd.Dir = filepath.Dir(absPath)
@@ -103,7 +116,7 @@ func (f *FSService) StartWithConsole(path string) (bool, error) {
err = cmd.Start() err = cmd.Start()
if err != nil { if err != nil {
return false, err return false, err.Error()
} }
go func() { go func() {
@@ -116,7 +129,7 @@ func (f *FSService) StartWithConsole(path string) (bool, error) {
application.Get().Event.Emit("proxy:exit") application.Get().Event.Emit("proxy:exit")
} }
}() }()
return true, nil return true, ""
} }
func (f *FSService) OpenFolder(path string) (bool, string) { func (f *FSService) OpenFolder(path string) (bool, string) {
@@ -142,4 +155,3 @@ func (f *FSService) FileExistsInZip(archivePath, fileInside string) (bool, strin
} }
return exists, "" return exists, ""
} }

View File

@@ -37,7 +37,7 @@ func (g *GitService) GetLatestProxyVersion() (bool, string, string) {
} }
func (g *GitService) DownloadProxyProgress(version string) (bool, string) { func (g *GitService) DownloadProxyProgress(version string) (bool, string) {
asset, ok := g.getReleaseAsset(version, constant.ProxyGitUrl, constant.ProxyZipFile) asset, ok := g.getReleaseAsset(version, constant.ProxyGitUrl, constant.ProxyFile)
if !ok { if !ok {
return false, "no release found" return false, "no release found"
} }
@@ -65,7 +65,3 @@ func (g *GitService) DownloadProxyProgress(version string) (bool, string) {
return false, "failed to rename tmp file after retries" return false, "failed to rename tmp file after retries"
} }
func (g *GitService) UnzipProxy() {
g.unzipParallel(filepath.Join(constant.ProxyStorageUrl, constant.ProxyZipFile), constant.ProxyStorageUrl)
os.Remove(filepath.Join(constant.ProxyStorageUrl, constant.ProxyZipFile))
}

View File

@@ -93,10 +93,12 @@ func main() {
TitleBar: application.MacTitleBarHiddenInset, TitleBar: application.MacTitleBarHiddenInset,
}, },
BackgroundColour: application.NewRGB(27, 38, 54), BackgroundColour: application.NewRGB(27, 38, 54),
Width: 1200, Width: 1280,
Height: 600, Height: 720,
URL: "/", URL: "/",
DevToolsEnabled: true, DevToolsEnabled: true,
Frameless: true,
DisableResize: true,
}) })
iconBytes, _ := tools.ReadFile("assets/appicon.png") iconBytes, _ := tools.ReadFile("assets/appicon.png")
@@ -115,8 +117,6 @@ func main() {
systemTray.SetMenu(menu) systemTray.SetMenu(menu)
window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) {
app.Event.Emit("window:close") app.Event.Emit("window:close")
e.Cancel() e.Cancel()

View File

@@ -1,16 +1,16 @@
package constant package constant
const ProxyGitUrl = "https://git.kain.io.vn/api/v1/repos/Firefly-Shelter/Firefly_Proxy/releases" const ProxyGitUrl = "https://git.kain.io.vn/api/v1/repos/Firefly-Shelter/FireflyGo_Proxy/releases"
const ServerGitUrl = "https://git.kain.io.vn/api/v1/repos/Firefly-Shelter/FireflyGo_Local_Archive/releases" const ServerGitUrl = "https://git.kain.io.vn/api/v1/repos/Firefly-Shelter/FireflyGo_Local_Archive/releases"
const LauncherGitUrl = "https://git.kain.io.vn/api/v1/repos/Firefly-Shelter/Firefly_Launcher/releases" const LauncherGitUrl = "https://git.kain.io.vn/api/v1/repos/Firefly-Shelter/Firefly_Launcher/releases"
const ServerStorageUrl = "./server" const ServerStorageUrl = "./server"
const ProxyStorageUrl = "./proxy" const ProxyStorageUrl = "./proxy"
const ServerZipFile = "prebuild_win_x86.zip" const ServerZipFile = "prebuild_win_x86.zip"
const ProxyZipFile = "64bit.zip" const ProxyFile = "firefly-go-proxy.exe"
const LauncherFile = "firefly-launcher.exe" const LauncherFile = "firefly-launcher.exe"
const TempUrl = "./temp" const TempUrl = "./temp"
const CurrentLauncherVersion = "2.1.0" const CurrentLauncherVersion = "2.3.2"
type ToolFile string type ToolFile string