mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2024-11-15 19:22:26 +08:00
chore: update
This commit is contained in:
parent
d45929c604
commit
507d52bcb9
12
package.json
12
package.json
|
@ -28,7 +28,15 @@
|
|||
"@mui/lab": "5.0.0-alpha.149",
|
||||
"@mui/material": "^5.16.0",
|
||||
"@mui/x-data-grid": "^7.9.0",
|
||||
"@tauri-apps/api": "^1.6.0",
|
||||
"@tauri-apps/api": "2.0.0-rc.4",
|
||||
"@tauri-apps/plugin-clipboard-manager": "2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-dialog": "^2.0.0-rc",
|
||||
"@tauri-apps/plugin-fs": "^2.0.0-rc",
|
||||
"@tauri-apps/plugin-global-shortcut": "^2.0.0-rc",
|
||||
"@tauri-apps/plugin-notification": "^2.0.0-rc",
|
||||
"@tauri-apps/plugin-process": "^2.0.0-rc",
|
||||
"@tauri-apps/plugin-shell": "^2.0.0-rc",
|
||||
"@tauri-apps/plugin-updater": "^2.0.0-rc",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"ahooks": "^3.8.0",
|
||||
"axios": "^1.7.2",
|
||||
|
@ -60,7 +68,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@actions/github": "^5.1.1",
|
||||
"@tauri-apps/cli": "^1.6.0",
|
||||
"@tauri-apps/cli": "2.0.0-rc.8",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
|
|
205
pnpm-lock.yaml
205
pnpm-lock.yaml
|
@ -38,8 +38,32 @@ importers:
|
|||
specifier: ^7.9.0
|
||||
version: 7.9.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
"@tauri-apps/api":
|
||||
specifier: ^1.6.0
|
||||
version: 1.6.0
|
||||
specifier: 2.0.0-rc.4
|
||||
version: 2.0.0-rc.4
|
||||
"@tauri-apps/plugin-clipboard-manager":
|
||||
specifier: 2.0.0-rc.0
|
||||
version: 2.0.0-rc.0
|
||||
"@tauri-apps/plugin-dialog":
|
||||
specifier: ^2.0.0-rc
|
||||
version: 2.0.0-rc.0
|
||||
"@tauri-apps/plugin-fs":
|
||||
specifier: ^2.0.0-rc
|
||||
version: 2.0.0-rc.1
|
||||
"@tauri-apps/plugin-global-shortcut":
|
||||
specifier: ^2.0.0-rc
|
||||
version: 2.0.0-rc.0
|
||||
"@tauri-apps/plugin-notification":
|
||||
specifier: ^2.0.0-rc
|
||||
version: 2.0.0-rc.0
|
||||
"@tauri-apps/plugin-process":
|
||||
specifier: ^2.0.0-rc
|
||||
version: 2.0.0-rc.0
|
||||
"@tauri-apps/plugin-shell":
|
||||
specifier: ^2.0.0-rc
|
||||
version: 2.0.0-rc.0
|
||||
"@tauri-apps/plugin-updater":
|
||||
specifier: ^2.0.0-rc
|
||||
version: 2.0.0-rc.0
|
||||
"@types/json-schema":
|
||||
specifier: ^7.0.15
|
||||
version: 7.0.15
|
||||
|
@ -129,8 +153,8 @@ importers:
|
|||
specifier: ^5.1.1
|
||||
version: 5.1.1
|
||||
"@tauri-apps/cli":
|
||||
specifier: ^1.6.0
|
||||
version: 1.6.0
|
||||
specifier: 2.0.0-rc.8
|
||||
version: 2.0.0-rc.8
|
||||
"@types/fs-extra":
|
||||
specifier: ^9.0.13
|
||||
version: 9.0.13
|
||||
|
@ -2076,111 +2100,158 @@ packages:
|
|||
peerDependencies:
|
||||
"@svgr/core": "*"
|
||||
|
||||
"@tauri-apps/api@1.6.0":
|
||||
"@tauri-apps/api@2.0.0-rc.4":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-rqI++FWClU5I2UBp4HXFvl+sBWkdigBkxnpJDQUWttNyG7IZP4FwQGhTNL5EOw0vI8i6eSAJ5frLqO7n7jbJdg==,
|
||||
integrity: sha512-UNiIhhKG08j4ooss2oEEVexffmWkgkYlC2M3GcX3VPtNsqFgVNL8Mcw/4Y7rO9M9S+ffAMnLOF5ypzyuyb8tyg==,
|
||||
}
|
||||
engines: { node: ">= 14.6.0", npm: ">= 6.6.0", yarn: ">= 1.19.1" }
|
||||
|
||||
"@tauri-apps/cli-darwin-arm64@1.6.0":
|
||||
"@tauri-apps/cli-darwin-arm64@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-SNRwUD9nqGxY47mbY1CGTt/jqyQOU7Ps7Mx/mpgahL0FVUDiCEY/5L9QfEPPhEgccgcelEVn7i6aQHIkHyUtCA==,
|
||||
integrity: sha512-XDjFLfCz7gOsKg9qFyK7S9EbrdcLhWE2bSTvHDpnFdMc+DcjMR4O3HuCO7SrPmmFUf86OknYFiuMPEUoHf0Fiw==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
"@tauri-apps/cli-darwin-x64@1.6.0":
|
||||
"@tauri-apps/cli-darwin-x64@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-g2/uDR/eeH2arvuawA4WwaEOqv/7jDO/ZLNI3JlBjP5Pk8GGb3Kdy0ro1xQzF94mtk2mOnOXa4dMgAet4sUJ1A==,
|
||||
integrity: sha512-vYuITao7qq45jzTXRFdAcB+rVBULmofksWsKzoi+cgI8R0kcfB3bts+FRBdV3j+fkbpBQKpriW6Y6gdOzbf6Ow==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf@1.6.0":
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-EVwf4oRkQyG8BpSrk0gqO7oA0sDM2MdNDtJpMfleYFEgCxLIOGZKNqaOW3M7U+0Y4qikmG3TtRK+ngc8Ymtrjg==,
|
||||
integrity: sha512-iW1gJyRBvwxCeBEu+ain18v8FtFBhrsqepzuUyOy7hZJWUMPdKHJhbFVz6xp3RGZf5ycsLUr3ZhqMB3vKtv7iQ==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-gnu@1.6.0":
|
||||
"@tauri-apps/cli-linux-arm64-gnu@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-YdpY17cAySrhK9dX4BUVEmhAxE2o+6skIEFg8iN/xrDwRxhaNPI9I80YXPatUTX54Kx55T5++25VJG9+3iw83A==,
|
||||
integrity: sha512-k1HQHpu59B8JteXALCSdCQBUVb+ytsg1u/QEWPzCm7mFhzr7jqdfBjQVAKt0T5rdQQTcNtK341oB7izuXmJE2A==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-musl@1.6.0":
|
||||
"@tauri-apps/cli-linux-arm64-musl@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-4U628tuf2U8pMr4tIBJhEkrFwt+46dwhXrDlpdyWSZtnop5RJAVKHODm0KbWns4xGKfTW1F3r6sSv+2ZxLcISA==,
|
||||
integrity: sha512-tMotP7J/dMqCL8zPCwtMwjeO3SK1yxU9bUMZ3mwdAtf+3xr2d2hpmGo4KXk5r2jQee9+dIC3IBXexFhrVJGRHA==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
"@tauri-apps/cli-linux-x64-gnu@1.6.0":
|
||||
"@tauri-apps/cli-linux-x64-gnu@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-AKRzp76fVUaJyXj5KRJT9bJyhwZyUnRQU0RqIRqOtZCT5yr6qGP8rjtQ7YhCIzWrseBlOllc3Qvbgw3Yl0VQcA==,
|
||||
integrity: sha512-AnLghADQgt4oyp4rQyjpKfGpdAqofd+SRO9kht5d4c0RSViqwHBjIxrCt9FDhBpBwwkC6T6NNuQqaofZSnOH6Q==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
"@tauri-apps/cli-linux-x64-musl@1.6.0":
|
||||
"@tauri-apps/cli-linux-x64-musl@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-0edIdq6aMBTaRMIXddHfyAFL361JqulLLd2Wi2aoOie7DkQ2MYh6gv3hA7NB9gqFwNIGE+xtJ4BkXIP2tSGPlg==,
|
||||
integrity: sha512-jv/uiXI2K41/XMA2vnKMcpdv1tKvez70HHvBoIwHhelmXV5V6Tpu5fTMEAXbA6WbJNfcFRi0kd55YRBOS0DZcw==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
"@tauri-apps/cli-win32-arm64-msvc@1.6.0":
|
||||
"@tauri-apps/cli-win32-arm64-msvc@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-QwWpWk4ubcwJ1rljsRAmINgB2AwkyzZhpYbalA+MmzyYMREcdXWGkyixWbRZgqc6fEWEBmq5UG73qz5eBJiIKg==,
|
||||
integrity: sha512-wctgwSfuyJ0lXBzQSzGq5TAy2m9VZichZPPJ7GitYzdHbqIRLmvxM1abRen7HikP1lpjdmjl96/kWQOebEV0qw==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
"@tauri-apps/cli-win32-ia32-msvc@1.6.0":
|
||||
"@tauri-apps/cli-win32-ia32-msvc@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-Vtw0yxO9+aEFuhuxQ57ALG43tjECopRimRuKGbtZYDCriB/ty5TrT3QWMdy0dxBkpDTu3Rqsz30sbDzw6tlP3Q==,
|
||||
integrity: sha512-BBjoAezNpHscGhBICHrt+X+IyJIh9jYnaEIGvbCIMcGB6sSDxvtttw4ef9+4jNh3JixotOR2mwIudTc1H9HffQ==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
"@tauri-apps/cli-win32-x64-msvc@1.6.0":
|
||||
"@tauri-apps/cli-win32-x64-msvc@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-h54FHOvGi7+LIfRchzgZYSCHB1HDlP599vWXQQJ/XnwJY+6Rwr2E5bOe/EhqoG8rbGkfK0xX3KPAvXPbUlmggg==,
|
||||
integrity: sha512-1pgDw2woeyDMvXctmqc53LBxsaAYqiRNUVgwvzlmzJDbUHv4+Pj4B1OGKQh1YKlsmks8LK3mK9uSbk+k1OLZhw==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
"@tauri-apps/cli@1.6.0":
|
||||
"@tauri-apps/cli@2.0.0-rc.8":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-DBBpBl6GhTzm8ImMbKkfaZ4fDTykWrC7Q5OXP4XqD91recmDEn2LExuvuiiS3HYe7uP8Eb5B9NPHhqJb+Zo7qQ==,
|
||||
integrity: sha512-hB6Pa0IaJs/As3Hc5IOiiK4Ilh9jspEA+2uPURCRQg4BkzQWwQzNdGQ4gjAzFNFAWPzy/4uuIXdnd1a+jC4wLA==,
|
||||
}
|
||||
engines: { node: ">= 10" }
|
||||
hasBin: true
|
||||
|
||||
"@tauri-apps/plugin-clipboard-manager@2.0.0-rc.0":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-2fS3wbRQEtorkk3Np2msJUeKCXRqLQ9sSo2FzlFdUPYNzThsu43uWCF55McGLAfltNOvXQIcQLUBf05jbBL/5w==,
|
||||
}
|
||||
|
||||
"@tauri-apps/plugin-dialog@2.0.0-rc.0":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-DPOXYe8SQ6Radk/67EOdaomlxL7oF99JO/ZUaPp1IBEs3Wro7lhlz63CfdKIBfKIZTLJLzP1R7/EiPL/GTA3Bg==,
|
||||
}
|
||||
|
||||
"@tauri-apps/plugin-fs@2.0.0-rc.1":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-r6N5dqBNXy9YAK9XbiEqAq3ZKBIN+TWevE7ZFmSRdvdSB1urrLweYu4wxycY2kDaDPzSeeOIJhCmqdNrFT9OSA==,
|
||||
}
|
||||
|
||||
"@tauri-apps/plugin-global-shortcut@2.0.0-rc.0":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-rcefV4AG+vnbTtGc07hDn4Uj8u//NpuqHVg1CShACyiCS0q2sZrDVC3qPN3RGhzQyeIOPq4bY1kQRHODffKXZA==,
|
||||
}
|
||||
|
||||
"@tauri-apps/plugin-notification@2.0.0-rc.0":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-0qsT/kvxQ6Ky4g6eQ4SUiHXzM4szTVc6thjz9vnGPYaApLoZrCJ9GdG+vEqeB+cT2dvE+wmxUFETh3ZXYVw8UA==,
|
||||
}
|
||||
|
||||
"@tauri-apps/plugin-process@2.0.0-rc.0":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-Z12D/kmQzG1vCVf+jLXPhPDUA0pEjFrsg4p0uwO2sotVLM9287IuTM+aIz9cuAYOxFLKcsnDG7amSCL9IfA1gw==,
|
||||
}
|
||||
|
||||
"@tauri-apps/plugin-shell@2.0.0-rc.0":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-bhUcQcrqZoK8H1DFXapr5r1Z75oh6Kd5Tltz97XpZFLREEqp+KhN2Fvyh8r/fKAyenYsTYUIsDsyGdjdueuF9g==,
|
||||
}
|
||||
|
||||
"@tauri-apps/plugin-updater@2.0.0-rc.0":
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-EKajf/sBpFif0cwXhTo3BmNvTZ2t2DDLRyhA8FFKugZNoOeqU97bHhPT5DIqMUPRE1tyDk9o7sXm8dKf7oz+EA==,
|
||||
}
|
||||
|
||||
"@types/babel__core@7.20.5":
|
||||
resolution:
|
||||
{
|
||||
|
@ -5959,50 +6030,82 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
"@tauri-apps/api@1.6.0": {}
|
||||
"@tauri-apps/api@2.0.0-rc.4": {}
|
||||
|
||||
"@tauri-apps/cli-darwin-arm64@1.6.0":
|
||||
"@tauri-apps/cli-darwin-arm64@2.0.0-rc.8":
|
||||
optional: true
|
||||
|
||||
"@tauri-apps/cli-darwin-x64@1.6.0":
|
||||
"@tauri-apps/cli-darwin-x64@2.0.0-rc.8":
|
||||
optional: true
|
||||
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf@1.6.0":
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-rc.8":
|
||||
optional: true
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-gnu@1.6.0":
|
||||
"@tauri-apps/cli-linux-arm64-gnu@2.0.0-rc.8":
|
||||
optional: true
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-musl@1.6.0":
|
||||
"@tauri-apps/cli-linux-arm64-musl@2.0.0-rc.8":
|
||||
optional: true
|
||||
|
||||
"@tauri-apps/cli-linux-x64-gnu@1.6.0":
|
||||
"@tauri-apps/cli-linux-x64-gnu@2.0.0-rc.8":
|
||||
optional: true
|
||||
|
||||
"@tauri-apps/cli-linux-x64-musl@1.6.0":
|
||||
"@tauri-apps/cli-linux-x64-musl@2.0.0-rc.8":
|
||||
optional: true
|
||||
|
||||
"@tauri-apps/cli-win32-arm64-msvc@1.6.0":
|
||||
"@tauri-apps/cli-win32-arm64-msvc@2.0.0-rc.8":
|
||||
optional: true
|
||||
|
||||
"@tauri-apps/cli-win32-ia32-msvc@1.6.0":
|
||||
"@tauri-apps/cli-win32-ia32-msvc@2.0.0-rc.8":
|
||||
optional: true
|
||||
|
||||
"@tauri-apps/cli-win32-x64-msvc@1.6.0":
|
||||
"@tauri-apps/cli-win32-x64-msvc@2.0.0-rc.8":
|
||||
optional: true
|
||||
|
||||
"@tauri-apps/cli@1.6.0":
|
||||
"@tauri-apps/cli@2.0.0-rc.8":
|
||||
optionalDependencies:
|
||||
"@tauri-apps/cli-darwin-arm64": 1.6.0
|
||||
"@tauri-apps/cli-darwin-x64": 1.6.0
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": 1.6.0
|
||||
"@tauri-apps/cli-linux-arm64-gnu": 1.6.0
|
||||
"@tauri-apps/cli-linux-arm64-musl": 1.6.0
|
||||
"@tauri-apps/cli-linux-x64-gnu": 1.6.0
|
||||
"@tauri-apps/cli-linux-x64-musl": 1.6.0
|
||||
"@tauri-apps/cli-win32-arm64-msvc": 1.6.0
|
||||
"@tauri-apps/cli-win32-ia32-msvc": 1.6.0
|
||||
"@tauri-apps/cli-win32-x64-msvc": 1.6.0
|
||||
"@tauri-apps/cli-darwin-arm64": 2.0.0-rc.8
|
||||
"@tauri-apps/cli-darwin-x64": 2.0.0-rc.8
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": 2.0.0-rc.8
|
||||
"@tauri-apps/cli-linux-arm64-gnu": 2.0.0-rc.8
|
||||
"@tauri-apps/cli-linux-arm64-musl": 2.0.0-rc.8
|
||||
"@tauri-apps/cli-linux-x64-gnu": 2.0.0-rc.8
|
||||
"@tauri-apps/cli-linux-x64-musl": 2.0.0-rc.8
|
||||
"@tauri-apps/cli-win32-arm64-msvc": 2.0.0-rc.8
|
||||
"@tauri-apps/cli-win32-ia32-msvc": 2.0.0-rc.8
|
||||
"@tauri-apps/cli-win32-x64-msvc": 2.0.0-rc.8
|
||||
|
||||
"@tauri-apps/plugin-clipboard-manager@2.0.0-rc.0":
|
||||
dependencies:
|
||||
"@tauri-apps/api": 2.0.0-rc.4
|
||||
|
||||
"@tauri-apps/plugin-dialog@2.0.0-rc.0":
|
||||
dependencies:
|
||||
"@tauri-apps/api": 2.0.0-rc.4
|
||||
|
||||
"@tauri-apps/plugin-fs@2.0.0-rc.1":
|
||||
dependencies:
|
||||
"@tauri-apps/api": 2.0.0-rc.4
|
||||
|
||||
"@tauri-apps/plugin-global-shortcut@2.0.0-rc.0":
|
||||
dependencies:
|
||||
"@tauri-apps/api": 2.0.0-rc.4
|
||||
|
||||
"@tauri-apps/plugin-notification@2.0.0-rc.0":
|
||||
dependencies:
|
||||
"@tauri-apps/api": 2.0.0-rc.4
|
||||
|
||||
"@tauri-apps/plugin-process@2.0.0-rc.0":
|
||||
dependencies:
|
||||
"@tauri-apps/api": 2.0.0-rc.4
|
||||
|
||||
"@tauri-apps/plugin-shell@2.0.0-rc.0":
|
||||
dependencies:
|
||||
"@tauri-apps/api": 2.0.0-rc.4
|
||||
|
||||
"@tauri-apps/plugin-updater@2.0.0-rc.0":
|
||||
dependencies:
|
||||
"@tauri-apps/api": 2.0.0-rc.4
|
||||
|
||||
"@types/babel__core@7.20.5":
|
||||
dependencies:
|
||||
|
|
2819
src-tauri/Cargo.lock
generated
2819
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,7 @@ edition = "2021"
|
|||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version="1", features = [] }
|
||||
tauri-build = { version= "2.0.0-rc", features = [] }
|
||||
|
||||
[dependencies]
|
||||
warp = "0.3"
|
||||
|
@ -32,13 +32,19 @@ delay_timer = "0.11"
|
|||
parking_lot = "0.12"
|
||||
auto-launch = "0.5.0"
|
||||
percent-encoding = "2.3.1"
|
||||
window-shadows = { version = "0.2" }
|
||||
window-shadows = { version = "0.2.2" }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
|
||||
sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" }
|
||||
tauri = { version="1", features = [ "fs-read-file", "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
|
||||
tauri = { version= "2.0.0-rc", features = [ "protocol-asset", "devtools", "tray-icon", "image-ico", "image-png"] }
|
||||
network-interface = { version = "2.0.0", features = ["serde"] }
|
||||
tauri-plugin-shell = "2.0.0-rc"
|
||||
tauri-plugin-dialog = "2.0.0-rc"
|
||||
tauri-plugin-fs = "2.0.0-rc"
|
||||
tauri-plugin-notification = "2.0.0-rc"
|
||||
tauri-plugin-process = "2.0.0-rc"
|
||||
tauri-plugin-clipboard-manager = "2.1.0-beta.7"
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
runas = "=1.2.0"
|
||||
deelevate = "0.2.0"
|
||||
|
@ -46,6 +52,10 @@ winreg = "0.52.0"
|
|||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
users = "0.11.0"
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-global-shortcut = "2.0.0-rc"
|
||||
tauri-plugin-updater = "2.0.0-rc"
|
||||
#openssl
|
||||
|
||||
[features]
|
||||
|
|
5
src-tauri/capabilities/desktop.json
Normal file
5
src-tauri/capabilities/desktop.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"identifier": "desktop-capability",
|
||||
"platforms": ["macOS", "windows", "linux"],
|
||||
"permissions": ["global-shortcut:default", "updater:default"]
|
||||
}
|
65
src-tauri/capabilities/migrated.json
Normal file
65
src-tauri/capabilities/migrated.json
Normal file
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"identifier": "migrated",
|
||||
"description": "permissions that were migrated from v1",
|
||||
"local": true,
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"fs:allow-read-file",
|
||||
"fs:allow-exists",
|
||||
{
|
||||
"identifier": "fs:scope",
|
||||
"allow": ["$APPDATA/**", "$RESOURCE/../**", "**"]
|
||||
},
|
||||
"core:window:allow-create",
|
||||
"core:window:allow-center",
|
||||
"core:window:allow-request-user-attention",
|
||||
"core:window:allow-set-resizable",
|
||||
"core:window:allow-set-maximizable",
|
||||
"core:window:allow-set-minimizable",
|
||||
"core:window:allow-set-closable",
|
||||
"core:window:allow-set-title",
|
||||
"core:window:allow-maximize",
|
||||
"core:window:allow-unmaximize",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-unminimize",
|
||||
"core:window:allow-show",
|
||||
"core:window:allow-hide",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-set-decorations",
|
||||
"core:window:allow-set-always-on-top",
|
||||
"core:window:allow-set-content-protected",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:allow-set-min-size",
|
||||
"core:window:allow-set-max-size",
|
||||
"core:window:allow-set-position",
|
||||
"core:window:allow-set-fullscreen",
|
||||
"core:window:allow-set-focus",
|
||||
"core:window:allow-set-icon",
|
||||
"core:window:allow-set-skip-taskbar",
|
||||
"core:window:allow-set-cursor-grab",
|
||||
"core:window:allow-set-cursor-visible",
|
||||
"core:window:allow-set-cursor-icon",
|
||||
"core:window:allow-set-cursor-position",
|
||||
"core:window:allow-set-ignore-cursor-events",
|
||||
"core:window:allow-start-dragging",
|
||||
"core:webview:allow-print",
|
||||
"shell:allow-execute",
|
||||
"shell:allow-open",
|
||||
"dialog:allow-open",
|
||||
"notification:default",
|
||||
"global-shortcut:allow-is-registered",
|
||||
"global-shortcut:allow-register",
|
||||
"global-shortcut:allow-register-all",
|
||||
"global-shortcut:allow-unregister",
|
||||
"global-shortcut:allow-unregister-all",
|
||||
"process:allow-restart",
|
||||
"process:allow-exit",
|
||||
"clipboard-manager:allow-read-text",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"shell:default",
|
||||
"dialog:default",
|
||||
"fs:default",
|
||||
"notification:default"
|
||||
]
|
||||
}
|
3811
src-tauri/gen/schemas/acl-manifests.json
Normal file
3811
src-tauri/gen/schemas/acl-manifests.json
Normal file
File diff suppressed because it is too large
Load Diff
74
src-tauri/gen/schemas/capabilities.json
Normal file
74
src-tauri/gen/schemas/capabilities.json
Normal file
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"desktop-capability": {
|
||||
"identifier": "desktop-capability",
|
||||
"description": "",
|
||||
"local": true,
|
||||
"permissions": ["global-shortcut:default", "updater:default"],
|
||||
"platforms": ["macOS", "windows", "linux"]
|
||||
},
|
||||
"migrated": {
|
||||
"identifier": "migrated",
|
||||
"description": "permissions that were migrated from v1",
|
||||
"local": true,
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"fs:allow-read-file",
|
||||
"fs:allow-exists",
|
||||
{
|
||||
"identifier": "fs:scope",
|
||||
"allow": ["$APPDATA/**", "$RESOURCE/../**", "**"]
|
||||
},
|
||||
"core:window:allow-create",
|
||||
"core:window:allow-center",
|
||||
"core:window:allow-request-user-attention",
|
||||
"core:window:allow-set-resizable",
|
||||
"core:window:allow-set-maximizable",
|
||||
"core:window:allow-set-minimizable",
|
||||
"core:window:allow-set-closable",
|
||||
"core:window:allow-set-title",
|
||||
"core:window:allow-maximize",
|
||||
"core:window:allow-unmaximize",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-unminimize",
|
||||
"core:window:allow-show",
|
||||
"core:window:allow-hide",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-set-decorations",
|
||||
"core:window:allow-set-always-on-top",
|
||||
"core:window:allow-set-content-protected",
|
||||
"core:window:allow-set-size",
|
||||
"core:window:allow-set-min-size",
|
||||
"core:window:allow-set-max-size",
|
||||
"core:window:allow-set-position",
|
||||
"core:window:allow-set-fullscreen",
|
||||
"core:window:allow-set-focus",
|
||||
"core:window:allow-set-icon",
|
||||
"core:window:allow-set-skip-taskbar",
|
||||
"core:window:allow-set-cursor-grab",
|
||||
"core:window:allow-set-cursor-visible",
|
||||
"core:window:allow-set-cursor-icon",
|
||||
"core:window:allow-set-cursor-position",
|
||||
"core:window:allow-set-ignore-cursor-events",
|
||||
"core:window:allow-start-dragging",
|
||||
"core:webview:allow-print",
|
||||
"shell:allow-execute",
|
||||
"shell:allow-open",
|
||||
"dialog:allow-open",
|
||||
"notification:default",
|
||||
"global-shortcut:allow-is-registered",
|
||||
"global-shortcut:allow-register",
|
||||
"global-shortcut:allow-register-all",
|
||||
"global-shortcut:allow-unregister",
|
||||
"global-shortcut:allow-unregister-all",
|
||||
"process:allow-restart",
|
||||
"process:allow-exit",
|
||||
"clipboard-manager:allow-read-text",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"shell:default",
|
||||
"dialog:default",
|
||||
"fs:default",
|
||||
"notification:default"
|
||||
]
|
||||
}
|
||||
}
|
5171
src-tauri/gen/schemas/desktop-schema.json
Normal file
5171
src-tauri/gen/schemas/desktop-schema.json
Normal file
File diff suppressed because it is too large
Load Diff
5171
src-tauri/gen/schemas/macOS-schema.json
Normal file
5171
src-tauri/gen/schemas/macOS-schema.json
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -10,8 +10,8 @@ use network_interface::NetworkInterface;
|
|||
use serde_yaml::Mapping;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use sysproxy::{Autoproxy, Sysproxy};
|
||||
use tauri::{api, Manager};
|
||||
type CmdResult<T = ()> = Result<T, String>;
|
||||
use tauri::Manager;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn copy_clash_env(app_handle: tauri::AppHandle) -> CmdResult {
|
||||
|
@ -361,7 +361,7 @@ pub fn get_network_interfaces_info() -> CmdResult<Vec<NetworkInterface>> {
|
|||
|
||||
#[tauri::command]
|
||||
pub fn open_devtools(app_handle: tauri::AppHandle) {
|
||||
if let Some(window) = app_handle.get_window("main") {
|
||||
if let Some(window) = app_handle.get_webview_window("main") {
|
||||
if !window.is_devtools_open() {
|
||||
window.open_devtools();
|
||||
} else {
|
||||
|
@ -374,7 +374,6 @@ pub fn open_devtools(app_handle: tauri::AppHandle) {
|
|||
pub fn exit_app(app_handle: tauri::AppHandle) {
|
||||
let _ = resolve::save_window_size_position(&app_handle, true);
|
||||
resolve::resolve_reset();
|
||||
api::process::kill_children();
|
||||
app_handle.exit(0);
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
|
|
@ -2,19 +2,22 @@ use crate::config::*;
|
|||
use crate::core::{clash_api, handle, logger::Logger, service};
|
||||
use crate::log_err;
|
||||
use crate::utils::dirs;
|
||||
use anyhow::{bail, Result};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use serde_yaml::Mapping;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use std::{fs, io::Write, sync::Arc, time::Duration};
|
||||
use sysinfo::{ProcessRefreshKind, RefreshKind, System};
|
||||
use tauri::api::process::{Command, CommandChild, CommandEvent};
|
||||
use tauri::AppHandle;
|
||||
use tauri_plugin_shell::process::{CommandChild, CommandEvent};
|
||||
use tauri_plugin_shell::ShellExt;
|
||||
|
||||
use tokio::time::sleep;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CoreManager {
|
||||
app_handle: Arc<Mutex<Option<AppHandle>>>,
|
||||
sidecar: Arc<Mutex<Option<CommandChild>>>,
|
||||
|
||||
#[allow(unused)]
|
||||
use_service_mode: Arc<Mutex<bool>>,
|
||||
}
|
||||
|
@ -24,12 +27,14 @@ impl CoreManager {
|
|||
static CORE_MANAGER: OnceCell<CoreManager> = OnceCell::new();
|
||||
|
||||
CORE_MANAGER.get_or_init(|| CoreManager {
|
||||
app_handle: Arc::new(Mutex::new(None)),
|
||||
sidecar: Arc::new(Mutex::new(None)),
|
||||
use_service_mode: Arc::new(Mutex::new(false)),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn init(&self) -> Result<()> {
|
||||
pub fn init(&self, app_handle: &AppHandle) -> Result<()> {
|
||||
*self.app_handle.lock() = Some(app_handle.clone());
|
||||
tauri::async_runtime::spawn(async {
|
||||
// 启动clash
|
||||
log_err!(Self::global().run_core().await);
|
||||
|
@ -39,7 +44,7 @@ impl CoreManager {
|
|||
}
|
||||
|
||||
/// 检查订阅是否正确
|
||||
pub fn check_config(&self) -> Result<()> {
|
||||
pub async fn check_config(&self) -> Result<()> {
|
||||
let config_path = Config::generate_file(ConfigType::Check)?;
|
||||
let config_path = dirs::path_to_str(&config_path)?;
|
||||
|
||||
|
@ -62,20 +67,30 @@ impl CoreManager {
|
|||
|
||||
let test_dir = dirs::app_home_dir()?.join("test");
|
||||
let test_dir = dirs::path_to_str(&test_dir)?;
|
||||
let app_handle_option = {
|
||||
let lock = self.app_handle.lock();
|
||||
lock.as_ref().cloned()
|
||||
};
|
||||
|
||||
let output = Command::new_sidecar(clash_core)?
|
||||
if let Some(app_handle) = app_handle_option {
|
||||
let output = app_handle
|
||||
.shell()
|
||||
.sidecar(clash_core)?
|
||||
.args(["-t", "-d", test_dir, "-f", config_path])
|
||||
.output()?;
|
||||
.output()
|
||||
.await?;
|
||||
|
||||
if !output.status.success() {
|
||||
let error = clash_api::parse_check_output(output.stdout.clone());
|
||||
let stdout = String::from_utf8(output.stdout).unwrap_or_default();
|
||||
let error = clash_api::parse_check_output(stdout.clone());
|
||||
let error = match !error.is_empty() {
|
||||
true => error,
|
||||
false => output.stdout.clone(),
|
||||
false => stdout.clone(),
|
||||
};
|
||||
Logger::global().set_log(output.stdout);
|
||||
Logger::global().set_log(stdout.clone());
|
||||
bail!("{error}");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -156,9 +171,23 @@ impl CoreManager {
|
|||
|
||||
let args = vec!["-d", app_dir, "-f", config_path];
|
||||
|
||||
let cmd = Command::new_sidecar(clash_core)?;
|
||||
let app_handle = self.app_handle.lock();
|
||||
|
||||
if let Some(app_handle) = app_handle.as_ref() {
|
||||
let cmd = app_handle.shell().sidecar(clash_core)?;
|
||||
let (mut rx, cmd_child) = cmd.args(args).spawn()?;
|
||||
|
||||
// 将pid写入文件中
|
||||
crate::log_err!((|| {
|
||||
let pid = cmd_child.pid();
|
||||
let path = dirs::clash_pid_path()?;
|
||||
fs::File::create(path)
|
||||
.context("failed to create the pid file")?
|
||||
.write(format!("{pid}").as_bytes())
|
||||
.context("failed to write pid to the file")?;
|
||||
<Result<()>>::Ok(())
|
||||
})());
|
||||
|
||||
let mut sidecar = self.sidecar.lock();
|
||||
*sidecar = Some(cmd_child);
|
||||
drop(sidecar);
|
||||
|
@ -167,10 +196,12 @@ impl CoreManager {
|
|||
while let Some(event) = rx.recv().await {
|
||||
match event {
|
||||
CommandEvent::Stdout(line) => {
|
||||
let line = String::from_utf8(line).unwrap_or_default();
|
||||
log::info!(target: "app", "[mihomo]: {line}");
|
||||
Logger::global().set_log(line);
|
||||
}
|
||||
CommandEvent::Stderr(err) => {
|
||||
let err = String::from_utf8(err).unwrap_or_default();
|
||||
log::error!(target: "app", "[mihomo]: {err}");
|
||||
Logger::global().set_log(err);
|
||||
}
|
||||
|
@ -187,6 +218,7 @@ impl CoreManager {
|
|||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -268,7 +300,7 @@ impl CoreManager {
|
|||
// 更新订阅
|
||||
Config::generate().await?;
|
||||
|
||||
self.check_config()?;
|
||||
self.check_config().await?;
|
||||
|
||||
// 清掉旧日志
|
||||
Logger::global().clear_log();
|
||||
|
@ -296,7 +328,7 @@ impl CoreManager {
|
|||
Config::generate().await?;
|
||||
|
||||
// 检查订阅是否正常
|
||||
self.check_config()?;
|
||||
self.check_config().await?;
|
||||
|
||||
// 更新运行时订阅
|
||||
let path = Config::generate_file(ConfigType::Run)?;
|
||||
|
|
|
@ -4,7 +4,7 @@ use anyhow::{bail, Result};
|
|||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::Arc;
|
||||
use tauri::{AppHandle, Manager, Window};
|
||||
use tauri::{AppHandle, WebviewWindow, Manager, Emitter};
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Handle {
|
||||
|
@ -20,15 +20,15 @@ impl Handle {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn init(&self, app_handle: AppHandle) {
|
||||
*self.app_handle.lock() = Some(app_handle);
|
||||
pub fn init(&self, app_handle: &AppHandle) {
|
||||
*self.app_handle.lock() = Some(app_handle.clone());
|
||||
}
|
||||
|
||||
pub fn get_window(&self) -> Option<Window> {
|
||||
pub fn get_window(&self) -> Option<WebviewWindow> {
|
||||
self.app_handle
|
||||
.lock()
|
||||
.as_ref()
|
||||
.and_then(|a| a.get_window("main"))
|
||||
.and_then(|a| a.get_webview_window("main"))
|
||||
}
|
||||
|
||||
pub fn refresh_clash() {
|
||||
|
|
|
@ -3,11 +3,11 @@ use anyhow::{bail, Result};
|
|||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
use tauri::{AppHandle, GlobalShortcutManager};
|
||||
use tauri::AppHandle;
|
||||
use tauri_plugin_global_shortcut::GlobalShortcutExt;
|
||||
|
||||
pub struct Hotkey {
|
||||
current: Arc<Mutex<Vec<String>>>, // 保存当前的热键设置
|
||||
|
||||
app_handle: Arc<Mutex<Option<AppHandle>>>,
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,8 @@ impl Hotkey {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn init(&self, app_handle: AppHandle) -> Result<()> {
|
||||
*self.app_handle.lock() = Some(app_handle);
|
||||
|
||||
pub fn init(&self, app_handle: &AppHandle) -> Result<()> {
|
||||
*self.app_handle.lock() = Some(app_handle.clone());
|
||||
let verge = Config::verge();
|
||||
|
||||
if let Some(hotkeys) = verge.latest().hotkeys.as_ref() {
|
||||
|
@ -49,18 +48,14 @@ impl Hotkey {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_manager(&self) -> Result<impl GlobalShortcutManager> {
|
||||
fn register(&self, hotkey: &str, func: &str) -> Result<()> {
|
||||
let app_handle = self.app_handle.lock();
|
||||
if app_handle.is_none() {
|
||||
bail!("failed to get the hotkey manager");
|
||||
}
|
||||
Ok(app_handle.as_ref().unwrap().global_shortcut_manager())
|
||||
}
|
||||
let manager = app_handle.as_ref().unwrap().global_shortcut();
|
||||
|
||||
fn register(&self, hotkey: &str, func: &str) -> Result<()> {
|
||||
let mut manager = self.get_manager()?;
|
||||
|
||||
if manager.is_registered(hotkey)? {
|
||||
if manager.is_registered(hotkey) {
|
||||
manager.unregister(hotkey)?;
|
||||
}
|
||||
|
||||
|
@ -71,17 +66,22 @@ impl Hotkey {
|
|||
"clash_mode_direct" => || feat::change_clash_mode("direct".into()),
|
||||
"toggle_system_proxy" => feat::toggle_system_proxy,
|
||||
"toggle_tun_mode" => feat::toggle_tun_mode,
|
||||
|
||||
_ => bail!("invalid function \"{func}\""),
|
||||
};
|
||||
|
||||
manager.register(hotkey, f)?;
|
||||
let _ = manager.on_shortcut(hotkey, move |_, _, _| f());
|
||||
log::info!(target: "app", "register hotkey {hotkey} {func}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unregister(&self, hotkey: &str) -> Result<()> {
|
||||
self.get_manager()?.unregister(hotkey)?;
|
||||
let app_handle = self.app_handle.lock();
|
||||
if app_handle.is_none() {
|
||||
bail!("failed to get the hotkey manager");
|
||||
}
|
||||
let manager = app_handle.as_ref().unwrap().global_shortcut();
|
||||
manager.unregister(hotkey)?;
|
||||
|
||||
log::info!(target: "app", "unregister hotkey {hotkey}");
|
||||
Ok(())
|
||||
}
|
||||
|
@ -153,8 +153,10 @@ impl Hotkey {
|
|||
|
||||
impl Drop for Hotkey {
|
||||
fn drop(&mut self) {
|
||||
if let Ok(mut manager) = self.get_manager() {
|
||||
let _ = manager.unregister_all();
|
||||
if let Some(app_handle) = self.app_handle.lock().as_ref() {
|
||||
if let Err(e) = app_handle.global_shortcut().unregister_all() {
|
||||
log::error!("Error unregistering all hotkeys: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,19 +5,14 @@ use crate::{
|
|||
utils::{dirs, resolve},
|
||||
};
|
||||
use anyhow::Result;
|
||||
use tauri::{
|
||||
api, AppHandle, CustomMenuItem, Manager, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
|
||||
SystemTraySubmenu,
|
||||
};
|
||||
|
||||
use tauri::menu::{MenuBuilder, MenuEvent, MenuItemBuilder, PredefinedMenuItem, SubmenuBuilder};
|
||||
use tauri::tray::{MouseButton, MouseButtonState, TrayIcon, TrayIconBuilder, TrayIconEvent};
|
||||
use tauri::{AppHandle, Manager};
|
||||
pub struct Tray {}
|
||||
|
||||
impl Tray {
|
||||
pub fn tray_menu(app_handle: &AppHandle) -> SystemTrayMenu {
|
||||
pub fn update_systray(app_handle: &AppHandle) -> Result<()> {
|
||||
let zh = { Config::verge().latest().language == Some("zh".into()) };
|
||||
|
||||
let version = app_handle.package_info().version.to_string();
|
||||
|
||||
macro_rules! t {
|
||||
($en: expr, $zh: expr) => {
|
||||
if zh {
|
||||
|
@ -28,80 +23,92 @@ impl Tray {
|
|||
};
|
||||
}
|
||||
|
||||
SystemTrayMenu::new()
|
||||
.add_item(CustomMenuItem::new(
|
||||
"open_window",
|
||||
t!("Dashboard", "打开面板"),
|
||||
))
|
||||
.add_native_item(SystemTrayMenuItem::Separator)
|
||||
.add_item(CustomMenuItem::new(
|
||||
"rule_mode",
|
||||
t!("Rule Mode", "规则模式"),
|
||||
))
|
||||
.add_item(CustomMenuItem::new(
|
||||
"global_mode",
|
||||
t!("Global Mode", "全局模式"),
|
||||
))
|
||||
.add_item(CustomMenuItem::new(
|
||||
"direct_mode",
|
||||
t!("Direct Mode", "直连模式"),
|
||||
))
|
||||
.add_native_item(SystemTrayMenuItem::Separator)
|
||||
.add_item(CustomMenuItem::new(
|
||||
"system_proxy",
|
||||
t!("System Proxy", "系统代理"),
|
||||
))
|
||||
.add_item(CustomMenuItem::new("tun_mode", t!("TUN Mode", "Tun 模式")))
|
||||
.add_item(CustomMenuItem::new(
|
||||
"copy_env",
|
||||
t!("Copy Env", "复制环境变量"),
|
||||
))
|
||||
.add_submenu(SystemTraySubmenu::new(
|
||||
t!("Open Dir", "打开目录"),
|
||||
SystemTrayMenu::new()
|
||||
.add_item(CustomMenuItem::new(
|
||||
"open_app_dir",
|
||||
t!("App Dir", "应用目录"),
|
||||
))
|
||||
.add_item(CustomMenuItem::new(
|
||||
"open_core_dir",
|
||||
t!("Core Dir", "内核目录"),
|
||||
))
|
||||
.add_item(CustomMenuItem::new(
|
||||
"open_logs_dir",
|
||||
t!("Logs Dir", "日志目录"),
|
||||
)),
|
||||
))
|
||||
.add_submenu(SystemTraySubmenu::new(
|
||||
t!("More", "更多"),
|
||||
SystemTrayMenu::new()
|
||||
.add_item(CustomMenuItem::new(
|
||||
"restart_clash",
|
||||
t!("Restart Clash", "重启 Clash"),
|
||||
))
|
||||
.add_item(CustomMenuItem::new(
|
||||
"restart_app",
|
||||
t!("Restart App", "重启应用"),
|
||||
))
|
||||
.add_item(
|
||||
CustomMenuItem::new("app_version", format!("Version {version}")).disabled(),
|
||||
),
|
||||
))
|
||||
.add_native_item(SystemTrayMenuItem::Separator)
|
||||
.add_item(CustomMenuItem::new("quit", t!("Quit", "退出")))
|
||||
}
|
||||
let version = app_handle.package_info().version.to_string();
|
||||
|
||||
let open_window = MenuItemBuilder::with_id("open_window", t!("Dashboard", "打开面板"))
|
||||
.build(app_handle)?;
|
||||
let rule_mode =
|
||||
MenuItemBuilder::with_id("rule_mode", t!("Rule Mode", "规则模式")).build(app_handle)?;
|
||||
let global_mode = MenuItemBuilder::with_id("global_mode", t!("Global Mode", "全局模式"))
|
||||
.build(app_handle)?;
|
||||
let direct_mode = MenuItemBuilder::with_id("direct_mode", t!("Direct Mode", "直连模式"))
|
||||
.build(app_handle)?;
|
||||
let system_proxy = MenuItemBuilder::with_id("system_proxy", t!("System Proxy", "系统代理"))
|
||||
.build(app_handle)?;
|
||||
let tun_mode =
|
||||
MenuItemBuilder::with_id("tun_mode", t!("TUN Mode", "Tun 模式")).build(app_handle)?;
|
||||
let copy_env = MenuItemBuilder::with_id("copy_env", t!("Copy Env", "复制环境变量"))
|
||||
.build(app_handle)?;
|
||||
let open_app_dir = MenuItemBuilder::with_id("open_app_dir", t!("App Dir", "应用目录"))
|
||||
.build(app_handle)?;
|
||||
let open_core_dir = MenuItemBuilder::with_id("open_core_dir", t!("Core Dir", "内核目录"))
|
||||
.build(app_handle)?;
|
||||
let open_logs_dir = MenuItemBuilder::with_id("open_logs_dir", t!("Logs Dir", "日志目录"))
|
||||
.build(app_handle)?;
|
||||
let open_dir = SubmenuBuilder::with_id(app_handle, "open_dir", t!("Open Dir", "打开目录"))
|
||||
.items(&[&open_app_dir, &open_core_dir, &open_logs_dir])
|
||||
.build()?;
|
||||
let restart_clash =
|
||||
MenuItemBuilder::with_id("restart_clash", t!("Restart Clash", "重启 Clash"))
|
||||
.build(app_handle)?;
|
||||
let restart_app = MenuItemBuilder::with_id("restart_app", t!("Restart App", "重启应用"))
|
||||
.build(app_handle)?;
|
||||
let app_version = MenuItemBuilder::with_id("app_version", format!("Version {version}"))
|
||||
.build(app_handle)?;
|
||||
let more = SubmenuBuilder::with_id(app_handle, "more", t!("More", "更多"))
|
||||
.items(&[&restart_clash, &restart_app, &app_version])
|
||||
.build()?;
|
||||
let quit = MenuItemBuilder::with_id("quit", t!("Quit", "退出"))
|
||||
.accelerator("CmdOrControl+Q")
|
||||
.build(app_handle)?;
|
||||
let separator = PredefinedMenuItem::separator(app_handle)?;
|
||||
let menu = MenuBuilder::new(app_handle)
|
||||
.items(&[
|
||||
&open_window,
|
||||
&separator,
|
||||
&rule_mode,
|
||||
&global_mode,
|
||||
&direct_mode,
|
||||
&separator,
|
||||
&system_proxy,
|
||||
&tun_mode,
|
||||
©_env,
|
||||
&open_dir,
|
||||
&more,
|
||||
&separator,
|
||||
&quit,
|
||||
])
|
||||
.build()?;
|
||||
|
||||
let _ = TrayIconBuilder::with_id("verge_tray")
|
||||
.menu(&menu)
|
||||
.on_menu_event(Self::on_menu_event)
|
||||
.on_tray_icon_event(|tray, event| {
|
||||
let tray_event = { Config::verge().latest().tray_event.clone() };
|
||||
let tray_event: String = tray_event.unwrap_or("main_window".into());
|
||||
if let TrayIconEvent::Click {
|
||||
button: MouseButton::Left,
|
||||
button_state: MouseButtonState::Up,
|
||||
..
|
||||
} = event
|
||||
{
|
||||
let app = tray.app_handle();
|
||||
match tray_event.as_str() {
|
||||
"system_proxy" => feat::toggle_system_proxy(),
|
||||
"tun_mode" => feat::toggle_tun_mode(),
|
||||
"main_window" => resolve::create_window(app),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
})
|
||||
.build(app_handle);
|
||||
|
||||
pub fn update_systray(app_handle: &AppHandle) -> Result<()> {
|
||||
app_handle
|
||||
.tray_handle()
|
||||
.set_menu(Tray::tray_menu(app_handle))?;
|
||||
Tray::update_part(app_handle)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_part(app_handle: &AppHandle) -> Result<()> {
|
||||
let zh = { Config::verge().latest().language == Some("zh".into()) };
|
||||
|
||||
let version = app_handle.package_info().version.to_string();
|
||||
|
||||
macro_rules! t {
|
||||
|
@ -124,46 +131,85 @@ impl Tray {
|
|||
.to_owned()
|
||||
};
|
||||
|
||||
let tray = app_handle.tray_handle();
|
||||
|
||||
let _ = tray.get_item("rule_mode").set_selected(mode == "rule");
|
||||
let _ = tray.get_item("global_mode").set_selected(mode == "global");
|
||||
let _ = tray.get_item("direct_mode").set_selected(mode == "direct");
|
||||
if let Some(menu) = app_handle.menu() {
|
||||
if let Some(item) = menu.get("rule_mode") {
|
||||
let item = item.as_check_menuitem().unwrap();
|
||||
let _ = item.set_checked(mode == "rule");
|
||||
}
|
||||
if let Some(item) = menu.get("global_mode") {
|
||||
let item = item.as_check_menuitem().unwrap();
|
||||
let _ = item.set_checked(mode == "global");
|
||||
}
|
||||
if let Some(item) = menu.get("direct_mode") {
|
||||
let item = item.as_check_menuitem().unwrap();
|
||||
let _ = item.set_checked(mode == "direct");
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
match mode.as_str() {
|
||||
"rule" => {
|
||||
let _ = tray
|
||||
.get_item("rule_mode")
|
||||
.set_title(t!("Rule Mode ✔", "规则模式 ✔"));
|
||||
let _ = tray
|
||||
.get_item("global_mode")
|
||||
.set_title(t!("Global Mode", "全局模式"));
|
||||
let _ = tray
|
||||
.get_item("direct_mode")
|
||||
.set_title(t!("Direct Mode", "直连模式"));
|
||||
if let Some(item) = menu.get("rule_mode") {
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("Rule Mode ✔", "规则模式 ✔"));
|
||||
}
|
||||
|
||||
if let Some(item) = menu.get("global_mode") {
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("Global Mode", "全局模式"));
|
||||
}
|
||||
|
||||
if let Some(item) = menu.get("direct_mode") {
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("Direct Mode", "直连模式"));
|
||||
}
|
||||
}
|
||||
"global" => {
|
||||
let _ = tray
|
||||
.get_item("rule_mode")
|
||||
.set_title(t!("Rule Mode", "规则模式"));
|
||||
let _ = tray
|
||||
.get_item("global_mode")
|
||||
.set_title(t!("Global Mode ✔", "全局模式 ✔"));
|
||||
let _ = tray
|
||||
.get_item("direct_mode")
|
||||
.set_title(t!("Direct Mode", "直连模式"));
|
||||
if let Some(item) = menu.get("rule_mode") {
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("Rule Mode", "规则模式"));
|
||||
}
|
||||
|
||||
if let Some(item) = menu.get("global_mode") {
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("Global Mode ✔", "全局模式 ✔"));
|
||||
}
|
||||
|
||||
if let Some(item) = menu.get("direct_mode") {
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("Direct Mode", "直连模式"));
|
||||
}
|
||||
}
|
||||
"direct" => {
|
||||
let _ = tray
|
||||
.get_item("rule_mode")
|
||||
.set_title(t!("Rule Mode", "规则模式"));
|
||||
let _ = tray
|
||||
.get_item("global_mode")
|
||||
.set_title(t!("Global Mode", "全局模式"));
|
||||
let _ = tray
|
||||
.get_item("direct_mode")
|
||||
.set_title(t!("Direct Mode ✔", "直连模式 ✔"));
|
||||
if let Some(item) = menu.get("rule_mode") {
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("Rule Mode", "规则模式"));
|
||||
}
|
||||
if let Some(item) = menu.get("global_mode") {
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("Global Mode", "全局模式"));
|
||||
}
|
||||
if let Some(item) = menu.get("direct_mode") {
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("Direct Mode ✔", "直连模式 ✔"));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -177,6 +223,8 @@ impl Tray {
|
|||
let common_tray_icon = verge.common_tray_icon.as_ref().unwrap_or(&false);
|
||||
let sysproxy_tray_icon = verge.sysproxy_tray_icon.as_ref().unwrap_or(&false);
|
||||
let tun_tray_icon = verge.tun_tray_icon.as_ref().unwrap_or(&false);
|
||||
let tray: TrayIcon = app_handle.tray_by_id("verge_tray").unwrap();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
match tray_icon.as_str() {
|
||||
"monochrome" => {
|
||||
|
@ -229,7 +277,6 @@ impl Tray {
|
|||
}
|
||||
icon
|
||||
};
|
||||
|
||||
if *tun_mode {
|
||||
#[cfg(target_os = "macos")]
|
||||
let mut icon = match tray_icon.as_str() {
|
||||
|
@ -252,29 +299,44 @@ impl Tray {
|
|||
indication_icon = icon
|
||||
}
|
||||
|
||||
let _ = tray.set_icon(tauri::Icon::Raw(indication_icon));
|
||||
let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&indication_icon)?));
|
||||
if let Some(item) = menu.get("system_proxy") {
|
||||
let item = item.as_check_menuitem().unwrap();
|
||||
let _ = item.set_checked(mode == "system_proxy");
|
||||
}
|
||||
if let Some(item) = menu.get("tun_mode") {
|
||||
let item = item.as_check_menuitem().unwrap();
|
||||
let _ = item.set_checked(mode == "tun_mode");
|
||||
}
|
||||
|
||||
let _ = tray.get_item("system_proxy").set_selected(*system_proxy);
|
||||
let _ = tray.get_item("tun_mode").set_selected(*tun_mode);
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if let Some(item) = menu.get("system_proxy") {
|
||||
if *system_proxy {
|
||||
let _ = tray
|
||||
.get_item("system_proxy")
|
||||
.set_title(t!("System Proxy ✔", "系统代理 ✔"));
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("System Proxy ✔", "系统代理 ✔"));
|
||||
} else {
|
||||
let _ = tray
|
||||
.get_item("system_proxy")
|
||||
.set_title(t!("System Proxy", "系统代理"));
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("System Proxy", "系统代理"));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(item) = menu.get("tun_mode") {
|
||||
if *tun_mode {
|
||||
let _ = tray
|
||||
.get_item("tun_mode")
|
||||
.set_title(t!("TUN Mode ✔", "Tun 模式 ✔"));
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("TUN Mode ✔", "Tun 模式 ✔"));
|
||||
} else {
|
||||
let _ = tray
|
||||
.get_item("tun_mode")
|
||||
.set_title(t!("TUN Mode", "Tun 模式"));
|
||||
let _ = item
|
||||
.as_menuitem()
|
||||
.unwrap()
|
||||
.set_text(t!("TUN Mode", "Tun 模式"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,7 +357,8 @@ impl Tray {
|
|||
None => current_profile_name,
|
||||
};
|
||||
};
|
||||
let _ = tray.set_tooltip(&format!(
|
||||
|
||||
let _ = tray.set_tooltip(Some(&format!(
|
||||
"Clash Verge {version}\n{}: {}\n{}: {}\n{}: {}",
|
||||
t!("SysProxy", "系统代理"),
|
||||
switch_map[system_proxy],
|
||||
|
@ -303,29 +366,14 @@ impl Tray {
|
|||
switch_map[tun_mode],
|
||||
t!("Profile", "当前订阅"),
|
||||
current_profile_name
|
||||
));
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn on_click(app_handle: &AppHandle) {
|
||||
let tray_event = { Config::verge().latest().tray_event.clone() };
|
||||
let tray_event = tray_event.unwrap_or("main_window".into());
|
||||
match tray_event.as_str() {
|
||||
"system_proxy" => feat::toggle_system_proxy(),
|
||||
"tun_mode" => feat::toggle_tun_mode(),
|
||||
"main_window" => resolve::create_window(app_handle),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_system_tray_event(app_handle: &AppHandle, event: SystemTrayEvent) {
|
||||
match event {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
SystemTrayEvent::LeftClick { .. } => Tray::on_click(app_handle),
|
||||
#[cfg(target_os = "macos")]
|
||||
SystemTrayEvent::RightClick { .. } => Tray::on_click(app_handle),
|
||||
SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
|
||||
pub fn on_menu_event(app_handle: &AppHandle, event: MenuEvent) {
|
||||
match event.id.as_ref() {
|
||||
mode @ ("rule_mode" | "global_mode" | "direct_mode") => {
|
||||
let mode = &mode[0..mode.len() - 5];
|
||||
feat::change_clash_mode(mode.into());
|
||||
|
@ -338,11 +386,8 @@ impl Tray {
|
|||
"open_core_dir" => crate::log_err!(cmds::open_core_dir()),
|
||||
"open_logs_dir" => crate::log_err!(cmds::open_logs_dir()),
|
||||
"restart_clash" => feat::restart_clash_core(),
|
||||
"restart_app" => api::process::restart(&app_handle.env()),
|
||||
"restart_app" => tauri::process::restart(&app_handle.env()),
|
||||
"quit" => cmds::exit_app(app_handle.clone()),
|
||||
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,14 +10,15 @@ use crate::log_err;
|
|||
use crate::utils::resolve;
|
||||
use anyhow::{bail, Result};
|
||||
use serde_yaml::{Mapping, Value};
|
||||
use tauri::{AppHandle, ClipboardManager, Manager};
|
||||
use tauri::{AppHandle, Manager};
|
||||
use tauri_plugin_clipboard_manager::ClipboardExt;
|
||||
|
||||
// 打开面板
|
||||
pub fn open_or_close_dashboard() {
|
||||
let handle = handle::Handle::global();
|
||||
let app_handle = handle.app_handle.lock();
|
||||
if let Some(app_handle) = app_handle.as_ref() {
|
||||
if let Some(window) = app_handle.get_window("main") {
|
||||
if let Some(window) = app_handle.get_webview_window("main") {
|
||||
if let Ok(true) = window.is_focused() {
|
||||
let _ = window.close();
|
||||
return;
|
||||
|
@ -319,8 +320,7 @@ pub fn copy_clash_env(app_handle: &AppHandle) {
|
|||
let cmd: String = format!("set http_proxy={http_proxy}\r\nset https_proxy={http_proxy}");
|
||||
let ps: String = format!("$env:HTTP_PROXY=\"{http_proxy}\"; $env:HTTPS_PROXY=\"{http_proxy}\"");
|
||||
|
||||
let mut cliboard = app_handle.clipboard_manager();
|
||||
|
||||
let cliboard = app_handle.clipboard();
|
||||
let env_type = { Config::verge().latest().env_type.clone() };
|
||||
let env_type = match env_type {
|
||||
Some(env_type) => env_type,
|
||||
|
|
|
@ -11,7 +11,7 @@ mod feat;
|
|||
mod utils;
|
||||
|
||||
use crate::utils::{init, resolve, server};
|
||||
use tauri::{api, SystemTray};
|
||||
use tauri::tray::TrayIconBuilder;
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
// 单例检测
|
||||
|
@ -34,14 +34,37 @@ fn main() -> std::io::Result<()> {
|
|||
|
||||
#[allow(unused_mut)]
|
||||
let mut builder = tauri::Builder::default()
|
||||
.system_tray(SystemTray::new())
|
||||
.plugin(tauri_plugin_updater::Builder::new().build())
|
||||
.plugin(tauri_plugin_clipboard_manager::init())
|
||||
.plugin(tauri_plugin_process::init())
|
||||
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
|
||||
.plugin(tauri_plugin_notification::init())
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.setup(|app| {
|
||||
TrayIconBuilder::new().build(app)?;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use tauri::menu::MenuBuilder;
|
||||
let _ = MenuBuilder::new(app)
|
||||
.copy()
|
||||
.paste()
|
||||
.undo()
|
||||
.redo()
|
||||
.cut()
|
||||
.select_all()
|
||||
.quit()
|
||||
.close_window()
|
||||
.build();
|
||||
}
|
||||
tauri::async_runtime::block_on(async move {
|
||||
resolve::resolve_setup(app).await;
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.on_system_tray_event(core::tray::Tray::on_system_tray_event)
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
// common
|
||||
cmds::get_sys_proxy,
|
||||
|
@ -97,26 +120,6 @@ fn main() -> std::io::Result<()> {
|
|||
cmds::clash_api_get_proxy_delay
|
||||
]);
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use tauri::{Menu, MenuItem, Submenu};
|
||||
|
||||
builder = builder.menu(
|
||||
Menu::new().add_submenu(Submenu::new(
|
||||
"Edit",
|
||||
Menu::new()
|
||||
.add_native_item(MenuItem::Undo)
|
||||
.add_native_item(MenuItem::Redo)
|
||||
.add_native_item(MenuItem::Copy)
|
||||
.add_native_item(MenuItem::Paste)
|
||||
.add_native_item(MenuItem::Cut)
|
||||
.add_native_item(MenuItem::SelectAll)
|
||||
.add_native_item(MenuItem::CloseWindow)
|
||||
.add_native_item(MenuItem::Quit),
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
let app = builder
|
||||
.build(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
@ -125,10 +128,6 @@ fn main() -> std::io::Result<()> {
|
|||
tauri::RunEvent::ExitRequested { api, .. } => {
|
||||
api.prevent_exit();
|
||||
}
|
||||
tauri::RunEvent::Updater(tauri::UpdaterEvent::Downloaded) => {
|
||||
resolve::resolve_reset();
|
||||
api::process::kill_children();
|
||||
}
|
||||
tauri::RunEvent::WindowEvent { label, event, .. } => {
|
||||
if label == "main" {
|
||||
match event {
|
||||
|
|
|
@ -2,10 +2,7 @@ use crate::core::handle;
|
|||
use anyhow::Result;
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::path::PathBuf;
|
||||
use tauri::{
|
||||
api::path::{data_dir, resource_dir},
|
||||
Env,
|
||||
};
|
||||
use tauri::Manager;
|
||||
|
||||
#[cfg(not(feature = "verge-dev"))]
|
||||
pub static APP_ID: &str = "io.github.clash-verge-rev.clash-verge-rev";
|
||||
|
@ -48,9 +45,21 @@ pub fn app_home_dir() -> Result<PathBuf> {
|
|||
return Ok(PathBuf::from(app_dir).join(".config").join(APP_ID));
|
||||
}
|
||||
|
||||
Ok(data_dir()
|
||||
.ok_or(anyhow::anyhow!("failed to get app home dir"))?
|
||||
.join(APP_ID))
|
||||
let handle = handle::Handle::global();
|
||||
let app_handle = handle.app_handle.lock();
|
||||
|
||||
if let Some(app_handle) = app_handle.as_ref() {
|
||||
match app_handle.path().data_dir() {
|
||||
Ok(dir) => {
|
||||
return Ok(dir.join(APP_ID));
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to get the app home directory: {}", e);
|
||||
return Err(anyhow::anyhow!("Failed to get the app homedirectory"));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(anyhow::anyhow!("failed to get the app home dir"))
|
||||
}
|
||||
|
||||
/// get the resources dir
|
||||
|
@ -58,10 +67,15 @@ pub fn app_resources_dir() -> Result<PathBuf> {
|
|||
let handle = handle::Handle::global();
|
||||
let app_handle = handle.app_handle.lock();
|
||||
if let Some(app_handle) = app_handle.as_ref() {
|
||||
let res_dir = resource_dir(app_handle.package_info(), &Env::default())
|
||||
.ok_or(anyhow::anyhow!("failed to get the resource dir"))?
|
||||
.join("resources");
|
||||
return Ok(res_dir);
|
||||
match app_handle.path().resource_dir() {
|
||||
Ok(dir) => {
|
||||
return Ok(dir.join("resources"));
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to get the resource directory: {}", e);
|
||||
return Err(anyhow::anyhow!("Failed to get the resource directory"));
|
||||
}
|
||||
};
|
||||
};
|
||||
Err(anyhow::anyhow!("failed to get the resource dir"))
|
||||
}
|
||||
|
@ -88,6 +102,10 @@ pub fn profiles_path() -> Result<PathBuf> {
|
|||
Ok(app_home_dir()?.join(PROFILE_YAML))
|
||||
}
|
||||
|
||||
pub fn clash_pid_path() -> Result<PathBuf> {
|
||||
Ok(app_home_dir()?.join("clash.pid"))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn service_path() -> Result<PathBuf> {
|
||||
Ok(app_resources_dir()?.join("clash-verge-service"))
|
||||
|
|
|
@ -4,10 +4,8 @@ use nanoid::nanoid;
|
|||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde_yaml::{Mapping, Value};
|
||||
use std::{fs, path::PathBuf, str::FromStr};
|
||||
use tauri::{
|
||||
api::shell::{open, Program},
|
||||
Manager,
|
||||
};
|
||||
use tauri_plugin_shell::ShellExt;
|
||||
|
||||
|
||||
/// read data from yaml as struct T
|
||||
pub fn read_yaml<T: DeserializeOwned>(path: &PathBuf) -> Result<T> {
|
||||
|
@ -104,20 +102,7 @@ pub fn get_last_part_and_decode(url: &str) -> Option<String> {
|
|||
/// open file
|
||||
/// use vscode by default
|
||||
pub fn open_file(app: tauri::AppHandle, path: PathBuf) -> Result<()> {
|
||||
#[cfg(target_os = "macos")]
|
||||
let code = "Visual Studio Code";
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let code = "code";
|
||||
|
||||
let _ = match Program::from_str(code) {
|
||||
Ok(code) => open(&app.shell_scope(), path.to_string_lossy(), Some(code)),
|
||||
Err(err) => {
|
||||
log::error!(target: "app", "Can't find VScode `{err}`");
|
||||
// default open
|
||||
open(&app.shell_scope(), path.to_string_lossy(), None)
|
||||
}
|
||||
};
|
||||
|
||||
app.shell().open(path.to_string_lossy(), None).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@ use log4rs::encode::pattern::PatternEncoder;
|
|||
use std::fs::{self, DirEntry};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use tauri::api::process::Command;
|
||||
use tauri::AppHandle;
|
||||
use tauri_plugin_shell::ShellExt;
|
||||
|
||||
/// initialize this instance's log file
|
||||
fn init_log() -> Result<()> {
|
||||
|
@ -296,43 +297,39 @@ pub fn init_scheme() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn startup_script() -> Result<()> {
|
||||
let path = {
|
||||
pub async fn startup_script(app_handle: &AppHandle) -> Result<()> {
|
||||
let script_path = {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.latest();
|
||||
verge.startup_script.clone().unwrap_or("".to_string())
|
||||
};
|
||||
|
||||
if !path.is_empty() {
|
||||
let mut shell = "";
|
||||
if path.ends_with(".sh") {
|
||||
shell = "bash";
|
||||
}
|
||||
if path.ends_with(".ps1") {
|
||||
shell = "powershell";
|
||||
}
|
||||
if path.ends_with(".bat") {
|
||||
shell = "powershell";
|
||||
}
|
||||
if shell.is_empty() {
|
||||
return Err(anyhow::anyhow!("unsupported script: {path}"));
|
||||
}
|
||||
let current_dir = PathBuf::from(path.clone());
|
||||
if !current_dir.exists() {
|
||||
return Err(anyhow::anyhow!("script not found: {path}"));
|
||||
}
|
||||
let current_dir = current_dir.parent();
|
||||
match current_dir {
|
||||
Some(dir) => {
|
||||
let _ = Command::new(shell)
|
||||
.current_dir(dir.to_path_buf())
|
||||
.args([path])
|
||||
.output()?;
|
||||
}
|
||||
None => {
|
||||
let _ = Command::new(shell).args([path]).output()?;
|
||||
}
|
||||
if script_path.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let shell_type = if script_path.ends_with(".sh") {
|
||||
"bash"
|
||||
} else if script_path.ends_with(".ps1") || script_path.ends_with(".bat") {
|
||||
"powershell"
|
||||
} else {
|
||||
return Err(anyhow::anyhow!("unsupported script extension: {}", script_path));
|
||||
};
|
||||
|
||||
let script_dir = PathBuf::from(&script_path);
|
||||
if !script_dir.exists() {
|
||||
return Err(anyhow::anyhow!("script not found: {}", script_path));
|
||||
}
|
||||
|
||||
let parent_dir = script_dir.parent();
|
||||
let working_dir = parent_dir.unwrap_or(script_dir.as_ref());
|
||||
|
||||
app_handle
|
||||
.shell()
|
||||
.command(shell_type)
|
||||
.current_dir(working_dir.to_path_buf())
|
||||
.args(&[script_path])
|
||||
.output().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -6,10 +6,12 @@ use anyhow::Result;
|
|||
use once_cell::sync::OnceCell;
|
||||
use serde_yaml::Mapping;
|
||||
use std::net::TcpListener;
|
||||
use tauri::api::notification;
|
||||
use tauri::{App, AppHandle, Manager};
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
use window_shadows::set_shadow;
|
||||
// use window_shadows::set_shadow;
|
||||
use tauri_plugin_notification::NotificationExt;
|
||||
|
||||
|
||||
|
||||
pub static VERSION: OnceCell<String> = OnceCell::new();
|
||||
|
||||
|
@ -33,14 +35,14 @@ pub fn find_unused_port() -> Result<u16> {
|
|||
/// handle something when start app
|
||||
pub async fn resolve_setup(app: &mut App) {
|
||||
#[cfg(target_os = "macos")]
|
||||
app.set_activation_policy(tauri::ActivationPolicy::Accessory);
|
||||
app.set_activation_policy(tauri::ActivationPolicy::Regular);
|
||||
let version = app.package_info().version.to_string();
|
||||
handle::Handle::global().init(app.app_handle());
|
||||
VERSION.get_or_init(|| version.clone());
|
||||
|
||||
log_err!(init::init_resources());
|
||||
log_err!(init::init_scheme());
|
||||
log_err!(init::startup_script());
|
||||
log_err!(init::startup_script(app.app_handle()).await);
|
||||
// 处理随机端口
|
||||
let enable_random_port = Config::verge().latest().enable_random_port.unwrap_or(false);
|
||||
|
||||
|
@ -74,7 +76,7 @@ pub async fn resolve_setup(app: &mut App) {
|
|||
log_err!(Config::init_config().await);
|
||||
|
||||
log::trace!("launch core");
|
||||
log_err!(CoreManager::global().init());
|
||||
log_err!(CoreManager::global().init(app.app_handle()));
|
||||
|
||||
// setup a simple http server for singleton
|
||||
log::trace!("launch embed server");
|
||||
|
@ -115,17 +117,17 @@ pub fn resolve_reset() {
|
|||
|
||||
/// create main window
|
||||
pub fn create_window(app_handle: &AppHandle) {
|
||||
if let Some(window) = app_handle.get_window("main") {
|
||||
if let Some(window) = app_handle.get_webview_window("main") {
|
||||
trace_err!(window.unminimize(), "set win unminimize");
|
||||
trace_err!(window.show(), "set win visible");
|
||||
trace_err!(window.set_focus(), "set win focus");
|
||||
return;
|
||||
}
|
||||
|
||||
let mut builder = tauri::window::WindowBuilder::new(
|
||||
let mut builder = tauri::WebviewWindowBuilder::new(
|
||||
app_handle,
|
||||
"main".to_string(),
|
||||
tauri::WindowUrl::App("index.html".into()),
|
||||
tauri::WebviewUrl::App("index.html".into()),
|
||||
)
|
||||
.title("Clash Verge")
|
||||
.visible(false)
|
||||
|
@ -199,8 +201,8 @@ pub fn create_window(app_handle: &AppHandle) {
|
|||
trace_err!(win.center(), "set win center");
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
trace_err!(set_shadow(&win, true), "set win shadow");
|
||||
// #[cfg(not(target_os = "linux"))]
|
||||
// trace_err!(set_shadow(&win, true), "set win shadow");
|
||||
if is_maximized {
|
||||
trace_err!(win.maximize(), "set win maximize");
|
||||
}
|
||||
|
@ -221,7 +223,7 @@ pub fn save_window_size_position(app_handle: &AppHandle, save_to_file: bool) ->
|
|||
}
|
||||
|
||||
let win = app_handle
|
||||
.get_window("main")
|
||||
.get_webview_window("main")
|
||||
.ok_or(anyhow::anyhow!("failed to get window"))?;
|
||||
|
||||
let scale = win.scale_factor()?;
|
||||
|
@ -241,16 +243,24 @@ pub async fn resolve_scheme(param: String) -> Result<()> {
|
|||
let url = param
|
||||
.trim_start_matches("clash://install-config/?url=")
|
||||
.trim_start_matches("clash://install-config?url=");
|
||||
|
||||
let handle = handle::Handle::global();
|
||||
let app_handle = handle.app_handle.lock();
|
||||
if let Some(app_handle) = app_handle.as_ref() {
|
||||
match import_profile(url.to_string(), None).await {
|
||||
Ok(_) => {
|
||||
notification::Notification::new(crate::utils::dirs::APP_ID)
|
||||
app_handle
|
||||
.notification()
|
||||
.builder()
|
||||
.title("Clash Verge")
|
||||
.body("Import profile success")
|
||||
.show()
|
||||
.unwrap();
|
||||
}
|
||||
Err(e) => {
|
||||
notification::Notification::new(crate::utils::dirs::APP_ID)
|
||||
app_handle
|
||||
.notification()
|
||||
.builder()
|
||||
.title("Clash Verge")
|
||||
.body(format!("Import profile failed: {e}"))
|
||||
.show()
|
||||
|
@ -258,5 +268,6 @@ pub async fn resolve_scheme(param: String) -> Result<()> {
|
|||
log::error!("Import profile failed: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
extern crate warp;
|
||||
|
||||
use super::resolve;
|
||||
use crate::{
|
||||
config::{Config, IVerge, DEFAULT_PAC},
|
||||
log_err,
|
||||
};
|
||||
use crate::config::{Config, IVerge, DEFAULT_PAC};
|
||||
use anyhow::{bail, Result};
|
||||
use port_scanner::local_port_available;
|
||||
use std::convert::Infallible;
|
||||
use tauri::AppHandle;
|
||||
use warp::http::StatusCode;
|
||||
use warp::Filter;
|
||||
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
struct QueryParam {
|
||||
param: String,
|
||||
}
|
||||
struct QueryParam {}
|
||||
|
||||
/// check whether there is already exists
|
||||
pub async fn check_singleton() -> Result<()> {
|
||||
|
@ -56,14 +52,15 @@ pub async fn check_singleton() -> Result<()> {
|
|||
|
||||
/// The embed server only be used to implement singleton process
|
||||
/// maybe it can be used as pac server later
|
||||
pub fn embed_server(app_handle: AppHandle) {
|
||||
pub fn embed_server(app_handle: &AppHandle) {
|
||||
let port = IVerge::get_singleton_port();
|
||||
|
||||
let handle = app_handle.clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let ping = warp::path!("commands" / "ping").map(move || "ok");
|
||||
|
||||
let visible = warp::path!("commands" / "visible").map(move || {
|
||||
resolve::create_window(&app_handle);
|
||||
resolve::create_window(&handle);
|
||||
"ok"
|
||||
});
|
||||
|
||||
|
@ -87,9 +84,9 @@ pub fn embed_server(app_handle: AppHandle) {
|
|||
.and(warp::query::<QueryParam>())
|
||||
.and_then(scheme_handler);
|
||||
|
||||
async fn scheme_handler(query: QueryParam) -> Result<impl warp::Reply, Infallible> {
|
||||
log_err!(resolve::resolve_scheme(query.param).await);
|
||||
Ok("ok")
|
||||
async fn scheme_handler(_: QueryParam) -> Result<impl warp::Reply, Infallible> {
|
||||
//let _ = resolve::resolve_scheme(query.param).await;
|
||||
Ok(warp::reply::with_status("Ok", StatusCode::OK))
|
||||
}
|
||||
let commands = ping.or(visible).or(pac).or(scheme);
|
||||
warp::serve(commands).run(([127, 0, 0, 1], port)).await;
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||
"package": {
|
||||
"productName": "Clash Verge",
|
||||
"version": "1.7.7"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
"devPath": "http://localhost:3000/",
|
||||
"beforeDevCommand": "pnpm run web:dev",
|
||||
"beforeBuildCommand": "pnpm run web:build"
|
||||
},
|
||||
"tauri": {
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"identifier": "io.github.clash-verge-rev.clash-verge-rev",
|
||||
"longDescription": "A Clash Meta GUI based on tauri.",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
|
@ -27,56 +16,34 @@
|
|||
"copyright": "GNU General Public License v3.0",
|
||||
"category": "DeveloperTool",
|
||||
"shortDescription": "A Clash Meta GUI based on tauri.",
|
||||
"longDescription": "A Clash Meta GUI based on tauri."
|
||||
"createUpdaterArtifacts": "v1Compatible"
|
||||
},
|
||||
"build": {
|
||||
"beforeBuildCommand": "pnpm run web:build",
|
||||
"frontendDist": "../dist",
|
||||
"beforeDevCommand": "pnpm run web:dev",
|
||||
"devUrl": "http://localhost:3000/"
|
||||
},
|
||||
"productName": "Clash Verge",
|
||||
"version": "1.7.7",
|
||||
"identifier": "io.github.clash-verge-rev.clash-verge-rev",
|
||||
"plugins": {
|
||||
"updater": {
|
||||
"active": true,
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEQyOEMyRjBCQkVGOUJEREYKUldUZnZmbStDeStNMHU5Mmo1N24xQXZwSVRYbXA2NUpzZE5oVzlqeS9Bc0t6RVV4MmtwVjBZaHgK",
|
||||
"endpoints": [
|
||||
"https://download.clashverge.dev/https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update-proxy.json",
|
||||
"https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update.json"
|
||||
],
|
||||
"dialog": false,
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEQyOEMyRjBCQkVGOUJEREYKUldUZnZmbStDeStNMHU5Mmo1N24xQXZwSVRYbXA2NUpzZE5oVzlqeS9Bc0t6RVV4MmtwVjBZaHgK"
|
||||
},
|
||||
"allowlist": {
|
||||
"shell": {
|
||||
"all": true
|
||||
},
|
||||
"window": {
|
||||
"all": true
|
||||
},
|
||||
"process": {
|
||||
"all": true
|
||||
},
|
||||
"globalShortcut": {
|
||||
"all": true
|
||||
},
|
||||
"clipboard": {
|
||||
"all": true
|
||||
},
|
||||
"notification": {
|
||||
"all": true
|
||||
},
|
||||
"dialog": {
|
||||
"all": false,
|
||||
"open": true
|
||||
},
|
||||
"protocol": {
|
||||
"asset": true,
|
||||
"assetScope": ["$APPDATA/**", "$RESOURCE/../**", "**"]
|
||||
},
|
||||
"path": {
|
||||
"all": true
|
||||
},
|
||||
"fs": {
|
||||
"exists": true,
|
||||
"readFile": true,
|
||||
"scope": ["$APPDATA/**", "$RESOURCE/../**", "**"]
|
||||
]
|
||||
}
|
||||
},
|
||||
"windows": [],
|
||||
"app": {
|
||||
"security": {
|
||||
"csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: asset: 'unsafe-eval' 'unsafe-inline' 'self';"
|
||||
}
|
||||
"assetProtocol": {
|
||||
"scope": ["$APPDATA/**", "$RESOURCE/../**", "**"],
|
||||
"enable": true
|
||||
},
|
||||
"csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: asset: 'unsafe-eval' 'unsafe-inline' 'self';; connect-src ipc: http://ipc.localhost"
|
||||
},
|
||||
"windows": []
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||
"tauri": {
|
||||
"systemTray": {
|
||||
"iconPath": "icons/tray-icon.ico"
|
||||
},
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"bundle": {
|
||||
"identifier": "io.github.clash-verge-rev.clash-verge-rev",
|
||||
"targets": ["deb", "rpm"],
|
||||
"linux": {
|
||||
"deb": {
|
||||
"depends": ["openssl"],
|
||||
"desktopTemplate": "./template/clash-verge.desktop",
|
||||
|
@ -22,5 +18,10 @@
|
|||
"obsoletes": ["clash-verge"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"app": {
|
||||
"trayIcon": {
|
||||
"iconPath": "icons/tray-icon.ico"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,13 @@
|
|||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||
"tauri": {
|
||||
"systemTray": {
|
||||
"iconPath": "icons/tray-icon-mono.ico",
|
||||
"iconAsTemplate": true
|
||||
},
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"bundle": {
|
||||
"identifier": "io.github.clash-verge-rev.clash-verge-rev",
|
||||
"targets": ["app", "dmg", "updater"],
|
||||
"targets": ["app", "dmg"],
|
||||
"macOS": {
|
||||
"frameworks": [],
|
||||
"minimumSystemVersion": "10.15",
|
||||
"exceptionDomain": "",
|
||||
"signingIdentity": null,
|
||||
"entitlements": null
|
||||
},
|
||||
"entitlements": null,
|
||||
"dmg": {
|
||||
"background": "images/background.png",
|
||||
"appPosition": {
|
||||
|
@ -35,5 +28,11 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"app": {
|
||||
"trayIcon": {
|
||||
"iconPath": "icons/tray-icon-mono.ico",
|
||||
"iconAsTemplate": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||
"tauri": {
|
||||
"systemTray": {
|
||||
"iconPath": "icons/tray-icon.ico"
|
||||
},
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"bundle": {
|
||||
"identifier": "io.github.clash-verge-rev.clash-verge-rev",
|
||||
"targets": ["nsis", "updater"],
|
||||
"targets": ["nsis"],
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
|
@ -19,11 +14,15 @@
|
|||
"displayLanguageSelector": true,
|
||||
"installerIcon": "icons/icon.ico",
|
||||
"languages": ["SimpChinese", "English"],
|
||||
"license": "../LICENSE",
|
||||
"installMode": "perMachine",
|
||||
"template": "./template/installer.nsi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"app": {
|
||||
"trayIcon": {
|
||||
"iconPath": "icons/tray-icon.ico",
|
||||
"iconAsTemplate": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ import {
|
|||
ErrorRounded,
|
||||
} from "@mui/icons-material";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
const appWindow = getCurrentWebviewWindow();
|
||||
interface InnerProps {
|
||||
type: string;
|
||||
duration?: number;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Button, ButtonGroup } from "@mui/material";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
import {
|
||||
CloseRounded,
|
||||
CropSquareRounded,
|
||||
|
@ -9,6 +9,7 @@ import {
|
|||
PushPinRounded,
|
||||
} from "@mui/icons-material";
|
||||
import { useEffect, useState } from "react";
|
||||
const appWindow = getCurrentWebviewWindow();
|
||||
|
||||
export const LayoutControl = () => {
|
||||
const minWidth = 40;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import useSWR from "swr";
|
||||
import { useRef } from "react";
|
||||
import { Button } from "@mui/material";
|
||||
import { checkUpdate } from "@tauri-apps/api/updater";
|
||||
import { check } from "@tauri-apps/plugin-updater";
|
||||
import { UpdateViewer } from "../setting/mods/update-viewer";
|
||||
import { DialogRef } from "../base";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
|
@ -19,7 +19,7 @@ export const UpdateButton = (props: Props) => {
|
|||
|
||||
const { data: updateInfo } = useSWR(
|
||||
auto_check_update || auto_check_update === null ? "checkUpdate" : null,
|
||||
checkUpdate,
|
||||
check,
|
||||
{
|
||||
errorRetryCount: 2,
|
||||
revalidateIfStale: false,
|
||||
|
@ -27,7 +27,7 @@ export const UpdateButton = (props: Props) => {
|
|||
}
|
||||
);
|
||||
|
||||
if (!updateInfo?.shouldUpdate) return null;
|
||||
if (!updateInfo?.available) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { useEffect, useMemo } from "react";
|
||||
import { alpha, createTheme, Shadows, Theme } from "@mui/material";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
import { useSetThemeMode, useThemeMode } from "@/services/states";
|
||||
import { defaultTheme, defaultDarkTheme } from "@/pages/_theme";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
const appWindow = getCurrentWebviewWindow();
|
||||
|
||||
/**
|
||||
* custom theme
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
import { useThemeMode } from "@/services/states";
|
||||
import { Notice } from "@/components/base";
|
||||
import { nanoid } from "nanoid";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
import getSystem from "@/utils/get-system";
|
||||
import debounce from "@/utils/debounce";
|
||||
|
||||
|
@ -29,6 +29,7 @@ import { type JSONSchema7 } from "json-schema";
|
|||
import metaSchema from "meta-json-schema/schemas/meta-json-schema.json";
|
||||
import mergeSchema from "meta-json-schema/schemas/clash-verge-merge-json-schema.json";
|
||||
import pac from "types-pac/pac.d.ts?raw";
|
||||
const appWindow = getCurrentWebviewWindow();
|
||||
|
||||
type Language = "yaml" | "javascript" | "css";
|
||||
type Schema<T extends Language> = LanguageSchemaMap[T];
|
||||
|
|
|
@ -10,7 +10,7 @@ import { DeleteForeverRounded, UndoRounded } from "@mui/icons-material";
|
|||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { downloadIconCache } from "@/services/cmds";
|
||||
import { convertFileSrc } from "@tauri-apps/api/tauri";
|
||||
import { convertFileSrc } from "@tauri-apps/api/core";
|
||||
import { useEffect, useState } from "react";
|
||||
interface Props {
|
||||
type: "prepend" | "original" | "delete" | "append";
|
||||
|
|
|
@ -30,7 +30,7 @@ import { EditorViewer } from "@/components/profile/editor-viewer";
|
|||
import { ProfileBox } from "./profile-box";
|
||||
import parseTraffic from "@/utils/parse-traffic";
|
||||
import { ConfirmViewer } from "@/components/profile/confirm-viewer";
|
||||
import { open } from "@tauri-apps/api/shell";
|
||||
import { open } from "@tauri-apps/plugin-shell";
|
||||
import { ProxiesEditorViewer } from "./proxies-editor-viewer";
|
||||
const round = keyframes`
|
||||
from { transform: rotate(0deg); }
|
||||
|
|
|
@ -19,7 +19,7 @@ import type { IRenderItem } from "./use-render-list";
|
|||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { useThemeMode } from "@/services/states";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { convertFileSrc } from "@tauri-apps/api/tauri";
|
||||
import { convertFileSrc } from "@tauri-apps/api/core";
|
||||
import { downloadIconCache } from "@/services/cmds";
|
||||
|
||||
interface RenderProps {
|
||||
|
|
|
@ -12,11 +12,11 @@ import {
|
|||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||
import { GuardState } from "./guard-state";
|
||||
import { open as openDialog } from "@tauri-apps/api/dialog";
|
||||
import { convertFileSrc } from "@tauri-apps/api/tauri";
|
||||
import { open as openDialog } from "@tauri-apps/plugin-dialog";
|
||||
import { convertFileSrc } from "@tauri-apps/api/core";
|
||||
import { copyIconFile, getAppDir } from "@/services/cmds";
|
||||
import { join } from "@tauri-apps/api/path";
|
||||
import { exists } from "@tauri-apps/api/fs";
|
||||
import { exists } from "@tauri-apps/plugin-fs";
|
||||
import getSystem from "@/utils/get-system";
|
||||
|
||||
const OS = getSystem();
|
||||
|
@ -186,7 +186,7 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
onChangeData({ common_tray_icon: false });
|
||||
patchVerge({ common_tray_icon: false });
|
||||
} else {
|
||||
const path = await openDialog({
|
||||
const selected = await openDialog({
|
||||
directory: false,
|
||||
multiple: false,
|
||||
filters: [
|
||||
|
@ -196,8 +196,8 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
},
|
||||
],
|
||||
});
|
||||
if (path?.length) {
|
||||
await copyIconFile(`${path}`, "common");
|
||||
if (selected?.path.length) {
|
||||
await copyIconFile(`${selected.path}`, "common");
|
||||
await initIconPath();
|
||||
onChangeData({ common_tray_icon: true });
|
||||
patchVerge({ common_tray_icon: true });
|
||||
|
@ -232,7 +232,7 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
onChangeData({ sysproxy_tray_icon: false });
|
||||
patchVerge({ sysproxy_tray_icon: false });
|
||||
} else {
|
||||
const path = await openDialog({
|
||||
const selected = await openDialog({
|
||||
directory: false,
|
||||
multiple: false,
|
||||
filters: [
|
||||
|
@ -242,8 +242,8 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
},
|
||||
],
|
||||
});
|
||||
if (path?.length) {
|
||||
await copyIconFile(`${path}`, "sysproxy");
|
||||
if (selected?.path.length) {
|
||||
await copyIconFile(`${selected.path}`, "sysproxy");
|
||||
await initIconPath();
|
||||
onChangeData({ sysproxy_tray_icon: true });
|
||||
patchVerge({ sysproxy_tray_icon: true });
|
||||
|
@ -276,7 +276,7 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
onChangeData({ tun_tray_icon: false });
|
||||
patchVerge({ tun_tray_icon: false });
|
||||
} else {
|
||||
const path = await openDialog({
|
||||
const selected = await openDialog({
|
||||
directory: false,
|
||||
multiple: false,
|
||||
filters: [
|
||||
|
@ -286,8 +286,8 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
},
|
||||
],
|
||||
});
|
||||
if (path?.length) {
|
||||
await copyIconFile(`${path}`, "tun");
|
||||
if (selected?.path.length) {
|
||||
await copyIconFile(`${selected.path}`, "tun");
|
||||
await initIconPath();
|
||||
onChangeData({ tun_tray_icon: true });
|
||||
patchVerge({ tun_tray_icon: true });
|
||||
|
|
|
@ -4,7 +4,7 @@ import { BaseDialog, DialogRef, Notice } from "@/components/base";
|
|||
import { getNetworkInterfacesInfo } from "@/services/cmds";
|
||||
import { alpha, Box, Button, Chip, IconButton } from "@mui/material";
|
||||
import { ContentCopyRounded } from "@mui/icons-material";
|
||||
import { writeText } from "@tauri-apps/api/clipboard";
|
||||
import { writeText } from "@tauri-apps/plugin-clipboard-manager";
|
||||
|
||||
export const NetworkInterfaceViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
const { t } = useTranslation();
|
||||
|
|
|
@ -3,13 +3,13 @@ import { forwardRef, useImperativeHandle, useState, useMemo } from "react";
|
|||
import { useLockFn } from "ahooks";
|
||||
import { Box, LinearProgress, Button } from "@mui/material";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { relaunch } from "@tauri-apps/api/process";
|
||||
import { checkUpdate, installUpdate } from "@tauri-apps/api/updater";
|
||||
import { relaunch } from "@tauri-apps/plugin-process";
|
||||
import { check as checkUpdate } from "@tauri-apps/plugin-updater";
|
||||
import { BaseDialog, DialogRef, Notice } from "@/components/base";
|
||||
import { useUpdateState, useSetUpdateState } from "@/services/states";
|
||||
import { listen, Event, UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { portableFlag } from "@/pages/_layout";
|
||||
import { open as openUrl } from "@tauri-apps/api/shell";
|
||||
import { open as openUrl } from "@tauri-apps/plugin-shell";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
|
||||
let eventListener: UnlistenFn | null = null;
|
||||
|
@ -38,17 +38,17 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
}));
|
||||
|
||||
const markdownContent = useMemo(() => {
|
||||
if (!updateInfo?.manifest?.body) {
|
||||
if (!updateInfo?.body) {
|
||||
return "New Version is available";
|
||||
}
|
||||
return updateInfo?.manifest?.body;
|
||||
return updateInfo?.body;
|
||||
}, [updateInfo]);
|
||||
|
||||
const breakChangeFlag = useMemo(() => {
|
||||
if (!updateInfo?.manifest?.body) {
|
||||
if (!updateInfo?.body) {
|
||||
return false;
|
||||
}
|
||||
return updateInfo?.manifest?.body.toLowerCase().includes("break change");
|
||||
return updateInfo?.body.toLowerCase().includes("break change");
|
||||
}, [updateInfo]);
|
||||
|
||||
const onUpdate = useLockFn(async () => {
|
||||
|
@ -56,7 +56,7 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
Notice.error(t("Portable Updater Error"));
|
||||
return;
|
||||
}
|
||||
if (!updateInfo?.manifest?.body) return;
|
||||
if (!updateInfo?.body) return;
|
||||
if (breakChangeFlag) {
|
||||
Notice.error(t("Break Change Update Error"));
|
||||
return;
|
||||
|
@ -77,7 +77,7 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
}
|
||||
);
|
||||
try {
|
||||
await installUpdate();
|
||||
await updateInfo.install();
|
||||
await relaunch();
|
||||
} catch (err: any) {
|
||||
Notice.error(err?.message || err.toString());
|
||||
|
@ -91,14 +91,14 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
open={open}
|
||||
title={
|
||||
<Box display="flex" justifyContent="space-between">
|
||||
{`New Version v${updateInfo?.manifest?.version}`}
|
||||
{`New Version v${updateInfo?.version}`}
|
||||
<Box>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
openUrl(
|
||||
`https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/v${updateInfo?.manifest?.version}`
|
||||
`https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/v${updateInfo?.version}`
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
import { useCallback, useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { open } from "@tauri-apps/api/dialog";
|
||||
import {
|
||||
Button,
|
||||
MenuItem,
|
||||
Select,
|
||||
Input,
|
||||
Typography,
|
||||
Box,
|
||||
} from "@mui/material";
|
||||
import { open } from "@tauri-apps/plugin-dialog";
|
||||
import { Button, MenuItem, Select, Input, Typography } from "@mui/material";
|
||||
import {
|
||||
exitApp,
|
||||
openAppDir,
|
||||
|
@ -17,7 +10,7 @@ import {
|
|||
openDevTools,
|
||||
copyClashEnv,
|
||||
} from "@/services/cmds";
|
||||
import { checkUpdate } from "@tauri-apps/api/updater";
|
||||
import { check as checkUpdate } from "@tauri-apps/plugin-updater";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { version } from "@root/package.json";
|
||||
import { DialogRef, Notice } from "@/components/base";
|
||||
|
@ -67,7 +60,7 @@ const SettingVerge = ({ onError }: Props) => {
|
|||
const onCheckUpdate = async () => {
|
||||
try {
|
||||
const info = await checkUpdate();
|
||||
if (!info?.shouldUpdate) {
|
||||
if (!info?.available) {
|
||||
Notice.success(t("Currently on the Latest Version"));
|
||||
} else {
|
||||
updateRef.current?.open();
|
||||
|
@ -191,7 +184,7 @@ const SettingVerge = ({ onError }: Props) => {
|
|||
<>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const path = await open({
|
||||
const selected = await open({
|
||||
directory: false,
|
||||
multiple: false,
|
||||
filters: [
|
||||
|
@ -201,9 +194,9 @@ const SettingVerge = ({ onError }: Props) => {
|
|||
},
|
||||
],
|
||||
});
|
||||
if (path?.length) {
|
||||
onChangeData({ startup_script: `${path}` });
|
||||
patchVerge({ startup_script: `${path}` });
|
||||
if (selected?.path.length) {
|
||||
onChangeData({ startup_script: `${selected.path}` });
|
||||
patchVerge({ startup_script: `${selected.path}` });
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -19,7 +19,7 @@ import { TestBox } from "./test-box";
|
|||
import delayManager from "@/services/delay";
|
||||
import { cmdTestDelay, downloadIconCache } from "@/services/cmds";
|
||||
import { listen, UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { convertFileSrc } from "@tauri-apps/api/tauri";
|
||||
import { convertFileSrc } from "@tauri-apps/api/core";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
|
|
|
@ -7,7 +7,7 @@ import { useTranslation } from "react-i18next";
|
|||
import { useLocation, useRoutes } from "react-router-dom";
|
||||
import { List, Paper, ThemeProvider, SvgIcon } from "@mui/material";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
import { routers } from "./_routers";
|
||||
import { getAxios } from "@/services/api";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
|
@ -28,6 +28,7 @@ import { getPortableFlag } from "@/services/cmds";
|
|||
import { useNavigate } from "react-router-dom";
|
||||
import React from "react";
|
||||
import { TransitionGroup, CSSTransition } from "react-transition-group";
|
||||
const appWindow = getCurrentWebviewWindow();
|
||||
export let portableFlag = false;
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
|
|
@ -48,8 +48,8 @@ import { ConfigViewer } from "@/components/setting/mods/config-viewer";
|
|||
import { throttle } from "lodash-es";
|
||||
import { BaseStyledTextField } from "@/components/base/base-styled-text-field";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { readTextFile } from "@tauri-apps/api/fs";
|
||||
import { readText } from "@tauri-apps/api/clipboard";
|
||||
import { readTextFile } from "@tauri-apps/plugin-fs";
|
||||
import { readText } from "@tauri-apps/plugin-clipboard-manager";
|
||||
|
||||
const ProfilePage = () => {
|
||||
const { t } = useTranslation();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import dayjs from "dayjs";
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { Notice } from "@/components/base";
|
||||
|
||||
export async function copyClashEnv() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user