Add tray controls and clean up child processes
Build Windows Portable Package / portable (release) Successful in 12m13s

This commit is contained in:
2026-09-02 02:25:18 +08:00
parent a8d803168f
commit 2bbd370e02
6 changed files with 299 additions and 21 deletions
+3
View File
@@ -39,6 +39,9 @@ export const tapTraffic = (tapDevice) => nativeCall('tap_traffic', { request: {
export const resolveTapAdapter = (tapDevice) => nativeCall('resolve_tap_adapter', { request: { tapDevice } }, () => {
throw new Error('浏览器预览无法识别 TAP 网卡')
})
export const configureTapAdapter = (request) => nativeCall('configure_tap_adapter', { request }, () => {
throw new Error('浏览器预览无法配置 TAP 网卡')
})
export const startupStatus = () => nativeCall('startup_status', {}, () => ({
configExists: false,
firstLaunch: false,
+48 -3
View File
@@ -1,11 +1,13 @@
import { useEffect, useRef, useState } from 'react'
import { createRoot } from 'react-dom/client'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { listen } from '@tauri-apps/api/event'
import {
ArrowDown, ArrowUp, CheckCircle2, ChevronDown, CircleAlert, Gauge, Globe2, Network, Play,
Download, Router, ScrollText, Server, Settings2, Square, Wifi,
} from 'lucide-react'
import {
exportLog, isTauri, openTapInstaller, readConfig, resolveTapAdapter, serviceStatus, startService,
configureTapAdapter, exportLog, isTauri, openTapInstaller, readConfig, resolveTapAdapter, serviceStatus, startService,
startupStatus, stopService, tapTraffic, writeConfig,
} from './lib/tauri'
import './styles.css'
@@ -22,6 +24,7 @@ const initialEdge = {
}
const edgeConfigStorageKey = 'super-n2n.edge-config.v1'
const isWindowsRuntime = typeof navigator !== 'undefined' && /Windows/i.test(navigator.userAgent)
function parseEdgeConfig(value) {
const fallback = { ...initialEdge }
@@ -119,6 +122,38 @@ function App() {
return () => { active = false }
}, [])
useEffect(() => {
if (!isTauri) return undefined
let active = true
let unlistenConnect
let unlistenDisconnect
let unlistenStopped
const bindTrayEvents = async () => {
unlistenConnect = await listen('tray-connect', async () => {
if (!active) return
await getCurrentWindow().show()
await getCurrentWindow().setFocus()
if (!edgeRunning) await toggleEdge()
})
unlistenDisconnect = await listen('tray-disconnect', async () => {
if (!active || !edgeRunning) return
await toggleEdge()
})
unlistenStopped = await listen('tray-service-stopped', () => {
if (!active) return
setEdgeRunning(false)
setActiveTapDevice('')
})
}
bindTrayEvents()
return () => {
active = false
unlistenConnect?.()
unlistenDisconnect?.()
unlistenStopped?.()
}
}, [edgeRunning, edge])
useEffect(() => {
let active = true
serviceStatus('edge')
@@ -203,10 +238,18 @@ function App() {
try {
const tapAdapter = await resolveTapAdapter(edge.tapDevice)
appendLog('已选择 TAP 设备:' + tapAdapter.name)
if (isWindowsRuntime) {
await configureTapAdapter({
tapDevice: tapAdapter.guid || tapAdapter.name,
dhcp: edge.dhcp,
ip: edge.ip,
})
appendLog('已配置 TAP 网卡地址', 'success')
}
const status = await startService({
service: 'edge',
binaryPath: './n2n/edge.exe',
args: buildEdgeArgs(edge, tapAdapter.name),
args: buildEdgeArgs(edge, tapAdapter.guid || tapAdapter.name),
})
setEdgeRunning(Boolean(status.running))
setActiveTapDevice(tapAdapter.name)
@@ -444,7 +487,9 @@ function buildEdgeArgs(config, tapDevice) {
addOption(args, '-d', tapDevice)
addOption(args, '-t', config.managementPort)
if (config.encryptionKey) addOption(args, '-k', config.encryptionKey)
args.push('-f', '-v', '-v')
// Windows edge does not implement the POSIX-only -f daemon flag.
if (!isWindowsRuntime) args.push('-f')
args.push('-v', '-v')
return args
}