mirror of
https://mirror.suhoan.cn/https://github.com/EasyTier/EasyTier.git
synced 2025-12-13 05:07:23 +08:00
Compare commits
3 Commits
67cba2c326
...
ae6d929f4a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae6d929f4a | ||
|
|
bb82b3a5b0 | ||
|
|
70b122fb91 |
@@ -24,8 +24,7 @@ impl Command {
|
||||
/// Prompting the user with a graphical OS dialog for the root password,
|
||||
/// excuting the command with escalated privileges, and return the output
|
||||
pub fn output(&self) -> Result<Output> {
|
||||
let pkexec = PathBuf::from_str("/bin/pkexec")?;
|
||||
let mut command = StdCommand::new(pkexec);
|
||||
let mut command = StdCommand::new("pkexec");
|
||||
let display = env::var("DISPLAY");
|
||||
let xauthority = env::var("XAUTHORITY");
|
||||
let home = env::var("HOME");
|
||||
|
||||
@@ -113,6 +113,39 @@ async fn run_network_instance(
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
if let Some(instance_manager) = INSTANCE_MANAGER.read().await.as_ref() {
|
||||
let instance_uuid = instance_id
|
||||
.parse::<uuid::Uuid>()
|
||||
.map_err(|e| e.to_string())?;
|
||||
if let Some(instance_ref) = instance_manager
|
||||
.iter()
|
||||
.find(|item| *item.key() == instance_uuid)
|
||||
{
|
||||
if let Some(mut event_receiver) = instance_ref.value().subscribe_event() {
|
||||
let app_clone = app.clone();
|
||||
let instance_id_clone = instance_id.clone();
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
match event_receiver.recv().await {
|
||||
Ok(event) => {
|
||||
if let easytier::common::global_ctx::GlobalCtxEvent::DhcpIpv4Changed(_, _) = event {
|
||||
let _ = app_clone.emit("dhcp_ip_changed", instance_id_clone.clone());
|
||||
}
|
||||
}
|
||||
Err(tokio::sync::broadcast::error::RecvError::Closed) => {
|
||||
break;
|
||||
}
|
||||
Err(tokio::sync::broadcast::error::RecvError::Lagged(_)) => {
|
||||
event_receiver = event_receiver.resubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.emit("post_run_network_instance", instance_id)
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
@@ -392,19 +425,25 @@ async fn is_client_running() -> Result<bool, String> {
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn toggle_window_visibility<R: tauri::Runtime>(app: &tauri::AppHandle<R>) {
|
||||
fn toggle_window_visibility(app: &tauri::AppHandle) {
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
if window.is_visible().unwrap_or_default() {
|
||||
let visible = if window.is_visible().unwrap_or_default() {
|
||||
if window.is_minimized().unwrap_or_default() {
|
||||
let _ = window.unminimize();
|
||||
let _ = window.set_focus();
|
||||
false
|
||||
} else {
|
||||
let _ = window.hide();
|
||||
true
|
||||
}
|
||||
} else {
|
||||
let _ = window.show();
|
||||
false
|
||||
};
|
||||
if visible {
|
||||
let _ = window.hide();
|
||||
} else {
|
||||
let _ = window.set_focus();
|
||||
}
|
||||
let _ = set_dock_visibility(app.clone(), !visible);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,7 +676,8 @@ mod manager {
|
||||
app: &AppHandle,
|
||||
) -> Result<(), easytier::rpc_service::remote_client::RemoteClientError<anyhow::Error>>
|
||||
{
|
||||
for inst_id in self.get_enabled_instances_with_tun_ids() {
|
||||
let inst_ids: Vec<uuid::Uuid> = self.get_enabled_instances_with_tun_ids().collect();
|
||||
for inst_id in inst_ids {
|
||||
self.handle_update_network_state(app.clone(), inst_id, true)
|
||||
.await?;
|
||||
}
|
||||
@@ -892,7 +932,7 @@ pub fn run_gui() -> std::process::ExitCode {
|
||||
.icon(tauri::image::Image::from_bytes(include_bytes!(
|
||||
"../icons/icon.png"
|
||||
))?)
|
||||
.icon_as_template(false)
|
||||
.icon_as_template(true)
|
||||
.build(app)?;
|
||||
|
||||
Ok(())
|
||||
@@ -924,6 +964,7 @@ pub fn run_gui() -> std::process::ExitCode {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
tauri::WindowEvent::CloseRequested { api, .. } => {
|
||||
let _ = _win.hide();
|
||||
let _ = set_dock_visibility(_win.app_handle().clone(), false);
|
||||
api.prevent_close();
|
||||
}
|
||||
_ => {}
|
||||
@@ -931,20 +972,8 @@ pub fn run_gui() -> std::process::ExitCode {
|
||||
.build(tauri::generate_context!())
|
||||
.unwrap();
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
app.run(|_app, _event| {});
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use tauri::RunEvent;
|
||||
app.run(|app, event| match event {
|
||||
RunEvent::Reopen { .. } => {
|
||||
toggle_window_visibility(app);
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
}
|
||||
|
||||
std::process::ExitCode::SUCCESS
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ const EVENTS = Object.freeze({
|
||||
PRE_RUN_NETWORK_INSTANCE: 'pre_run_network_instance',
|
||||
POST_RUN_NETWORK_INSTANCE: 'post_run_network_instance',
|
||||
VPN_SERVICE_STOP: 'vpn_service_stop',
|
||||
DHCP_IP_CHANGED: 'dhcp_ip_changed',
|
||||
});
|
||||
|
||||
function onSaveConfigs(event: Event<NetworkTypes.NetworkConfig[]>) {
|
||||
@@ -30,15 +31,23 @@ async function onVpnServiceStop(event: Event<string>) {
|
||||
await onNetworkInstanceChange(event.payload);
|
||||
}
|
||||
|
||||
async function onDhcpIpChanged(event: Event<string>) {
|
||||
console.log(`Received event '${EVENTS.DHCP_IP_CHANGED}' for instance: ${event.payload}`);
|
||||
if (type() === 'android') {
|
||||
await onNetworkInstanceChange(event.payload);
|
||||
}
|
||||
}
|
||||
|
||||
export async function listenGlobalEvents() {
|
||||
const unlisteners = [
|
||||
await listen(EVENTS.SAVE_CONFIGS, onSaveConfigs),
|
||||
await listen(EVENTS.PRE_RUN_NETWORK_INSTANCE, onPreRunNetworkInstance),
|
||||
await listen(EVENTS.POST_RUN_NETWORK_INSTANCE, onPostRunNetworkInstance),
|
||||
await listen(EVENTS.VPN_SERVICE_STOP, onVpnServiceStop),
|
||||
await listen(EVENTS.DHCP_IP_CHANGED, onDhcpIpChanged),
|
||||
];
|
||||
|
||||
return () => {
|
||||
unlisteners.forEach(unlisten => unlisten());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ interface vpnStatus {
|
||||
dns: string | null | undefined
|
||||
}
|
||||
|
||||
let dhcpPollingTimer: NodeJS.Timeout | null = null
|
||||
const DHCP_POLLING_INTERVAL = 2000 // 2秒后重试
|
||||
|
||||
const curVpnStatus: vpnStatus = {
|
||||
running: false,
|
||||
ipv4Addr: undefined,
|
||||
@@ -125,6 +128,12 @@ function getRoutesForVpn(routes: Route[], node_config: NetworkTypes.NetworkConfi
|
||||
|
||||
export async function onNetworkInstanceChange(instanceId: string) {
|
||||
console.error('vpn service network instance change id', instanceId)
|
||||
|
||||
if (dhcpPollingTimer) {
|
||||
clearTimeout(dhcpPollingTimer)
|
||||
dhcpPollingTimer = null
|
||||
}
|
||||
|
||||
if (!instanceId) {
|
||||
await doStopVpn()
|
||||
return
|
||||
@@ -140,6 +149,15 @@ export async function onNetworkInstanceChange(instanceId: string) {
|
||||
}
|
||||
|
||||
const virtual_ip = Utils.ipv4ToString(curNetworkInfo?.my_node_info?.virtual_ipv4.address)
|
||||
|
||||
if (config.dhcp && (!virtual_ip || !virtual_ip.length)) {
|
||||
console.log('DHCP enabled but no IP yet, will retry in', DHCP_POLLING_INTERVAL, 'ms')
|
||||
dhcpPollingTimer = setTimeout(() => {
|
||||
onNetworkInstanceChange(instanceId)
|
||||
}, DHCP_POLLING_INTERVAL)
|
||||
return
|
||||
}
|
||||
|
||||
if (!virtual_ip || !virtual_ip.length) {
|
||||
await doStopVpn()
|
||||
return
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
|
||||
export async function loadDockVisibilityAsync(visible: boolean): Promise<boolean> {
|
||||
try {
|
||||
await invoke('set_dock_visibility', { visible })
|
||||
localStorage.setItem('dock_visibility', JSON.stringify(visible))
|
||||
return visible
|
||||
}
|
||||
catch (e) {
|
||||
console.error('Failed to set dock visibility:', e)
|
||||
return getDockVisibilityStatus()
|
||||
}
|
||||
}
|
||||
|
||||
export function getDockVisibilityStatus(): boolean {
|
||||
const stored = localStorage.getItem('dock_visibility')
|
||||
return stored !== null ? JSON.parse(stored) : true
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import type { MenuItem } from 'primevue/menuitem'
|
||||
import { useTray } from '~/composables/tray'
|
||||
import { GUIRemoteClient } from '~/modules/api'
|
||||
|
||||
import { getDockVisibilityStatus, loadDockVisibilityAsync } from '~/modules/dock_visibility'
|
||||
import { useToast, useConfirm } from 'primevue'
|
||||
import { loadMode, saveMode, type Mode } from '~/composables/mode'
|
||||
import ModeSwitcher from '~/components/ModeSwitcher.vue'
|
||||
@@ -263,14 +262,6 @@ const setting_menu_items: Ref<MenuItem[]> = ref([
|
||||
command: openModeDialog,
|
||||
visible: () => type() !== 'android',
|
||||
},
|
||||
{
|
||||
label: () => getDockVisibilityStatus() ? t('hide_dock_icon') : t('show_dock_icon'),
|
||||
icon: 'pi pi-eye-slash',
|
||||
command: async () => {
|
||||
await loadDockVisibilityAsync(!getDockVisibilityStatus())
|
||||
},
|
||||
visible: () => type() === 'macos',
|
||||
},
|
||||
{
|
||||
key: 'logging_menu',
|
||||
label: () => t('logging'),
|
||||
|
||||
Reference in New Issue
Block a user