feat: clash meta core supports
This commit is contained in:
parent
f5c6fa842a
commit
be9ea4ea8e
@ -5,7 +5,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "tauri dev",
|
"dev": "tauri dev",
|
||||||
"dev:diff": "tauri dev -f verge-dev -c src-tauri/tauri.diff.json",
|
"dev:diff": "tauri dev -f verge-dev -c src-tauri/tauri.diff.json",
|
||||||
"dev:meta": "tauri dev -f meta-dev -c src-tauri/tauri.meta.json",
|
"dev:core": "cross-env VITE_MULTI_CORE=1 yarn dev:diff",
|
||||||
"build": "tauri build",
|
"build": "tauri build",
|
||||||
"tauri": "tauri",
|
"tauri": "tauri",
|
||||||
"web:dev": "vite",
|
"web:dev": "vite",
|
||||||
@ -47,6 +47,7 @@
|
|||||||
"@types/react-dom": "^17.0.0",
|
"@types/react-dom": "^17.0.0",
|
||||||
"@vitejs/plugin-react": "^1.3.2",
|
"@vitejs/plugin-react": "^1.3.2",
|
||||||
"adm-zip": "^0.5.9",
|
"adm-zip": "^0.5.9",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.0",
|
||||||
"https-proxy-agent": "^5.0.1",
|
"https-proxy-agent": "^5.0.1",
|
||||||
"husky": "^7.0.0",
|
"husky": "^7.0.0",
|
||||||
|
@ -45,9 +45,7 @@ windows-sys = { version = "0.36", features = ["Win32_System_LibraryLoader", "Win
|
|||||||
[features]
|
[features]
|
||||||
default = ["custom-protocol", "tauri/ayatana-tray"]
|
default = ["custom-protocol", "tauri/ayatana-tray"]
|
||||||
custom-protocol = ["tauri/custom-protocol"]
|
custom-protocol = ["tauri/custom-protocol"]
|
||||||
meta-dev = ["clash-meta", "verge-dev"]
|
|
||||||
verge-dev = []
|
verge-dev = []
|
||||||
clash-meta = []
|
|
||||||
debug-yml = []
|
debug-yml = []
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
@ -196,10 +196,16 @@ pub fn patch_verge_config(
|
|||||||
payload: Verge,
|
payload: Verge,
|
||||||
app_handle: tauri::AppHandle,
|
app_handle: tauri::AppHandle,
|
||||||
core: State<'_, Core>,
|
core: State<'_, Core>,
|
||||||
) -> Result<(), String> {
|
) -> CmdResult {
|
||||||
wrap_err!(core.patch_verge(payload, &app_handle))
|
wrap_err!(core.patch_verge(payload, &app_handle))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// change clash core
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn change_clash_core(core: State<'_, Core>, clash_core: Option<String>) -> CmdResult {
|
||||||
|
wrap_err!(core.change_core(clash_core))
|
||||||
|
}
|
||||||
|
|
||||||
/// restart the sidecar
|
/// restart the sidecar
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn restart_sidecar(core: State<'_, Core>) -> CmdResult {
|
pub fn restart_sidecar(core: State<'_, Core>) -> CmdResult {
|
||||||
|
@ -65,22 +65,21 @@ impl Core {
|
|||||||
|
|
||||||
/// initialize the core state
|
/// initialize the core state
|
||||||
pub fn init(&self, app_handle: tauri::AppHandle) {
|
pub fn init(&self, app_handle: tauri::AppHandle) {
|
||||||
|
let verge = self.verge.lock();
|
||||||
|
let clash_core = verge.clash_core.clone();
|
||||||
|
|
||||||
|
let mut service = self.service.lock();
|
||||||
|
service.set_core(clash_core);
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
let verge = self.verge.lock();
|
|
||||||
let enable = verge.enable_service_mode.clone();
|
let enable = verge.enable_service_mode.clone();
|
||||||
|
|
||||||
let mut service = self.service.lock();
|
|
||||||
service.set_mode(enable.unwrap_or(false));
|
service.set_mode(enable.unwrap_or(false));
|
||||||
|
|
||||||
log_if_err!(service.start());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
{
|
|
||||||
let mut service = self.service.lock();
|
|
||||||
log_if_err!(service.start());
|
log_if_err!(service.start());
|
||||||
}
|
drop(verge);
|
||||||
|
drop(service);
|
||||||
|
|
||||||
log_if_err!(self.activate());
|
log_if_err!(self.activate());
|
||||||
|
|
||||||
@ -138,6 +137,31 @@ impl Core {
|
|||||||
self.activate_enhanced(true)
|
self.activate_enhanced(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// change the clash core
|
||||||
|
pub fn change_core(&self, clash_core: Option<String>) -> Result<()> {
|
||||||
|
let clash_core = clash_core.unwrap_or("clash".into());
|
||||||
|
|
||||||
|
if &clash_core != "clash" && &clash_core != "clash-meta" {
|
||||||
|
bail!("invalid clash core name \"{clash_core}\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut verge = self.verge.lock();
|
||||||
|
verge.patch_config(Verge {
|
||||||
|
clash_core: Some(clash_core.clone()),
|
||||||
|
..Verge::default()
|
||||||
|
})?;
|
||||||
|
drop(verge);
|
||||||
|
|
||||||
|
let mut service = self.service.lock();
|
||||||
|
service.stop()?;
|
||||||
|
service.set_core(Some(clash_core));
|
||||||
|
service.start()?;
|
||||||
|
drop(service);
|
||||||
|
|
||||||
|
self.activate()?;
|
||||||
|
self.activate_enhanced(true)
|
||||||
|
}
|
||||||
|
|
||||||
/// Patch Clash
|
/// Patch Clash
|
||||||
/// handle the clash config changed
|
/// handle the clash config changed
|
||||||
pub fn patch_clash(&self, patch: Mapping) -> Result<()> {
|
pub fn patch_clash(&self, patch: Mapping) -> Result<()> {
|
||||||
|
26
src-tauri/src/core/multi.rs
Normal file
26
src-tauri/src/core/multi.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use anyhow::{Context, Result};
|
||||||
|
use std::env::current_exe;
|
||||||
|
|
||||||
|
pub struct CoreItem {
|
||||||
|
pub name: String,
|
||||||
|
pub path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Multi {}
|
||||||
|
|
||||||
|
impl Multi {
|
||||||
|
pub fn list() -> Result<Vec<CoreItem>> {
|
||||||
|
let paths = current_exe()
|
||||||
|
.unwrap()
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.read_dir()
|
||||||
|
.context("failed to current dir")?;
|
||||||
|
|
||||||
|
for path in paths {
|
||||||
|
dbg!(path.unwrap().path().metadata().unwrap().permissions().);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
}
|
@ -100,15 +100,16 @@ fn main() -> std::io::Result<()> {
|
|||||||
})
|
})
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
// common
|
// common
|
||||||
cmds::restart_sidecar,
|
|
||||||
cmds::get_sys_proxy,
|
cmds::get_sys_proxy,
|
||||||
cmds::get_cur_proxy,
|
cmds::get_cur_proxy,
|
||||||
cmds::kill_sidecar,
|
|
||||||
cmds::open_app_dir,
|
cmds::open_app_dir,
|
||||||
cmds::open_logs_dir,
|
cmds::open_logs_dir,
|
||||||
|
cmds::kill_sidecar,
|
||||||
|
cmds::restart_sidecar,
|
||||||
// clash
|
// clash
|
||||||
cmds::get_clash_info,
|
cmds::get_clash_info,
|
||||||
cmds::patch_clash_config,
|
cmds::patch_clash_config,
|
||||||
|
cmds::change_clash_core,
|
||||||
// verge
|
// verge
|
||||||
cmds::get_verge_config,
|
cmds::get_verge_config,
|
||||||
cmds::patch_verge_config,
|
cmds::patch_verge_config,
|
||||||
|
@ -6,4 +6,3 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"tauri": {
|
|
||||||
"bundle": {
|
|
||||||
"externalBin": ["sidecar/clash", "sidecar/clash-meta"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
84
src/components/setting/core-switch.tsx
Normal file
84
src/components/setting/core-switch.tsx
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import useSWR, { useSWRConfig } from "swr";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useLockFn } from "ahooks";
|
||||||
|
import { Menu, MenuItem } from "@mui/material";
|
||||||
|
import { Settings } from "@mui/icons-material";
|
||||||
|
import { changeClashCore, getVergeConfig } from "../../services/cmds";
|
||||||
|
import getSystem from "../../utils/get-system";
|
||||||
|
import Notice from "../base/base-notice";
|
||||||
|
|
||||||
|
const OS = getSystem();
|
||||||
|
|
||||||
|
const VALID_CORE = [
|
||||||
|
{ name: "Clash", core: "clash" },
|
||||||
|
{ name: "Clash Meta", core: "clash-meta" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const CoreSwitch = () => {
|
||||||
|
const { mutate } = useSWRConfig();
|
||||||
|
|
||||||
|
const { data: vergeConfig } = useSWR("getVergeConfig", getVergeConfig);
|
||||||
|
|
||||||
|
const [anchorEl, setAnchorEl] = useState<any>(null);
|
||||||
|
const [position, setPosition] = useState({ left: 0, top: 0 });
|
||||||
|
|
||||||
|
const { clash_core = "clash" } = vergeConfig ?? {};
|
||||||
|
|
||||||
|
const onCoreChange = useLockFn(async (core: string) => {
|
||||||
|
if (core === clash_core) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await changeClashCore(core);
|
||||||
|
mutate("getVergeConfig");
|
||||||
|
mutate("getClashConfig");
|
||||||
|
mutate("getVersion");
|
||||||
|
setAnchorEl(null);
|
||||||
|
Notice.success(`Successfully switch to ${core}`, 1000);
|
||||||
|
} catch (err: any) {
|
||||||
|
Notice.error(err?.message || err.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Settings
|
||||||
|
fontSize="small"
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
onClick={(event) => {
|
||||||
|
const { clientX, clientY } = event;
|
||||||
|
setPosition({ top: clientY, left: clientX });
|
||||||
|
setAnchorEl(event.currentTarget);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Menu
|
||||||
|
open={!!anchorEl}
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
onClose={() => setAnchorEl(null)}
|
||||||
|
anchorPosition={position}
|
||||||
|
anchorReference="anchorPosition"
|
||||||
|
transitionDuration={225}
|
||||||
|
TransitionProps={
|
||||||
|
OS === "macos" ? { style: { transitionDuration: "225ms" } } : {}
|
||||||
|
}
|
||||||
|
onContextMenu={(e) => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
e.preventDefault();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{VALID_CORE.map((each) => (
|
||||||
|
<MenuItem
|
||||||
|
key={each.core}
|
||||||
|
sx={{ minWidth: 125 }}
|
||||||
|
selected={each.core === clash_core}
|
||||||
|
onClick={() => onCoreChange(each.core)}
|
||||||
|
>
|
||||||
|
{each.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CoreSwitch;
|
@ -8,6 +8,7 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
Typography,
|
Typography,
|
||||||
|
Box,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { ApiType } from "../../services/types";
|
import { ApiType } from "../../services/types";
|
||||||
import { atomClashPort } from "../../services/states";
|
import { atomClashPort } from "../../services/states";
|
||||||
@ -16,11 +17,14 @@ import { SettingList, SettingItem } from "./setting";
|
|||||||
import { getClashConfig, getVersion, updateConfigs } from "../../services/api";
|
import { getClashConfig, getVersion, updateConfigs } from "../../services/api";
|
||||||
import Notice from "../base/base-notice";
|
import Notice from "../base/base-notice";
|
||||||
import GuardState from "./guard-state";
|
import GuardState from "./guard-state";
|
||||||
|
import CoreSwitch from "./core-switch";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onError: (err: Error) => void;
|
onError: (err: Error) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MULTI_CORE = !!import.meta.env.VITE_MULTI_CORE;
|
||||||
|
|
||||||
const SettingClash = ({ onError }: Props) => {
|
const SettingClash = ({ onError }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { mutate } = useSWRConfig();
|
const { mutate } = useSWRConfig();
|
||||||
@ -54,7 +58,7 @@ const SettingClash = ({ onError }: Props) => {
|
|||||||
}
|
}
|
||||||
await patchClashConfig({ "mixed-port": port });
|
await patchClashConfig({ "mixed-port": port });
|
||||||
setGlobalClashPort(port);
|
setGlobalClashPort(port);
|
||||||
Notice.success("Change Clash port successfully!");
|
Notice.success("Change Clash port successfully!", 1000);
|
||||||
|
|
||||||
// update the config
|
// update the config
|
||||||
mutate("getClashConfig");
|
mutate("getClashConfig");
|
||||||
@ -129,7 +133,18 @@ const SettingClash = ({ onError }: Props) => {
|
|||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
|
||||||
<SettingItem>
|
<SettingItem>
|
||||||
<ListItemText primary={t("Clash Core")} />
|
<ListItemText
|
||||||
|
primary={
|
||||||
|
MULTI_CORE ? (
|
||||||
|
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||||
|
<span style={{ marginRight: 4 }}>{t("Clash Core")}</span>
|
||||||
|
<CoreSwitch />
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
t("Clash Core")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Typography sx={{ py: 1 }}>{clashVer}</Typography>
|
<Typography sx={{ py: 1 }}>{clashVer}</Typography>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
</SettingList>
|
</SettingList>
|
||||||
|
@ -86,6 +86,10 @@ export async function getSystemProxy() {
|
|||||||
return invoke<any>("get_sys_proxy");
|
return invoke<any>("get_sys_proxy");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function changeClashCore(clashCore: string) {
|
||||||
|
return invoke<any>("change_clash_core", { clashCore });
|
||||||
|
}
|
||||||
|
|
||||||
export async function restartSidecar() {
|
export async function restartSidecar() {
|
||||||
return invoke<void>("restart_sidecar");
|
return invoke<void>("restart_sidecar");
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,7 @@ export namespace CmdType {
|
|||||||
|
|
||||||
export interface VergeConfig {
|
export interface VergeConfig {
|
||||||
language?: string;
|
language?: string;
|
||||||
|
clash_core?: string;
|
||||||
theme_mode?: "light" | "dark";
|
theme_mode?: "light" | "dark";
|
||||||
theme_blur?: boolean;
|
theme_blur?: boolean;
|
||||||
traffic_graph?: boolean;
|
traffic_graph?: boolean;
|
||||||
|
@ -1201,7 +1201,14 @@ cosmiconfig@^7.0.1:
|
|||||||
path-type "^4.0.0"
|
path-type "^4.0.0"
|
||||||
yaml "^1.10.0"
|
yaml "^1.10.0"
|
||||||
|
|
||||||
cross-spawn@^7.0.0:
|
cross-env@^7.0.3:
|
||||||
|
version "7.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
|
||||||
|
integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
|
||||||
|
dependencies:
|
||||||
|
cross-spawn "^7.0.1"
|
||||||
|
|
||||||
|
cross-spawn@^7.0.0, cross-spawn@^7.0.1:
|
||||||
version "7.0.3"
|
version "7.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||||
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
||||||
|
Loading…
x
Reference in New Issue
Block a user