feat: finish some features
This commit is contained in:
parent
df435fc9df
commit
c13a755eb6
@ -1,56 +1,30 @@
|
|||||||
|
extern crate log;
|
||||||
extern crate reqwest;
|
extern crate reqwest;
|
||||||
extern crate serde_yaml;
|
extern crate serde_yaml;
|
||||||
|
|
||||||
use std::fs;
|
use crate::init::app_home_dir;
|
||||||
use std::io::Write;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use tauri::api::path::home_dir;
|
|
||||||
use tauri::api::process::{Command, CommandEvent};
|
use tauri::api::process::{Command, CommandEvent};
|
||||||
|
|
||||||
/// Get the clash config dir
|
|
||||||
pub fn get_config_dir() -> PathBuf {
|
|
||||||
home_dir()
|
|
||||||
.unwrap()
|
|
||||||
.join(Path::new(".config"))
|
|
||||||
.join(Path::new("clash-verge"))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initialize the default config dir for clash
|
|
||||||
pub fn init_clash_config() {
|
|
||||||
let config_dir = get_config_dir();
|
|
||||||
let conifg_yaml = config_dir.join("config.yaml");
|
|
||||||
|
|
||||||
let default_yaml =
|
|
||||||
"mixed-port: 7890\nallow-lan: false\nexternal-controller: 127.0.0.1:9090\nsecret: ''\n";
|
|
||||||
let mut yaml_obj = serde_yaml::from_str::<serde_yaml::Value>(&default_yaml).unwrap();
|
|
||||||
|
|
||||||
if !config_dir.exists() {
|
|
||||||
let config_dir = config_dir.clone();
|
|
||||||
fs::create_dir(config_dir).unwrap();
|
|
||||||
let mut file = fs::File::create(conifg_yaml).unwrap();
|
|
||||||
file.write(default_yaml.as_bytes()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let yaml_path = &config_dir.join("config.yaml");
|
|
||||||
let yaml_str = fs::read_to_string(yaml_path).unwrap();
|
|
||||||
yaml_obj = serde_yaml::from_str::<serde_yaml::Value>(&yaml_str).unwrap();
|
|
||||||
|
|
||||||
println!("{:?}", yaml_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run the clash bin
|
/// Run the clash bin
|
||||||
pub fn run_clash_bin(config_dirs: &str) {
|
pub fn run_clash_bin() {
|
||||||
let (mut rx, mut _child) = Command::new_sidecar("clash")
|
let app_dir = app_home_dir();
|
||||||
|
|
||||||
|
let (mut rx, _sidecar) = Command::new_sidecar("clash")
|
||||||
.expect("failed to create clash binary")
|
.expect("failed to create clash binary")
|
||||||
.args(["-d", config_dirs])
|
.args(["-d", &app_dir.as_os_str().to_str().unwrap()])
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("failed to spawn sidecar");
|
.expect("failed to spawn sidecar");
|
||||||
|
|
||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
// read events such as stdout
|
|
||||||
while let Some(event) = rx.recv().await {
|
while let Some(event) = rx.recv().await {
|
||||||
if let CommandEvent::Stdout(line) = event {
|
match event {
|
||||||
println!("{:?}", line);
|
CommandEvent::Stdout(line) => {
|
||||||
|
log::info!("{}", line);
|
||||||
|
}
|
||||||
|
CommandEvent::Stderr(err) => {
|
||||||
|
log::error!("{}", err);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,16 @@
|
|||||||
use tauri::api::process::CommandChild;
|
use crate::clash;
|
||||||
|
use tauri::api::process::kill_children;
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn set_clash_port(process: Option<CommandChild>, port: i32) {}
|
pub fn restart_sidebar() {
|
||||||
|
kill_children();
|
||||||
|
clash::run_clash_bin();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_config_data(url: String) -> Result<String, String> {
|
||||||
|
match clash::fetch_url(&url).await {
|
||||||
|
Ok(_) => Ok(String::from("success")),
|
||||||
|
Err(_) => Err(String::from("error")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
143
src-tauri/src/init.rs
Normal file
143
src-tauri/src/init.rs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
extern crate serde_yaml;
|
||||||
|
|
||||||
|
use log::LevelFilter;
|
||||||
|
use log4rs::append::console::ConsoleAppender;
|
||||||
|
use log4rs::append::file::FileAppender;
|
||||||
|
use log4rs::config::{Appender, Config, Root};
|
||||||
|
use log4rs::encode::pattern::PatternEncoder;
|
||||||
|
use serde_yaml::Mapping;
|
||||||
|
use std::fs;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
use tauri::api::path::home_dir;
|
||||||
|
|
||||||
|
const CLASH_CONFIG: &str = r#"
|
||||||
|
mixed-port: 7890
|
||||||
|
allow-lan: false
|
||||||
|
external-controller: 127.0.0.1:9090
|
||||||
|
secret: ''
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const VERGE_CONFIG: &str = r#"
|
||||||
|
nothing: ohh!
|
||||||
|
"#;
|
||||||
|
|
||||||
|
/// get the verge app home dir
|
||||||
|
pub fn app_home_dir() -> PathBuf {
|
||||||
|
home_dir()
|
||||||
|
.unwrap()
|
||||||
|
.join(Path::new(".config"))
|
||||||
|
.join(Path::new("clash-verge"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// initialize the app home dir
|
||||||
|
fn init_app_dir() -> PathBuf {
|
||||||
|
let app_dir = app_home_dir();
|
||||||
|
if !app_dir.exists() {
|
||||||
|
fs::create_dir(&app_dir).unwrap();
|
||||||
|
}
|
||||||
|
app_dir
|
||||||
|
}
|
||||||
|
|
||||||
|
/// initialize the logs dir
|
||||||
|
fn init_log_dir() -> PathBuf {
|
||||||
|
let log_dir = app_home_dir().join("logs");
|
||||||
|
if !log_dir.exists() {
|
||||||
|
fs::create_dir(&log_dir).unwrap();
|
||||||
|
}
|
||||||
|
log_dir
|
||||||
|
}
|
||||||
|
|
||||||
|
/// initialize this instance's log file
|
||||||
|
fn init_log() {
|
||||||
|
let log_dir = init_log_dir();
|
||||||
|
let log_time = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs();
|
||||||
|
let log_file = format!("log-{:?}", log_time);
|
||||||
|
let log_file = log_dir.join(log_file);
|
||||||
|
|
||||||
|
let stdout = ConsoleAppender::builder().build();
|
||||||
|
let tofile = FileAppender::builder()
|
||||||
|
.encoder(Box::new(PatternEncoder::new(
|
||||||
|
"{d(%Y-%m-%d %H:%M:%S)} - {m}{n}",
|
||||||
|
)))
|
||||||
|
.build(log_file)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let config = Config::builder()
|
||||||
|
.appender(Appender::builder().build("stdout", Box::new(stdout)))
|
||||||
|
.appender(Appender::builder().build("file", Box::new(tofile)))
|
||||||
|
.build(
|
||||||
|
Root::builder()
|
||||||
|
.appenders(["stdout", "file"])
|
||||||
|
.build(LevelFilter::Debug),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
log4rs::init_config(config).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize & Get the clash config
|
||||||
|
fn init_clash_config() -> Mapping {
|
||||||
|
let app_dir = app_home_dir();
|
||||||
|
let yaml_path = app_dir.join("config.yaml");
|
||||||
|
let mut yaml_obj = serde_yaml::from_str::<Mapping>(CLASH_CONFIG).unwrap();
|
||||||
|
|
||||||
|
if !yaml_path.exists() {
|
||||||
|
fs::File::create(yaml_path)
|
||||||
|
.unwrap()
|
||||||
|
.write(CLASH_CONFIG.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
let yaml_str = fs::read_to_string(yaml_path).unwrap();
|
||||||
|
let user_obj = serde_yaml::from_str::<Mapping>(&yaml_str).unwrap();
|
||||||
|
for (key, value) in user_obj.iter() {
|
||||||
|
yaml_obj.insert(key.clone(), value.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yaml_obj
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize & Get the app config
|
||||||
|
fn init_verge_config() -> Mapping {
|
||||||
|
let app_dir = app_home_dir();
|
||||||
|
let yaml_path = app_dir.join("verge.yaml");
|
||||||
|
let mut yaml_obj = serde_yaml::from_str::<Mapping>(VERGE_CONFIG).unwrap();
|
||||||
|
|
||||||
|
if !yaml_path.exists() {
|
||||||
|
fs::File::create(yaml_path)
|
||||||
|
.unwrap()
|
||||||
|
.write(VERGE_CONFIG.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
let yaml_str = fs::read_to_string(yaml_path).unwrap();
|
||||||
|
let user_obj = serde_yaml::from_str::<Mapping>(&yaml_str).unwrap();
|
||||||
|
for (key, value) in user_obj.iter() {
|
||||||
|
yaml_obj.insert(key.clone(), value.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yaml_obj
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InitApp {
|
||||||
|
pub clash_config: Mapping,
|
||||||
|
pub verge_config: Mapping,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// initialize app
|
||||||
|
pub fn init_app() -> InitApp {
|
||||||
|
init_app_dir();
|
||||||
|
init_log();
|
||||||
|
|
||||||
|
let clash_config = init_clash_config();
|
||||||
|
let verge_config = init_verge_config();
|
||||||
|
|
||||||
|
InitApp {
|
||||||
|
clash_config,
|
||||||
|
verge_config,
|
||||||
|
}
|
||||||
|
}
|
@ -6,50 +6,63 @@
|
|||||||
extern crate tauri;
|
extern crate tauri;
|
||||||
|
|
||||||
mod clash;
|
mod clash;
|
||||||
|
mod cmd;
|
||||||
|
mod init;
|
||||||
mod sysopt;
|
mod sysopt;
|
||||||
|
|
||||||
use tauri::{CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu};
|
use tauri::{
|
||||||
|
CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
|
||||||
#[tauri::command]
|
SystemTraySubmenu,
|
||||||
async fn get_config_data(url: String) -> Result<String, String> {
|
};
|
||||||
match clash::fetch_url(&url).await {
|
|
||||||
Ok(_) => Ok(String::from("success")),
|
|
||||||
Err(_) => Err(String::from("error")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
clash::run_clash_bin(&clash::get_config_dir().to_str().unwrap());
|
init::init_app();
|
||||||
|
// clash::run_clash_bin();
|
||||||
|
|
||||||
|
// 通过clash config初始化menu和tray
|
||||||
|
// 通过verge config干点别的
|
||||||
|
|
||||||
|
let sub_menu = SystemTraySubmenu::new(
|
||||||
|
"出站规则",
|
||||||
|
SystemTrayMenu::new()
|
||||||
|
.add_item(CustomMenuItem::new("rway_global", "全局连接"))
|
||||||
|
.add_item(CustomMenuItem::new("rway_rule", "规则连接").selected())
|
||||||
|
.add_item(CustomMenuItem::new("rway_direct", "直接连接")),
|
||||||
|
);
|
||||||
|
let menu = SystemTrayMenu::new()
|
||||||
|
.add_submenu(sub_menu)
|
||||||
|
.add_native_item(SystemTrayMenuItem::Separator)
|
||||||
|
.add_item(CustomMenuItem::new("syste_proxy", "设置为系统代理"))
|
||||||
|
.add_item(CustomMenuItem::new("self_startup", "开机启动").selected())
|
||||||
|
.add_item(CustomMenuItem::new("open_window", "显示应用"))
|
||||||
|
.add_native_item(SystemTrayMenuItem::Separator)
|
||||||
|
.add_item(CustomMenuItem::new("quit", "退出").accelerator("CmdOrControl+Q"));
|
||||||
|
|
||||||
let app = tauri::Builder::default()
|
let app = tauri::Builder::default()
|
||||||
.system_tray(
|
.system_tray(SystemTray::new().with_menu(menu))
|
||||||
SystemTray::new().with_menu(
|
|
||||||
SystemTrayMenu::new()
|
|
||||||
.add_item(CustomMenuItem::new("event_show", "Show"))
|
|
||||||
.add_item(CustomMenuItem::new("event_quit", "Quit")),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.on_system_tray_event(move |app, event| match event {
|
.on_system_tray_event(move |app, event| match event {
|
||||||
|
SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
|
||||||
|
"open_window" => {
|
||||||
|
let window = app.get_window("main").unwrap();
|
||||||
|
window.show().unwrap();
|
||||||
|
window.set_focus().unwrap();
|
||||||
|
}
|
||||||
|
"quit" => {
|
||||||
|
app.exit(0);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
SystemTrayEvent::LeftClick { .. } => {
|
SystemTrayEvent::LeftClick { .. } => {
|
||||||
let window = app.get_window("main").unwrap();
|
let window = app.get_window("main").unwrap();
|
||||||
window.show().unwrap();
|
window.show().unwrap();
|
||||||
window.set_focus().unwrap();
|
window.set_focus().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
|
|
||||||
"event_show" => {
|
|
||||||
let window = app.get_window("main").unwrap();
|
|
||||||
window.show().unwrap();
|
|
||||||
window.set_focus().unwrap();
|
|
||||||
}
|
|
||||||
"event_quit" => {
|
|
||||||
app.exit(0);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
_ => {}
|
_ => {}
|
||||||
})
|
})
|
||||||
.invoke_handler(tauri::generate_handler![get_config_data])
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
cmd::get_config_data,
|
||||||
|
cmd::restart_sidebar,
|
||||||
|
])
|
||||||
.build(tauri::generate_context!())
|
.build(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::io;
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use winreg::enums::*;
|
use winreg::enums::*;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"distDir": "../dist",
|
"distDir": "../dist",
|
||||||
"devPath": "http://localhost:3000",
|
"devPath": "http://localhost:3000/proxy",
|
||||||
"beforeDevCommand": "npm run web:dev",
|
"beforeDevCommand": "npm run web:dev",
|
||||||
"beforeBuildCommand": "npm run web:build"
|
"beforeBuildCommand": "npm run web:build"
|
||||||
},
|
},
|
||||||
@ -61,7 +61,9 @@
|
|||||||
"width": 800,
|
"width": 800,
|
||||||
"height": 600,
|
"height": 600,
|
||||||
"resizable": true,
|
"resizable": true,
|
||||||
"fullscreen": false
|
"fullscreen": false,
|
||||||
|
"decorations": true,
|
||||||
|
"transparent": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"security": {
|
"security": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user