feat: enhance clash caller & support more commands

This commit is contained in:
GyDi 2021-12-14 18:37:03 +08:00
parent 4719649bf4
commit 881a95520a
6 changed files with 121 additions and 32 deletions

View File

@ -1,17 +1,31 @@
use tauri::api::process::kill_children;
use crate::utils::{clash, import};
use crate::{
events::{emit::ClashInfoPayload, state::ClashInfoState},
utils::{clash, import},
};
use tauri::{api::process::kill_children, AppHandle, State};
#[tauri::command]
pub fn cmd_restart_sidebar() {
pub fn restart_sidebar(app_handle: AppHandle, clash_info: State<'_, ClashInfoState>) {
kill_children();
clash::run_clash_bin();
let payload = clash::run_clash_bin(&app_handle);
if let Ok(mut arc) = clash_info.0.lock() {
*arc = payload;
}
}
#[tauri::command]
pub async fn cmd_import_profile(url: String) -> Result<String, String> {
pub async fn import_profile(url: String) -> Result<String, String> {
match import::import_profile(&url).await {
Ok(_) => Ok(String::from("success")),
Err(_) => Err(String::from("error")),
}
}
#[tauri::command]
pub fn get_clash_info(clash_info: State<'_, ClashInfoState>) -> Option<ClashInfoPayload> {
match clash_info.0.lock() {
Ok(arc) => Some(arc.clone()),
_ => None,
}
}

View File

@ -0,0 +1,26 @@
use serde::{Deserialize, Serialize};
use tauri::{AppHandle, Manager};
use crate::config::ClashController;
#[derive(Default, Debug, Clone, Deserialize, Serialize)]
pub struct ClashInfoPayload {
/// value between `success` and `error`
pub status: String,
/// the clash core's external controller infomation
pub controller: Option<ClashController>,
/// some message
pub message: Option<String>,
}
/// emit `clash_runtime` to the main windows
pub fn clash_start(app_handle: &AppHandle, payload: &ClashInfoPayload) {
match app_handle.get_window("main") {
Some(main_win) => {
main_win.emit("clash_start", payload).unwrap();
}
_ => {}
};
}

View File

@ -0,0 +1,2 @@
pub mod emit;
pub mod state;

View File

@ -0,0 +1,6 @@
use std::sync::{Arc, Mutex};
use super::emit::ClashInfoPayload;
#[derive(Default)]
pub struct ClashInfoState(pub Arc<Mutex<ClashInfoPayload>>);

View File

@ -7,10 +7,13 @@ extern crate tauri;
mod cmd;
mod config;
mod events;
mod utils;
use crate::events::state::ClashInfoState;
use std::sync::{Arc, Mutex};
use tauri::{
CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
api, CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
SystemTraySubmenu,
};
@ -41,6 +44,7 @@ fn main() -> std::io::Result<()> {
window.set_focus().unwrap();
}
"quit" => {
api::process::kill_children();
app.exit(0);
}
_ => {}
@ -53,18 +57,18 @@ fn main() -> std::io::Result<()> {
_ => {}
})
.invoke_handler(tauri::generate_handler![
cmd::cmd_import_profile,
cmd::cmd_restart_sidebar,
cmd::import_profile,
cmd::restart_sidebar,
cmd::get_clash_info,
])
.build(tauri::generate_context!())
.expect("error while running tauri application");
// init app config
utils::init::init_app(app.package_info());
// clash::run_clash_bin();
// 通过clash config初始化menu和tray
// 通过verge config干点别的
// run clash sidecar
let info = utils::clash::run_clash_bin(&app.handle());
app.manage(ClashInfoState(Arc::new(Mutex::new(info))));
app.run(|app_handle, e| match e {
tauri::Event::CloseRequested { label, api, .. } => {
@ -75,6 +79,9 @@ fn main() -> std::io::Result<()> {
tauri::Event::ExitRequested { api, .. } => {
api.prevent_exit();
}
tauri::Event::Exit => {
api::process::kill_children();
}
_ => {}
});

View File

@ -1,29 +1,63 @@
extern crate log;
use crate::utils::app_home_dir;
use tauri::api::process::{Command, CommandEvent};
use crate::{
config::read_clash_controller,
events::emit::{clash_start, ClashInfoPayload},
utils::app_home_dir,
};
use tauri::{
api::process::{Command, CommandEvent},
AppHandle,
};
/// Run the clash bin
pub fn run_clash_bin() {
pub fn run_clash_bin(app_handle: &AppHandle) -> ClashInfoPayload {
let app_dir = app_home_dir();
let mut payload = ClashInfoPayload {
status: "success".to_string(),
controller: None,
message: None,
};
let (mut rx, _sidecar) = Command::new_sidecar("clash")
.expect("failed to create clash binary")
.args(["-d", &app_dir.as_os_str().to_str().unwrap()])
.spawn()
.expect("failed to spawn sidecar");
match Command::new_sidecar("clash") {
Ok(cmd) => match cmd
.args(["-d", &app_dir.as_os_str().to_str().unwrap()])
.spawn()
{
Ok((mut rx, _)) => {
log::info!("Successfully execute clash sidecar");
payload.controller = Some(read_clash_controller());
tauri::async_runtime::spawn(async move {
while let Some(event) = rx.recv().await {
match event {
CommandEvent::Stdout(line) => {
log::info!("{}", line);
}
CommandEvent::Stderr(err) => {
log::error!("{}", err);
}
_ => {}
tauri::async_runtime::spawn(async move {
while let Some(event) = rx.recv().await {
match event {
CommandEvent::Stdout(line) => log::info!("{}", line),
CommandEvent::Stderr(err) => log::error!("{}", err),
_ => {}
}
}
});
}
Err(err) => {
log::error!(
"Failed to execute clash sidecar for \"{:?}\"",
err.to_string()
);
payload.status = "error".to_string();
payload.message = Some(err.to_string());
}
},
Err(err) => {
log::error!(
"Failed to execute clash sidecar for \"{:?}\"",
err.to_string()
);
payload.status = "error".to_string();
payload.message = Some(err.to_string());
}
});
};
clash_start(app_handle, &payload);
payload
}