chore: update

This commit is contained in:
huzibaca
2024-09-02 19:33:17 +08:00
parent ad80d21e89
commit 6cc81fe6b8
42 changed files with 16683 additions and 2013 deletions

View File

@@ -2,10 +2,7 @@ use crate::core::handle;
use anyhow::Result;
use once_cell::sync::OnceCell;
use std::path::PathBuf;
use tauri::{
api::path::{data_dir, resource_dir},
Env,
};
use tauri::Manager;
#[cfg(not(feature = "verge-dev"))]
pub static APP_ID: &str = "io.github.clash-verge-rev.clash-verge-rev";
@@ -48,9 +45,21 @@ pub fn app_home_dir() -> Result<PathBuf> {
return Ok(PathBuf::from(app_dir).join(".config").join(APP_ID));
}
Ok(data_dir()
.ok_or(anyhow::anyhow!("failed to get app home dir"))?
.join(APP_ID))
let handle = handle::Handle::global();
let app_handle = handle.app_handle.lock();
if let Some(app_handle) = app_handle.as_ref() {
match app_handle.path().data_dir() {
Ok(dir) => {
return Ok(dir.join(APP_ID));
}
Err(e) => {
log::error!("Failed to get the app home directory: {}", e);
return Err(anyhow::anyhow!("Failed to get the app homedirectory"));
}
}
}
Err(anyhow::anyhow!("failed to get the app home dir"))
}
/// get the resources dir
@@ -58,10 +67,15 @@ pub fn app_resources_dir() -> Result<PathBuf> {
let handle = handle::Handle::global();
let app_handle = handle.app_handle.lock();
if let Some(app_handle) = app_handle.as_ref() {
let res_dir = resource_dir(app_handle.package_info(), &Env::default())
.ok_or(anyhow::anyhow!("failed to get the resource dir"))?
.join("resources");
return Ok(res_dir);
match app_handle.path().resource_dir() {
Ok(dir) => {
return Ok(dir.join("resources"));
}
Err(e) => {
log::error!("Failed to get the resource directory: {}", e);
return Err(anyhow::anyhow!("Failed to get the resource directory"));
}
};
};
Err(anyhow::anyhow!("failed to get the resource dir"))
}
@@ -88,6 +102,10 @@ pub fn profiles_path() -> Result<PathBuf> {
Ok(app_home_dir()?.join(PROFILE_YAML))
}
pub fn clash_pid_path() -> Result<PathBuf> {
Ok(app_home_dir()?.join("clash.pid"))
}
#[cfg(not(target_os = "windows"))]
pub fn service_path() -> Result<PathBuf> {
Ok(app_resources_dir()?.join("clash-verge-service"))

View File

@@ -4,10 +4,8 @@ use nanoid::nanoid;
use serde::{de::DeserializeOwned, Serialize};
use serde_yaml::{Mapping, Value};
use std::{fs, path::PathBuf, str::FromStr};
use tauri::{
api::shell::{open, Program},
Manager,
};
use tauri_plugin_shell::ShellExt;
/// read data from yaml as struct T
pub fn read_yaml<T: DeserializeOwned>(path: &PathBuf) -> Result<T> {
@@ -104,20 +102,7 @@ pub fn get_last_part_and_decode(url: &str) -> Option<String> {
/// open file
/// use vscode by default
pub fn open_file(app: tauri::AppHandle, path: PathBuf) -> Result<()> {
#[cfg(target_os = "macos")]
let code = "Visual Studio Code";
#[cfg(not(target_os = "macos"))]
let code = "code";
let _ = match Program::from_str(code) {
Ok(code) => open(&app.shell_scope(), path.to_string_lossy(), Some(code)),
Err(err) => {
log::error!(target: "app", "Can't find VScode `{err}`");
// default open
open(&app.shell_scope(), path.to_string_lossy(), None)
}
};
app.shell().open(path.to_string_lossy(), None).unwrap();
Ok(())
}

View File

@@ -10,7 +10,8 @@ use log4rs::encode::pattern::PatternEncoder;
use std::fs::{self, DirEntry};
use std::path::PathBuf;
use std::str::FromStr;
use tauri::api::process::Command;
use tauri::AppHandle;
use tauri_plugin_shell::ShellExt;
/// initialize this instance's log file
fn init_log() -> Result<()> {
@@ -296,43 +297,39 @@ pub fn init_scheme() -> Result<()> {
Ok(())
}
pub fn startup_script() -> Result<()> {
let path = {
pub async fn startup_script(app_handle: &AppHandle) -> Result<()> {
let script_path = {
let verge = Config::verge();
let verge = verge.latest();
verge.startup_script.clone().unwrap_or("".to_string())
};
if !path.is_empty() {
let mut shell = "";
if path.ends_with(".sh") {
shell = "bash";
}
if path.ends_with(".ps1") {
shell = "powershell";
}
if path.ends_with(".bat") {
shell = "powershell";
}
if shell.is_empty() {
return Err(anyhow::anyhow!("unsupported script: {path}"));
}
let current_dir = PathBuf::from(path.clone());
if !current_dir.exists() {
return Err(anyhow::anyhow!("script not found: {path}"));
}
let current_dir = current_dir.parent();
match current_dir {
Some(dir) => {
let _ = Command::new(shell)
.current_dir(dir.to_path_buf())
.args([path])
.output()?;
}
None => {
let _ = Command::new(shell).args([path]).output()?;
}
}
if script_path.is_empty() {
return Ok(());
}
let shell_type = if script_path.ends_with(".sh") {
"bash"
} else if script_path.ends_with(".ps1") || script_path.ends_with(".bat") {
"powershell"
} else {
return Err(anyhow::anyhow!("unsupported script extension: {}", script_path));
};
let script_dir = PathBuf::from(&script_path);
if !script_dir.exists() {
return Err(anyhow::anyhow!("script not found: {}", script_path));
}
let parent_dir = script_dir.parent();
let working_dir = parent_dir.unwrap_or(script_dir.as_ref());
app_handle
.shell()
.command(shell_type)
.current_dir(working_dir.to_path_buf())
.args(&[script_path])
.output().await?;
Ok(())
}

View File

@@ -6,10 +6,12 @@ use anyhow::Result;
use once_cell::sync::OnceCell;
use serde_yaml::Mapping;
use std::net::TcpListener;
use tauri::api::notification;
use tauri::{App, AppHandle, Manager};
#[cfg(not(target_os = "linux"))]
use window_shadows::set_shadow;
// use window_shadows::set_shadow;
use tauri_plugin_notification::NotificationExt;
pub static VERSION: OnceCell<String> = OnceCell::new();
@@ -33,14 +35,14 @@ pub fn find_unused_port() -> Result<u16> {
/// handle something when start app
pub async fn resolve_setup(app: &mut App) {
#[cfg(target_os = "macos")]
app.set_activation_policy(tauri::ActivationPolicy::Accessory);
app.set_activation_policy(tauri::ActivationPolicy::Regular);
let version = app.package_info().version.to_string();
handle::Handle::global().init(app.app_handle());
VERSION.get_or_init(|| version.clone());
log_err!(init::init_resources());
log_err!(init::init_scheme());
log_err!(init::startup_script());
log_err!(init::startup_script(app.app_handle()).await);
// 处理随机端口
let enable_random_port = Config::verge().latest().enable_random_port.unwrap_or(false);
@@ -74,7 +76,7 @@ pub async fn resolve_setup(app: &mut App) {
log_err!(Config::init_config().await);
log::trace!("launch core");
log_err!(CoreManager::global().init());
log_err!(CoreManager::global().init(app.app_handle()));
// setup a simple http server for singleton
log::trace!("launch embed server");
@@ -115,17 +117,17 @@ pub fn resolve_reset() {
/// create main window
pub fn create_window(app_handle: &AppHandle) {
if let Some(window) = app_handle.get_window("main") {
if let Some(window) = app_handle.get_webview_window("main") {
trace_err!(window.unminimize(), "set win unminimize");
trace_err!(window.show(), "set win visible");
trace_err!(window.set_focus(), "set win focus");
return;
}
let mut builder = tauri::window::WindowBuilder::new(
let mut builder = tauri::WebviewWindowBuilder::new(
app_handle,
"main".to_string(),
tauri::WindowUrl::App("index.html".into()),
tauri::WebviewUrl::App("index.html".into()),
)
.title("Clash Verge")
.visible(false)
@@ -199,8 +201,8 @@ pub fn create_window(app_handle: &AppHandle) {
trace_err!(win.center(), "set win center");
}
#[cfg(not(target_os = "linux"))]
trace_err!(set_shadow(&win, true), "set win shadow");
// #[cfg(not(target_os = "linux"))]
// trace_err!(set_shadow(&win, true), "set win shadow");
if is_maximized {
trace_err!(win.maximize(), "set win maximize");
}
@@ -221,7 +223,7 @@ pub fn save_window_size_position(app_handle: &AppHandle, save_to_file: bool) ->
}
let win = app_handle
.get_window("main")
.get_webview_window("main")
.ok_or(anyhow::anyhow!("failed to get window"))?;
let scale = win.scale_factor()?;
@@ -241,21 +243,30 @@ pub async fn resolve_scheme(param: String) -> Result<()> {
let url = param
.trim_start_matches("clash://install-config/?url=")
.trim_start_matches("clash://install-config?url=");
match import_profile(url.to_string(), None).await {
Ok(_) => {
notification::Notification::new(crate::utils::dirs::APP_ID)
.title("Clash Verge")
.body("Import profile success")
.show()
.unwrap();
}
Err(e) => {
notification::Notification::new(crate::utils::dirs::APP_ID)
.title("Clash Verge")
.body(format!("Import profile failed: {e}"))
.show()
.unwrap();
log::error!("Import profile failed: {e}");
let handle = handle::Handle::global();
let app_handle = handle.app_handle.lock();
if let Some(app_handle) = app_handle.as_ref() {
match import_profile(url.to_string(), None).await {
Ok(_) => {
app_handle
.notification()
.builder()
.title("Clash Verge")
.body("Import profile success")
.show()
.unwrap();
}
Err(e) => {
app_handle
.notification()
.builder()
.title("Clash Verge")
.body(format!("Import profile failed: {e}"))
.show()
.unwrap();
log::error!("Import profile failed: {e}");
}
}
}
Ok(())

View File

@@ -1,20 +1,16 @@
extern crate warp;
use super::resolve;
use crate::{
config::{Config, IVerge, DEFAULT_PAC},
log_err,
};
use crate::config::{Config, IVerge, DEFAULT_PAC};
use anyhow::{bail, Result};
use port_scanner::local_port_available;
use std::convert::Infallible;
use tauri::AppHandle;
use warp::http::StatusCode;
use warp::Filter;
#[derive(serde::Deserialize, Debug)]
struct QueryParam {
param: String,
}
struct QueryParam {}
/// check whether there is already exists
pub async fn check_singleton() -> Result<()> {
@@ -56,14 +52,15 @@ pub async fn check_singleton() -> Result<()> {
/// The embed server only be used to implement singleton process
/// maybe it can be used as pac server later
pub fn embed_server(app_handle: AppHandle) {
pub fn embed_server(app_handle: &AppHandle) {
let port = IVerge::get_singleton_port();
let handle = app_handle.clone();
tauri::async_runtime::spawn(async move {
let ping = warp::path!("commands" / "ping").map(move || "ok");
let visible = warp::path!("commands" / "visible").map(move || {
resolve::create_window(&app_handle);
resolve::create_window(&handle);
"ok"
});
@@ -87,9 +84,9 @@ pub fn embed_server(app_handle: AppHandle) {
.and(warp::query::<QueryParam>())
.and_then(scheme_handler);
async fn scheme_handler(query: QueryParam) -> Result<impl warp::Reply, Infallible> {
log_err!(resolve::resolve_scheme(query.param).await);
Ok("ok")
async fn scheme_handler(_: QueryParam) -> Result<impl warp::Reply, Infallible> {
//let _ = resolve::resolve_scheme(query.param).await;
Ok(warp::reply::with_status("Ok", StatusCode::OK))
}
let commands = ping.or(visible).or(pac).or(scheme);
warp::serve(commands).run(([127, 0, 0, 1], port)).await;