mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-28 16:30:52 +08:00
feat: profile enhanced mode
This commit is contained in:
@@ -8,7 +8,7 @@ use crate::{
|
||||
use anyhow::Result;
|
||||
use serde_yaml::Mapping;
|
||||
use std::{path::PathBuf, process::Command};
|
||||
use tauri::{api, State};
|
||||
use tauri::{api, Manager, State};
|
||||
|
||||
/// get all profiles from `profiles.yaml`
|
||||
#[tauri::command]
|
||||
@@ -100,6 +100,43 @@ pub fn select_profile(
|
||||
wrap_err!(clash.activate(&profiles))
|
||||
}
|
||||
|
||||
/// change the profile chain
|
||||
#[tauri::command]
|
||||
pub fn change_profile_chain(
|
||||
chain: Option<Vec<String>>,
|
||||
app_handle: tauri::AppHandle,
|
||||
clash_state: State<'_, ClashState>,
|
||||
profiles_state: State<'_, ProfilesState>,
|
||||
) -> Result<(), String> {
|
||||
let clash = clash_state.0.lock().unwrap();
|
||||
let mut profiles = profiles_state.0.lock().unwrap();
|
||||
|
||||
profiles.put_chain(chain);
|
||||
|
||||
app_handle
|
||||
.get_window("main")
|
||||
.map(|win| wrap_err!(clash.activate_enhanced(&profiles, win, false)));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// manually exec enhanced profile
|
||||
#[tauri::command]
|
||||
pub fn enhance_profiles(
|
||||
app_handle: tauri::AppHandle,
|
||||
clash_state: State<'_, ClashState>,
|
||||
profiles_state: State<'_, ProfilesState>,
|
||||
) -> Result<(), String> {
|
||||
let clash = clash_state.0.lock().unwrap();
|
||||
let profiles = profiles_state.0.lock().unwrap();
|
||||
|
||||
app_handle
|
||||
.get_window("main")
|
||||
.map(|win| wrap_err!(clash.activate_enhanced(&profiles, win, false)));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// delete profile item
|
||||
#[tauri::command]
|
||||
pub fn delete_profile(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{Profiles, Verge};
|
||||
use super::{PrfEnhancedResult, Profiles, Verge};
|
||||
use crate::utils::{config, dirs, help};
|
||||
use anyhow::{bail, Result};
|
||||
use reqwest::header::HeaderMap;
|
||||
@@ -260,6 +260,7 @@ impl Clash {
|
||||
let mut data = HashMap::new();
|
||||
data.insert("path", temp_path.as_os_str().to_str().unwrap());
|
||||
|
||||
// retry 5 times
|
||||
for _ in 0..5 {
|
||||
match reqwest::ClientBuilder::new().no_proxy().build() {
|
||||
Ok(client) => match client
|
||||
@@ -269,11 +270,18 @@ impl Clash {
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(_) => break,
|
||||
Ok(resp) => {
|
||||
if resp.status() != 204 {
|
||||
log::error!("failed to activate clash for status \"{}\"", resp.status());
|
||||
}
|
||||
// do not retry
|
||||
break;
|
||||
}
|
||||
Err(err) => log::error!("failed to activate for `{err}`"),
|
||||
},
|
||||
Err(err) => log::error!("failed to activate for `{err}`"),
|
||||
}
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -294,29 +302,43 @@ impl Clash {
|
||||
}
|
||||
|
||||
/// enhanced profiles mode
|
||||
pub fn activate_enhanced(&self, profiles: &Profiles, win: tauri::Window) -> Result<()> {
|
||||
pub fn activate_enhanced(
|
||||
&self,
|
||||
profiles: &Profiles,
|
||||
win: tauri::Window,
|
||||
delay: bool,
|
||||
) -> Result<()> {
|
||||
let event_name = help::get_uid("e");
|
||||
let event_name = format!("script-cb-{event_name}");
|
||||
let event_name = format!("enhanced-cb-{event_name}");
|
||||
|
||||
let info = self.info.clone();
|
||||
let mut config = self.config.clone();
|
||||
|
||||
// generate the payload
|
||||
let payload = profiles.gen_enhanced()?;
|
||||
let payload = profiles.gen_enhanced(event_name.clone())?;
|
||||
|
||||
win.once(&event_name, move |event| {
|
||||
if let Some(result) = event.payload() {
|
||||
let gen_map: Mapping = serde_json::from_str(result).unwrap();
|
||||
let result: PrfEnhancedResult = serde_json::from_str(result).unwrap();
|
||||
|
||||
for (key, value) in gen_map.into_iter() {
|
||||
config.insert(key, value);
|
||||
if let Some(data) = result.data {
|
||||
for (key, value) in data.into_iter() {
|
||||
config.insert(key, value);
|
||||
}
|
||||
Self::_activate(info, config).unwrap();
|
||||
}
|
||||
Self::_activate(info, config).unwrap();
|
||||
|
||||
log::info!("profile enhanced status {}", result.status);
|
||||
|
||||
result.error.map(|error| log::error!("{error}"));
|
||||
}
|
||||
});
|
||||
|
||||
tauri::async_runtime::spawn(async move {
|
||||
sleep(Duration::from_secs(5)).await;
|
||||
// wait the window setup during resolve app
|
||||
if delay {
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
win.emit("script-handler", payload).unwrap();
|
||||
});
|
||||
|
||||
|
||||
@@ -314,6 +314,11 @@ impl Profiles {
|
||||
bail!("invalid uid \"{uid}\"");
|
||||
}
|
||||
|
||||
/// just change the `chain`
|
||||
pub fn put_chain(&mut self, chain: Option<Vec<String>>) {
|
||||
self.chain = chain;
|
||||
}
|
||||
|
||||
/// find the item by the uid
|
||||
pub fn get_item(&self, uid: &String) -> Result<&PrfItem> {
|
||||
if self.items.is_some() {
|
||||
@@ -519,7 +524,7 @@ impl Profiles {
|
||||
}
|
||||
|
||||
/// gen the enhanced profiles
|
||||
pub fn gen_enhanced(&self) -> Result<PrfEnhanced> {
|
||||
pub fn gen_enhanced(&self, callback: String) -> Result<PrfEnhanced> {
|
||||
let current = self.gen_activate()?;
|
||||
|
||||
let chain = match self.chain.as_ref() {
|
||||
@@ -535,7 +540,11 @@ impl Profiles {
|
||||
None => vec![],
|
||||
};
|
||||
|
||||
Ok(PrfEnhanced { current, chain })
|
||||
Ok(PrfEnhanced {
|
||||
current,
|
||||
chain,
|
||||
callback,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,6 +553,17 @@ pub struct PrfEnhanced {
|
||||
current: Mapping,
|
||||
|
||||
chain: Vec<PrfData>,
|
||||
|
||||
callback: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PrfEnhancedResult {
|
||||
pub data: Option<Mapping>,
|
||||
|
||||
pub status: String,
|
||||
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||
|
||||
@@ -94,6 +94,8 @@ fn main() -> std::io::Result<()> {
|
||||
cmds::select_profile,
|
||||
cmds::get_profiles,
|
||||
cmds::sync_profiles,
|
||||
cmds::enhance_profiles,
|
||||
cmds::change_profile_chain
|
||||
]);
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
||||
@@ -26,9 +26,10 @@ pub fn resolve_setup(app: &App) {
|
||||
*profiles = Profiles::read_file();
|
||||
log_if_err!(clash.activate(&profiles));
|
||||
|
||||
app
|
||||
.get_window("main")
|
||||
.map(|win| log_if_err!(clash.activate_enhanced(&profiles, win)));
|
||||
match app.get_window("main") {
|
||||
Some(win) => log_if_err!(clash.activate_enhanced(&profiles, win, true)),
|
||||
None => log::error!("failed to get window for enhanced profiles"),
|
||||
};
|
||||
|
||||
verge.init_sysproxy(clash.info.port.clone());
|
||||
// enable tun mode
|
||||
|
||||
Reference in New Issue
Block a user