use autostart plugin and hide window when autostart
Some checks are pending
EasyTier Core / pre_job (push) Waiting to run
EasyTier Core / build (linux-aarch64, ubuntu-latest, aarch64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-arm, ubuntu-latest, arm-unknown-linux-musleabi) (push) Blocked by required conditions
EasyTier Core / build (linux-armhf, ubuntu-latest, arm-unknown-linux-musleabihf) (push) Blocked by required conditions
EasyTier Core / build (linux-armv7, ubuntu-latest, armv7-unknown-linux-musleabi) (push) Blocked by required conditions
EasyTier Core / build (linux-armv7hf, ubuntu-latest, armv7-unknown-linux-musleabihf) (push) Blocked by required conditions
EasyTier Core / build (linux-mips, ubuntu-latest, mips-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-mipsel, ubuntu-latest, mipsel-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-x86_64, ubuntu-latest, x86_64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (macos-aarch64, macos-latest, aarch64-apple-darwin) (push) Blocked by required conditions
EasyTier Core / build (macos-x86_64, macos-latest, x86_64-apple-darwin) (push) Blocked by required conditions
EasyTier Core / build (windows-x86_64, windows-latest, x86_64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier Core / core-result (push) Blocked by required conditions
EasyTier GUI / pre_job (push) Waiting to run
EasyTier GUI / build-gui (linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-latest, aarch64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier GUI / build-gui (linux-x86_64, x86_64-unknown-linux-gnu, ubuntu-latest, x86_64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier GUI / build-gui (macos-aarch64, aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Blocked by required conditions
EasyTier GUI / build-gui (macos-x86_64, x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Blocked by required conditions
EasyTier GUI / build-gui (windows-x86_64, x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier GUI / gui-result (push) Blocked by required conditions
EasyTier Mobile / pre_job (push) Waiting to run
EasyTier Mobile / build-mobile (android, ubuntu-latest, android) (push) Blocked by required conditions
EasyTier Mobile / mobile-result (push) Blocked by required conditions
EasyTier Test / pre_job (push) Waiting to run
EasyTier Test / test (push) Blocked by required conditions

This commit is contained in:
sijie.sun 2024-08-15 22:43:58 +08:00 committed by Sijie.Sun
parent ce10bf5e60
commit 2aa686f7ad
12 changed files with 192 additions and 213 deletions

17
Cargo.lock generated
View File

@ -1542,7 +1542,6 @@ name = "easytier-gui"
version = "1.2.2"
dependencies = [
"anyhow",
"auto-launch",
"chrono",
"dashmap",
"dunce",
@ -1554,6 +1553,7 @@ dependencies = [
"serde_json",
"tauri",
"tauri-build",
"tauri-plugin-autostart",
"tauri-plugin-clipboard-manager",
"tauri-plugin-os",
"tauri-plugin-positioner",
@ -5898,6 +5898,21 @@ dependencies = [
"walkdir",
]
[[package]]
name = "tauri-plugin-autostart"
version = "2.0.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25958a42daab7aaff4faff15cbaffd5505873a0654e6382c74fca1729a791898"
dependencies = [
"auto-launch",
"log",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
"thiserror",
]
[[package]]
name = "tauri-plugin-clipboard-manager"
version = "2.0.0-rc.0"

View File

@ -13,6 +13,7 @@
},
"dependencies": {
"@primevue/themes": "^4.0.4",
"@tauri-apps/plugin-autostart": "2.0.0-rc.0",
"@tauri-apps/plugin-clipboard-manager": "2.0.0-rc.0",
"@tauri-apps/plugin-os": "2.0.0-rc.0",
"@tauri-apps/plugin-process": "2.0.0-rc.0",

View File

@ -11,6 +11,9 @@ importers:
'@primevue/themes':
specifier: ^4.0.4
version: 4.0.4
'@tauri-apps/plugin-autostart':
specifier: 2.0.0-rc.0
version: 2.0.0-rc.0
'@tauri-apps/plugin-clipboard-manager':
specifier: 2.0.0-rc.0
version: 2.0.0-rc.0
@ -67,8 +70,8 @@ importers:
specifier: 2.0.0-rc.0
version: 2.0.0-rc.0
'@tauri-apps/cli':
specifier: 2.0.0-rc.1
version: 2.0.0-rc.1
specifier: 2.0.0-rc.3
version: 2.0.0-rc.3
'@types/node':
specifier: ^20.14.15
version: 20.14.15
@ -948,71 +951,74 @@ packages:
resolution: {integrity: sha512-v454Qs3REHc3Za59U+/eSmBsdmF+3NE5+76+lFDaitVqN4ZglDHENDaMARYKGJVZuxiSkzyqG0SeG7lLQjVkPA==}
engines: {node: '>= 18.18', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
'@tauri-apps/cli-darwin-arm64@2.0.0-rc.1':
resolution: {integrity: sha512-dJxyAi4P9fOkklBZXuwUVnHgdM/20fgM4zYdfejQfju5+q9GUqnMbrrIUqlJbQGf8EnrIdSWnieO8wU8GOwT0g==}
'@tauri-apps/cli-darwin-arm64@2.0.0-rc.3':
resolution: {integrity: sha512-szYCSr/ChbCF+S6Wnr15TYpI2cZR07d+AQOiFGuScP0preM8Pbsk/sb0hfLwqzepjVFFNVWQba9sG7FEW2Y2XA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
'@tauri-apps/cli-darwin-x64@2.0.0-rc.1':
resolution: {integrity: sha512-dwrqLzNIFk8a1Vf2YI8axHm7uvLfo4M4TSWCw2ZkgeSGWWK6Y6CYVZbBEjOEGIOf+GFAa9rVOSZRuMwpiufNng==}
'@tauri-apps/cli-darwin-x64@2.0.0-rc.3':
resolution: {integrity: sha512-BJv6EJOY1DJbRzVtfg8CcBAlnS5OjhBAc5YKjh4BT7EyOcop8HStBSxhL6yjWrUP7eLR1iIsW/uSehVJwzYIdQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
'@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-rc.1':
resolution: {integrity: sha512-jvMF4UNc3Jr/xHnw+4NNsWfk8WrcFrQVImAtKlCev9QepqfBmDh+FgXTvfysoBCSxEBS626TvYms3OhI0LOO4A==}
'@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-rc.3':
resolution: {integrity: sha512-fwx805/xL4sF/EdMYqcUHQHzMYwo+OVTBTz5x/JWK8D57rnmLHAP+ZhnfFsZQLRo2QRT2l1Ye3bDyU+QRA1JFA==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
'@tauri-apps/cli-linux-arm64-gnu@2.0.0-rc.1':
resolution: {integrity: sha512-TGmadGW8BjTq864AYrv/u+vTnAodnOuzv1VCUOV23O8st35GZG6V47jwNsSjQjhrcO1XzmJiRAtrcVKuTZ/xUA==}
'@tauri-apps/cli-linux-arm64-gnu@2.0.0-rc.3':
resolution: {integrity: sha512-3KauzO1Ls4kuY0nr82S4X8XFxlQAMN+Mqp8LLqvQ+PPMp92XQAkPH7osQdoHIEoW5gsE69U2JaiQ5tHSqNM9og==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tauri-apps/cli-linux-arm64-musl@2.0.0-rc.1':
resolution: {integrity: sha512-+SJsRTW0PvvD7awEn+tIPJ3s12s6RpKXdOib2mztoKocasrGRfz+EFZuXc42Iwk3xROsrQkiw2UAmcNLkW5NwA==}
'@tauri-apps/cli-linux-arm64-musl@2.0.0-rc.3':
resolution: {integrity: sha512-ngHS0foffm1xO5gqnDKGeYMKj8ceGmrFP5dDldoaaMQubw1SyFa0pRUjb7fZSYiO7F4SOSa8NYeMqlF9peZmnQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tauri-apps/cli-linux-x64-gnu@2.0.0-rc.1':
resolution: {integrity: sha512-vjPrj2btS97IOp6cU42IrkI49SQZDSg8TPqwOwFqyQeAotCT1i0F38pLZWe1gLyPUowO8XdaaBdwYg6IRDKcZg==}
'@tauri-apps/cli-linux-x64-gnu@2.0.0-rc.3':
resolution: {integrity: sha512-0/am9pVvuUHGmz32M8ffz1fpLnc08j3nzcRe5wUdL2AxfT+wKMII+Dn99GtCVgcdDW4jSXDMRUwrBkGocGC2OA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tauri-apps/cli-linux-x64-musl@2.0.0-rc.1':
resolution: {integrity: sha512-MrE68/u6rMrkM1uM/DR1MNnMXiYebhSPGqqxshJ12SmFdk3yQ/Z73Wzvk8xv78eOExh4lTtEXI22YwaBCf9AEg==}
'@tauri-apps/cli-linux-x64-musl@2.0.0-rc.3':
resolution: {integrity: sha512-r7mRi8q8TqTFVjb9kAsU7IgwUgno2s8Ip4xwq9psQhlRE3JGEZQmSEcy1jqTjfl6KFh6lJcDR7l+9/EMhL/D3Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tauri-apps/cli-win32-arm64-msvc@2.0.0-rc.1':
resolution: {integrity: sha512-SLulbiUjg8BGf/zX+U1PGjB+JpsN2nLRGuW07BYwSDW3s3mp2aagLuOwaTaOPBrDzfIMRYq8KT54A4jfRjEZlg==}
'@tauri-apps/cli-win32-arm64-msvc@2.0.0-rc.3':
resolution: {integrity: sha512-2J6KjmDIQCw6HF1X6/yPcd+JLl7pxrH2zVMGmNllaoWhHeByvRobqFWnT7gcdHaA3dGTo432CwWvOgTgrINQpQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
'@tauri-apps/cli-win32-ia32-msvc@2.0.0-rc.1':
resolution: {integrity: sha512-rz85riTjcWdZlgTku6HcBx625Otdc0/NwDjRXgdXakL1ybw7E+G5YlLZNcQX25u17RKUAWX/2/VZ1pSz945Ovw==}
'@tauri-apps/cli-win32-ia32-msvc@2.0.0-rc.3':
resolution: {integrity: sha512-8q75CsHDSEDdgi6xPwim+BaQZFCswK2Dn/qL38V3Mh9kmVvC8oGJMPC66bC20dF+v3KWeFm2FNNGQqOSXCveHg==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
'@tauri-apps/cli-win32-x64-msvc@2.0.0-rc.1':
resolution: {integrity: sha512-aRO70dDbn4w3CbALMG+b7g460xmbSTuUiGmRh0r/MNVeoZk/YbqluBUyhXdWGxJb8OVubw/4RlczKYcPmJceMw==}
'@tauri-apps/cli-win32-x64-msvc@2.0.0-rc.3':
resolution: {integrity: sha512-qeBRJYalahxEXolekcpZJ/HBrIJacG2NWJBGhhi797mIwnbmlpbHMc8blIJtNNNwVUb2BjXuxKQVfojQ5YYrcg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
'@tauri-apps/cli@2.0.0-rc.1':
resolution: {integrity: sha512-9AzVrUMdb6EZ/Lwtdqt03XqqG6d/3gTJPOw2E9zmCHprJWEwqEp4JIVHYYfrqkkZyKclD3m5ggXwfYwclcYLdw==}
'@tauri-apps/cli@2.0.0-rc.3':
resolution: {integrity: sha512-iNF95pieBmverl1EmQyqh+fhcIClS544fN5Ex5lAbYLTiHZ/gm3lOfVBhF6NPaKd/sfLuy7K1tfDXlHztBfANw==}
engines: {node: '>= 10'}
hasBin: true
'@tauri-apps/plugin-autostart@2.0.0-rc.0':
resolution: {integrity: sha512-V49lm++vhrMPPDGMtmOcbJLF4TYu78ZmAiMhyd4FFnbYlgin6ZTjiMCFEl4JKVy2lqP3C8DQvXf/gkUMuER7Iw==}
'@tauri-apps/plugin-clipboard-manager@2.0.0-rc.0':
resolution: {integrity: sha512-2fS3wbRQEtorkk3Np2msJUeKCXRqLQ9sSo2FzlFdUPYNzThsu43uWCF55McGLAfltNOvXQIcQLUBf05jbBL/5w==}
@ -4174,48 +4180,52 @@ snapshots:
'@tauri-apps/api@2.0.0-rc.0': {}
'@tauri-apps/cli-darwin-arm64@2.0.0-rc.1':
'@tauri-apps/cli-darwin-arm64@2.0.0-rc.3':
optional: true
'@tauri-apps/cli-darwin-x64@2.0.0-rc.1':
'@tauri-apps/cli-darwin-x64@2.0.0-rc.3':
optional: true
'@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-rc.1':
'@tauri-apps/cli-linux-arm-gnueabihf@2.0.0-rc.3':
optional: true
'@tauri-apps/cli-linux-arm64-gnu@2.0.0-rc.1':
'@tauri-apps/cli-linux-arm64-gnu@2.0.0-rc.3':
optional: true
'@tauri-apps/cli-linux-arm64-musl@2.0.0-rc.1':
'@tauri-apps/cli-linux-arm64-musl@2.0.0-rc.3':
optional: true
'@tauri-apps/cli-linux-x64-gnu@2.0.0-rc.1':
'@tauri-apps/cli-linux-x64-gnu@2.0.0-rc.3':
optional: true
'@tauri-apps/cli-linux-x64-musl@2.0.0-rc.1':
'@tauri-apps/cli-linux-x64-musl@2.0.0-rc.3':
optional: true
'@tauri-apps/cli-win32-arm64-msvc@2.0.0-rc.1':
'@tauri-apps/cli-win32-arm64-msvc@2.0.0-rc.3':
optional: true
'@tauri-apps/cli-win32-ia32-msvc@2.0.0-rc.1':
'@tauri-apps/cli-win32-ia32-msvc@2.0.0-rc.3':
optional: true
'@tauri-apps/cli-win32-x64-msvc@2.0.0-rc.1':
'@tauri-apps/cli-win32-x64-msvc@2.0.0-rc.3':
optional: true
'@tauri-apps/cli@2.0.0-rc.1':
'@tauri-apps/cli@2.0.0-rc.3':
optionalDependencies:
'@tauri-apps/cli-darwin-arm64': 2.0.0-rc.1
'@tauri-apps/cli-darwin-x64': 2.0.0-rc.1
'@tauri-apps/cli-linux-arm-gnueabihf': 2.0.0-rc.1
'@tauri-apps/cli-linux-arm64-gnu': 2.0.0-rc.1
'@tauri-apps/cli-linux-arm64-musl': 2.0.0-rc.1
'@tauri-apps/cli-linux-x64-gnu': 2.0.0-rc.1
'@tauri-apps/cli-linux-x64-musl': 2.0.0-rc.1
'@tauri-apps/cli-win32-arm64-msvc': 2.0.0-rc.1
'@tauri-apps/cli-win32-ia32-msvc': 2.0.0-rc.1
'@tauri-apps/cli-win32-x64-msvc': 2.0.0-rc.1
'@tauri-apps/cli-darwin-arm64': 2.0.0-rc.3
'@tauri-apps/cli-darwin-x64': 2.0.0-rc.3
'@tauri-apps/cli-linux-arm-gnueabihf': 2.0.0-rc.3
'@tauri-apps/cli-linux-arm64-gnu': 2.0.0-rc.3
'@tauri-apps/cli-linux-arm64-musl': 2.0.0-rc.3
'@tauri-apps/cli-linux-x64-gnu': 2.0.0-rc.3
'@tauri-apps/cli-linux-x64-musl': 2.0.0-rc.3
'@tauri-apps/cli-win32-arm64-msvc': 2.0.0-rc.3
'@tauri-apps/cli-win32-ia32-msvc': 2.0.0-rc.3
'@tauri-apps/cli-win32-x64-msvc': 2.0.0-rc.3
'@tauri-apps/plugin-autostart@2.0.0-rc.0':
dependencies:
'@tauri-apps/api': 2.0.0-rc.0
'@tauri-apps/plugin-clipboard-manager@2.0.0-rc.0':
dependencies:

View File

@ -35,7 +35,6 @@ dashmap = "6.0"
privilege = "0.3"
gethostname = "0.5"
auto-launch = "0.5.0"
dunce = "1.0.4"
tauri-plugin-shell = "2.0.0-rc"
@ -44,6 +43,7 @@ tauri-plugin-clipboard-manager = "2.0.0-rc"
tauri-plugin-positioner = { version = "2.0.0-rc", features = ["tray-icon"] }
tauri-plugin-vpnservice = { path = "../../tauri-plugin-vpnservice" }
tauri-plugin-os = "2.0.0-rc"
tauri-plugin-autostart = "2.0.0-rc"
[features]

View File

@ -1,34 +1,3 @@
fn main() {
if !cfg!(debug_assertions) && cfg!(target_os = "windows") {
let mut windows = tauri_build::WindowsAttributes::new();
windows = windows.app_manifest(
r#"
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
"#,
);
tauri_build::try_build(tauri_build::Attributes::new().windows_attributes(windows))
.expect("failed to run build script");
} else {
tauri_build::build();
}
}
fn main() {
tauri_build::build();
}

View File

@ -44,6 +44,10 @@
"os:allow-arch",
"os:allow-hostname",
"os:allow-platform",
"os:allow-locale"
"os:allow-locale",
"autostart:default",
"autostart:allow-disable",
"autostart:allow-enable",
"autostart:allow-is-enabled"
]
}

View File

@ -4,8 +4,6 @@
use std::collections::BTreeMap;
use anyhow::Context;
#[cfg(not(target_os = "android"))]
use auto_launch::AutoLaunchBuilder;
use dashmap::DashMap;
use easytier::{
common::config::{
@ -19,6 +17,8 @@ use serde::{Deserialize, Serialize};
use tauri::Manager as _;
pub const AUTOSTART_ARG: &str = "--autostart";
#[derive(Deserialize, Serialize, PartialEq, Debug)]
enum NetworkingMethod {
PublicServer,
@ -171,6 +171,13 @@ static INSTANCE_MAP: once_cell::sync::Lazy<DashMap<String, NetworkInstance>> =
static mut LOGGER_LEVEL_SENDER: once_cell::sync::Lazy<Option<NewFilterSender>> =
once_cell::sync::Lazy::new(Default::default);
#[tauri::command]
fn is_autostart() -> Result<bool, String> {
let args: Vec<String> = std::env::args().collect();
println!("{:?}", args);
Ok(args.contains(&AUTOSTART_ARG.to_owned()))
}
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
fn parse_network_config(cfg: NetworkConfig) -> Result<String, String> {
@ -223,11 +230,6 @@ fn get_os_hostname() -> Result<String, String> {
Ok(gethostname::gethostname().to_string_lossy().to_string())
}
#[tauri::command]
fn set_auto_launch_status(app_handle: tauri::AppHandle, enable: bool) -> Result<bool, String> {
Ok(init_launch(&app_handle, enable).map_err(|e| e.to_string())?)
}
#[tauri::command]
fn set_logging_level(level: String) -> Result<(), String> {
let sender = unsafe { LOGGER_LEVEL_SENDER.as_ref().unwrap() };
@ -261,81 +263,19 @@ fn check_sudo() -> bool {
use std::env::current_exe;
let is_elevated = privilege::user::privileged();
if !is_elevated {
let Ok(my_exe) = current_exe() else {
let Ok(exe) = current_exe() else {
return true;
};
let mut elevated_cmd = privilege::runas::Command::new(my_exe);
let _ = elevated_cmd.force_prompt(true).gui(true).run();
let args: Vec<String> = std::env::args().collect();
let mut elevated_cmd = privilege::runas::Command::new(exe);
if args.contains(&AUTOSTART_ARG.to_owned()) {
elevated_cmd.arg(AUTOSTART_ARG);
}
let _ = elevated_cmd.force_prompt(true).hide(true).gui(true).run();
}
is_elevated
}
#[cfg(target_os = "android")]
pub fn init_launch(_app_handle: &tauri::AppHandle, _enable: bool) -> Result<bool, anyhow::Error> {
Ok(false)
}
/// init the auto launch
#[cfg(not(target_os = "android"))]
pub fn init_launch(_app_handle: &tauri::AppHandle, enable: bool) -> Result<bool, anyhow::Error> {
use std::env::current_exe;
let app_exe = current_exe()?;
let app_exe = dunce::canonicalize(app_exe)?;
let app_name = app_exe
.file_stem()
.and_then(|f| f.to_str())
.ok_or(anyhow::anyhow!("failed to get file stem"))?;
let app_path = app_exe
.as_os_str()
.to_str()
.ok_or(anyhow::anyhow!("failed to get app_path"))?
.to_string();
#[cfg(target_os = "windows")]
let app_path = format!("\"{app_path}\"");
// use the /Applications/easytier-gui.app
#[cfg(target_os = "macos")]
let app_path = (|| -> Option<String> {
let path = std::path::PathBuf::from(&app_path);
let path = path.parent()?.parent()?.parent()?;
let extension = path.extension()?.to_str()?;
match extension == "app" {
true => Some(path.as_os_str().to_str()?.to_string()),
false => None,
}
})()
.unwrap_or(app_path);
#[cfg(target_os = "linux")]
let app_path = {
let appimage = _app_handle.env().appimage;
appimage
.and_then(|p| p.to_str().map(|s| s.to_string()))
.unwrap_or(app_path)
};
let auto = AutoLaunchBuilder::new()
.set_app_name(app_name)
.set_app_path(&app_path)
.build()
.with_context(|| "failed to build auto launch")?;
if enable && !auto.is_enabled().unwrap_or(false) {
// 避免重复设置登录项
let _ = auto.disable();
auto.enable()
.with_context(|| "failed to enable auto launch")?
} else if !enable {
let _ = auto.disable();
}
let enabled = auto.is_enabled()?;
Ok(enabled)
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
#[cfg(not(target_os = "android"))]
@ -347,7 +287,18 @@ pub fn run() {
#[cfg(not(target_os = "android"))]
utils::setup_panic_handler();
tauri::Builder::default()
let mut builder = tauri::Builder::default();
#[cfg(not(target_os = "android"))]
{
use tauri_plugin_autostart::MacosLauncher;
builder = builder.plugin(tauri_plugin_autostart::init(
MacosLauncher::LaunchAgent,
Some(vec![AUTOSTART_ARG]),
));
}
builder
.plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_process::init())
@ -398,9 +349,9 @@ pub fn run() {
retain_network_instance,
collect_network_infos,
get_os_hostname,
set_auto_launch_status,
set_logging_level,
set_tun_fd
set_tun_fd,
is_autostart
])
.on_window_event(|_win, event| match event {
#[cfg(not(target_os = "android"))]

View File

@ -29,6 +29,7 @@ declare global {
const initMobileService: typeof import('./composables/mobile_vpn')['initMobileService']
const initMobileVpnService: typeof import('./composables/mobile_vpn')['initMobileVpnService']
const inject: typeof import('vue')['inject']
const isAutostart: typeof import('./composables/network')['isAutostart']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
@ -131,11 +132,11 @@ declare module 'vue' {
readonly h: UnwrapRef<typeof import('vue')['h']>
readonly initMobileVpnService: UnwrapRef<typeof import('./composables/mobile_vpn')['initMobileVpnService']>
readonly inject: UnwrapRef<typeof import('vue')['inject']>
readonly isAutostart: UnwrapRef<typeof import('./composables/network')['isAutostart']>
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
readonly loadRunningInstanceIdsFromLocalStorage: UnwrapRef<typeof import('./stores/network')['loadRunningInstanceIdsFromLocalStorage']>
readonly mapActions: UnwrapRef<typeof import('pinia')['mapActions']>
readonly mapGetters: UnwrapRef<typeof import('pinia')['mapGetters']>
readonly mapState: UnwrapRef<typeof import('pinia')['mapState']>
@ -168,7 +169,6 @@ declare module 'vue' {
readonly retainNetworkInstance: UnwrapRef<typeof import('./composables/network')['retainNetworkInstance']>
readonly runNetworkInstance: UnwrapRef<typeof import('./composables/network')['runNetworkInstance']>
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
readonly setAutoLaunchStatus: UnwrapRef<typeof import('./composables/network')['setAutoLaunchStatus']>
readonly setLoggingLevel: UnwrapRef<typeof import('./composables/network')['setLoggingLevel']>
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
readonly setTrayMenu: UnwrapRef<typeof import('./composables/tray')['setTrayMenu']>

View File

@ -22,8 +22,8 @@ export async function getOsHostname() {
return await invoke<string>('get_os_hostname')
}
export async function setAutoLaunchStatus(enable: boolean) {
return await invoke<boolean>('set_auto_launch_status', { enable })
export async function isAutostart() {
return await invoke<boolean>('is_autostart')
}
export async function setLoggingLevel(level: string) {

View File

@ -1,11 +1,12 @@
import { setAutoLaunchStatus } from "~/composables/network"
import { disable, enable, isEnabled } from '@tauri-apps/plugin-autostart'
export async function loadAutoLaunchStatusAsync(enable: boolean): Promise<boolean> {
export async function loadAutoLaunchStatusAsync(target_enable: boolean): Promise<boolean> {
try {
const ret = await setAutoLaunchStatus(enable)
localStorage.setItem('auto_launch', JSON.stringify(ret))
return ret
} catch (e) {
target_enable ? await enable() : await disable()
localStorage.setItem('auto_launch', JSON.stringify(await isEnabled()))
return isEnabled()
}
catch (e) {
console.error(e)
return false
}

View File

@ -1,21 +1,21 @@
<script setup lang="ts">
import { useToast } from 'primevue/usetoast'
import { exit } from '@tauri-apps/plugin-process';
import { exit } from '@tauri-apps/plugin-process'
import TieredMenu from 'primevue/tieredmenu'
import { open } from '@tauri-apps/plugin-shell'
import { appLogDir } from '@tauri-apps/api/path'
import { writeText } from '@tauri-apps/plugin-clipboard-manager'
import { type } from '@tauri-apps/plugin-os'
import Config from '~/components/Config.vue'
import Status from '~/components/Status.vue'
import type { NetworkConfig } from '~/types/network'
import { loadLanguageAsync } from '~/modules/i18n'
import { getAutoLaunchStatusAsync as getAutoLaunchStatus, loadAutoLaunchStatusAsync } from '~/modules/auto_launch'
import { loadRunningInstanceIdsFromLocalStorage } from '~/stores/network'
import { setLoggingLevel } from '~/composables/network'
import TieredMenu from 'primevue/tieredmenu'
import { open } from '@tauri-apps/plugin-shell';
import { appLogDir } from '@tauri-apps/api/path'
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
import { useTray } from '~/composables/tray';
import { type } from '@tauri-apps/plugin-os';
import { isAutostart, setLoggingLevel } from '~/composables/network'
import { useTray } from '~/composables/tray'
import { getCurrentWindow } from '@tauri-apps/api/window'
const { t, locale } = useI18n()
const visible = ref(false)
@ -71,7 +71,6 @@ function addNewNetwork() {
networkStore.$subscribe(async () => {
networkStore.saveToLocalStorage()
networkStore.saveRunningInstanceIdsToLocalStorage()
try {
await parseNetworkConfig(networkStore.curNetwork)
messageBarSeverity.value = Severity.None
@ -95,6 +94,7 @@ async function runNetworkCb(cfg: NetworkConfig, cb: () => void) {
try {
await runNetworkInstance(cfg)
networkStore.addAutoStartInstId(cfg.instance_id)
}
catch (e: any) {
// console.error(e)
@ -109,6 +109,7 @@ async function stopNetworkCb(cfg: NetworkConfig, cb: () => void) {
cb()
networkStore.removeNetworkInstance(cfg.instance_id)
await retainNetworkInstance(networkStore.networkInstanceIds)
networkStore.removeAutoStartInstId(cfg.instance_id)
}
async function updateNetworkInfos() {
@ -120,10 +121,13 @@ onMounted(async () => {
intervalId = window.setInterval(async () => {
await updateNetworkInfos()
}, 500)
await setTrayMenu([
await MenuItemExit(t('tray.exit')),
await MenuItemShow(t('tray.show'))
])
window.setTimeout(async () => {
await setTrayMenu([
await MenuItemExit(t('tray.exit')),
await MenuItemShow(t('tray.show')),
])
}, 1000)
})
onUnmounted(() => clearInterval(intervalId))
@ -158,10 +162,10 @@ const setting_menu_items = ref([
icon: 'pi pi-file',
items: (function () {
const levels = ['off', 'warn', 'info', 'debug', 'trace']
let items = []
for (let level of levels) {
const items = []
for (const level of levels) {
items.push({
label: () => t("logging_level_" + level) + (current_log_level === level ? ' ✓' : ''),
label: () => t(`logging_level_${level}`) + (current_log_level === level ? ' ✓' : ''),
command: async () => {
current_log_level = level
await setLoggingLevel(level)
@ -175,7 +179,7 @@ const setting_menu_items = ref([
label: () => t('logging_open_dir'),
icon: 'pi pi-folder-open',
command: async () => {
console.log("open log dir", await appLogDir())
console.log('open log dir', await appLogDir())
await open(await appLogDir())
},
})
@ -187,7 +191,7 @@ const setting_menu_items = ref([
},
})
return items
})()
})(),
},
{
label: () => t('exit'),
@ -202,18 +206,22 @@ function toggle_setting_menu(event: any) {
setting_menu.value.toggle(event)
}
onMounted(async () => {
onBeforeMount(async () => {
networkStore.loadFromLocalStorage()
if (getAutoLaunchStatus()) {
let prev_running_ids = loadRunningInstanceIdsFromLocalStorage()
for (let id of prev_running_ids) {
let cfg = networkStore.networkList.find((item) => item.instance_id === id)
if (type() !== 'android' && getAutoLaunchStatus() && await isAutostart()) {
getCurrentWindow().hide()
const autoStartIds = networkStore.autoStartInstIds
for (const id of autoStartIds) {
const cfg = networkStore.networkList.find(item => item.instance_id === id)
if (cfg) {
networkStore.addNetworkInstance(cfg.instance_id)
await runNetworkInstance(cfg)
}
}
}
})
onMounted(async () => {
if (type() === 'android') {
await initMobileVpnService()
}
@ -222,7 +230,6 @@ onMounted(async () => {
function isRunning(id: string) {
return networkStore.networkInstanceIds.includes(id)
}
</script>
<script lang="ts">
@ -275,7 +282,7 @@ function isRunning(id: string) {
<div>{{ slotProps.option.public_server_url }}</div>
<div
v-if="isRunning(slotProps.option.instance_id) && networkStore.instances[slotProps.option.instance_id].detail && (networkStore.instances[slotProps.option.instance_id].detail?.my_node_info.virtual_ipv4 !== '')">
{{ networkStore.instances[slotProps.option.instance_id].detail
{{ networkStore.instances[slotProps.option.instance_id].detail
? networkStore.instances[slotProps.option.instance_id].detail?.my_node_info.virtual_ipv4 : '' }}
</div>
</div>
@ -295,8 +302,12 @@ function isRunning(id: string) {
<Panel class="h-full overflow-y-auto">
<Stepper :value="activeStep">
<StepList value="1">
<Step value="1">{{ t('config_network') }}</Step>
<Step value="2">{{ t('running') }}</Step>
<Step value="1">
{{ t('config_network') }}
</Step>
<Step value="2">
{{ t('running') }}
</Step>
</StepList>
<StepPanels value="1">
<StepPanel v-slot="{ activateCallback = (s: string) => { } } = {}" value="1">

View File

@ -14,6 +14,8 @@ export const useNetworkStore = defineStore('networkStore', {
instances: {} as Record<string, NetworkInstance>,
networkInfos: {} as Record<string, NetworkInstanceRunningInfo>,
autoStartInstIds: [] as string[],
}
},
@ -74,7 +76,6 @@ export const useNetworkStore = defineStore('networkStore', {
this.instances[instanceId].error_msg = info.error_msg || ''
this.instances[instanceId].detail = info
}
this.saveRunningInstanceIdsToLocalStorage()
},
loadFromLocalStorage() {
@ -92,27 +93,43 @@ export const useNetworkStore = defineStore('networkStore', {
this.networkList = networkList
this.curNetwork = this.networkList[0]
this.loadAutoStartInstIdsFromLocalStorage()
},
saveToLocalStorage() {
localStorage.setItem('networkList', JSON.stringify(this.networkList))
},
saveRunningInstanceIdsToLocalStorage() {
let instance_ids = Object.keys(this.instances).filter((instanceId) => this.instances[instanceId].running)
localStorage.setItem('runningInstanceIds', JSON.stringify(instance_ids))
}
saveAutoStartInstIdsToLocalStorage() {
localStorage.setItem('autoStartInstIds', JSON.stringify(this.autoStartInstIds))
},
loadAutoStartInstIdsFromLocalStorage() {
try {
this.autoStartInstIds = JSON.parse(localStorage.getItem('autoStartInstIds') || '[]')
} catch (e) {
console.error(e)
this.autoStartInstIds = []
}
},
addAutoStartInstId(instanceId: string) {
if (!this.autoStartInstIds.includes(instanceId)) {
this.autoStartInstIds.push(instanceId)
}
this.saveAutoStartInstIdsToLocalStorage()
},
removeAutoStartInstId(instanceId: string) {
const idx = this.autoStartInstIds.indexOf(instanceId)
if (idx !== -1) {
this.autoStartInstIds.splice(idx, 1)
}
this.saveAutoStartInstIdsToLocalStorage()
},
},
})
if (import.meta.hot)
import.meta.hot.accept(acceptHMRUpdate(useNetworkStore as any, import.meta.hot))
export function loadRunningInstanceIdsFromLocalStorage(): string[] {
try {
return JSON.parse(localStorage.getItem('runningInstanceIds') || '[]')
} catch (e) {
console.error(e)
return []
}
}