123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- //!
- //! feat mod 里的函数主要用于
- //! - hotkey 快捷键
- //! - timer 定时器
- //! - cmds 页面调用
- //!
- use crate::config::*;
- use crate::core::*;
- use crate::log_err;
- use crate::utils::resolve;
- use anyhow::{bail, Result};
- use serde_yaml::{Mapping, Value};
- use wry::application::clipboard::Clipboard;
- // 打开面板
- pub fn open_dashboard() {
- let handle = handle::Handle::global();
- let app_handle = handle.app_handle.lock();
- if let Some(app_handle) = app_handle.as_ref() {
- resolve::create_window(app_handle);
- }
- }
- // 重启clash
- pub fn restart_clash_core() {
- tauri::async_runtime::spawn(async {
- match CoreManager::global().run_core().await {
- Ok(_) => {
- handle::Handle::refresh_clash();
- handle::Handle::notice_message("set_config::ok", "ok");
- }
- Err(err) => {
- handle::Handle::notice_message("set_config::error", format!("{err}"));
- log::error!(target:"app", "{err}");
- }
- }
- });
- }
- // 切换模式 rule/global/direct/script mode
- pub fn change_clash_mode(mode: String) {
- let mut mapping = Mapping::new();
- mapping.insert(Value::from("mode"), mode.clone().into());
- tauri::async_runtime::spawn(async move {
- log::debug!(target: "app", "change clash mode to {mode}");
- match clash_api::patch_configs(&mapping).await {
- Ok(_) => {
- // 更新配置
- Config::clash().data().patch_config(mapping);
- if Config::clash().data().save_config().is_ok() {
- handle::Handle::refresh_clash();
- log_err!(handle::Handle::update_systray_part());
- }
- }
- Err(err) => log::error!(target: "app", "{err}"),
- }
- });
- }
- // 切换系统代理
- pub fn toggle_system_proxy() {
- let enable = Config::verge().draft().enable_system_proxy.clone();
- let enable = enable.unwrap_or(false);
- tauri::async_runtime::spawn(async move {
- match patch_verge(IVerge {
- enable_system_proxy: Some(!enable),
- ..IVerge::default()
- })
- .await
- {
- Ok(_) => handle::Handle::refresh_verge(),
- Err(err) => log::error!(target: "app", "{err}"),
- }
- });
- }
- // 打开系统代理
- pub fn enable_system_proxy() {
- tauri::async_runtime::spawn(async {
- match patch_verge(IVerge {
- enable_system_proxy: Some(true),
- ..IVerge::default()
- })
- .await
- {
- Ok(_) => handle::Handle::refresh_verge(),
- Err(err) => log::error!(target: "app", "{err}"),
- }
- });
- }
- // 关闭系统代理
- pub fn disable_system_proxy() {
- tauri::async_runtime::spawn(async {
- match patch_verge(IVerge {
- enable_system_proxy: Some(false),
- ..IVerge::default()
- })
- .await
- {
- Ok(_) => handle::Handle::refresh_verge(),
- Err(err) => log::error!(target: "app", "{err}"),
- }
- });
- }
- // 切换tun模式
- pub fn toggle_tun_mode() {
- let enable = Config::verge().data().enable_tun_mode.clone();
- let enable = enable.unwrap_or(false);
- tauri::async_runtime::spawn(async move {
- match patch_verge(IVerge {
- enable_tun_mode: Some(!enable),
- ..IVerge::default()
- })
- .await
- {
- Ok(_) => handle::Handle::refresh_verge(),
- Err(err) => log::error!(target: "app", "{err}"),
- }
- });
- }
- // 打开tun模式
- pub fn enable_tun_mode() {
- tauri::async_runtime::spawn(async {
- match patch_verge(IVerge {
- enable_tun_mode: Some(true),
- ..IVerge::default()
- })
- .await
- {
- Ok(_) => handle::Handle::refresh_verge(),
- Err(err) => log::error!(target: "app", "{err}"),
- }
- });
- }
- // 关闭tun模式
- pub fn disable_tun_mode() {
- tauri::async_runtime::spawn(async {
- match patch_verge(IVerge {
- enable_tun_mode: Some(false),
- ..IVerge::default()
- })
- .await
- {
- Ok(_) => handle::Handle::refresh_verge(),
- Err(err) => log::error!(target: "app", "{err}"),
- }
- });
- }
- /// 修改clash的配置
- pub async fn patch_clash(patch: Mapping) -> Result<()> {
- Config::clash().draft().patch_config(patch.clone());
- match {
- let mixed_port = patch.get("mixed-port");
- if mixed_port.is_some() {
- let changed = mixed_port != Config::clash().data().0.get("mixed-port");
- // 检查端口占用
- if changed {
- if let Some(port) = mixed_port.clone().unwrap().as_u64() {
- if !port_scanner::local_port_available(port as u16) {
- Config::clash().discard();
- bail!("port already in use");
- }
- }
- }
- };
- // 激活配置
- if mixed_port.is_some()
- || patch.get("secret").is_some()
- || patch.get("external-controller").is_some()
- {
- Config::generate()?;
- CoreManager::global().run_core().await?;
- handle::Handle::refresh_clash();
- }
- // 更新系统代理
- if mixed_port.is_some() {
- log_err!(sysopt::Sysopt::global().init_sysproxy());
- }
- if patch.get("mode").is_some() {
- log_err!(handle::Handle::update_systray_part());
- }
- Config::runtime().latest().patch_config(patch);
- <Result<()>>::Ok(())
- } {
- Ok(()) => {
- Config::clash().apply();
- Config::clash().data().save_config()?;
- Ok(())
- }
- Err(err) => {
- Config::clash().discard();
- Err(err)
- }
- }
- }
- /// 修改verge的配置
- /// 一般都是一个个的修改
- pub async fn patch_verge(patch: IVerge) -> Result<()> {
- Config::verge().draft().patch_config(patch.clone());
- let tun_mode = patch.enable_tun_mode;
- let auto_launch = patch.enable_auto_launch;
- let system_proxy = patch.enable_system_proxy;
- let proxy_bypass = patch.system_proxy_bypass;
- let language = patch.language;
- match {
- #[cfg(target_os = "windows")]
- {
- let service_mode = patch.enable_service_mode;
- if service_mode.is_some() {
- log::debug!(target: "app", "change service mode to {}", service_mode.unwrap());
- Config::generate()?;
- CoreManager::global().run_core().await?;
- } else if tun_mode.is_some() {
- update_core_config().await?;
- }
- }
- #[cfg(not(target_os = "windows"))]
- if tun_mode.is_some() {
- update_core_config().await?;
- }
- if auto_launch.is_some() {
- sysopt::Sysopt::global().update_launch()?;
- }
- if system_proxy.is_some() || proxy_bypass.is_some() {
- sysopt::Sysopt::global().update_sysproxy()?;
- sysopt::Sysopt::global().guard_proxy();
- }
- if let Some(true) = patch.enable_proxy_guard {
- sysopt::Sysopt::global().guard_proxy();
- }
- if let Some(hotkeys) = patch.hotkeys {
- hotkey::Hotkey::global().update(hotkeys)?;
- }
- if language.is_some() {
- handle::Handle::update_systray()?;
- } else if system_proxy.or(tun_mode).is_some() {
- handle::Handle::update_systray_part()?;
- }
- <Result<()>>::Ok(())
- } {
- Ok(()) => {
- Config::verge().apply();
- Config::verge().data().save_file()?;
- Ok(())
- }
- Err(err) => {
- Config::verge().discard();
- Err(err)
- }
- }
- }
- /// 更新某个profile
- /// 如果更新当前配置就激活配置
- pub async fn update_profile(uid: String, option: Option<PrfOption>) -> Result<()> {
- let url_opt = {
- let profiles = Config::profiles();
- let profiles = profiles.latest();
- let item = profiles.get_item(&uid)?;
- let is_remote = item.itype.as_ref().map_or(false, |s| s == "remote");
- if !is_remote {
- None // 直接更新
- } else if item.url.is_none() {
- bail!("failed to get the profile item url");
- } else {
- Some((item.url.clone().unwrap(), item.option.clone()))
- }
- };
- let should_update = match url_opt {
- Some((url, opt)) => {
- let merged_opt = PrfOption::merge(opt, option);
- let item = PrfItem::from_url(&url, None, None, merged_opt).await?;
- let profiles = Config::profiles();
- let mut profiles = profiles.latest();
- profiles.update_item(uid.clone(), item)?;
- Some(uid) == profiles.get_current()
- }
- None => true,
- };
- if should_update {
- update_core_config().await?;
- }
- Ok(())
- }
- /// 更新配置
- async fn update_core_config() -> Result<()> {
- match CoreManager::global().update_config().await {
- Ok(_) => {
- handle::Handle::refresh_clash();
- handle::Handle::notice_message("set_config::ok", "ok");
- Ok(())
- }
- Err(err) => {
- handle::Handle::notice_message("set_config::error", format!("{err}"));
- Err(err)
- }
- }
- }
- /// copy env variable
- pub fn copy_clash_env() {
- let port = { Config::clash().data().get_client_info().port };
- let text = format!("export https_proxy=http://127.0.0.1:{port} http_proxy=http://127.0.0.1:{port} all_proxy=socks5://127.0.0.1:{port}");
- let mut cliboard = Clipboard::new();
- cliboard.write_text(text);
- }
|