Perf/front page (#316)

* 🐳 chore: dependencies

* 🐞 fix: minor style issues

fixed background white patches in dark mode
fixed the line height of the status label, which resulted in a bloated appearance

* 🌈 style: lint

*  feat: about
This commit is contained in:
m1m1sha
2024-09-11 09:13:00 +08:00
committed by GitHub
parent 1609c97574
commit 4342be29d7
23 changed files with 1974 additions and 1526 deletions

View File

@@ -1,183 +1,184 @@
import { addPluginListener } from '@tauri-apps/api/core';
import { prepare_vpn, start_vpn, stop_vpn } from 'tauri-plugin-vpnservice-api';
import { Route } from '~/types/network';
import { addPluginListener } from '@tauri-apps/api/core'
import { prepare_vpn, start_vpn, stop_vpn } from 'tauri-plugin-vpnservice-api'
import type { Route } from '~/types/network'
const networkStore = useNetworkStore()
interface vpnStatus {
running: boolean
ipv4Addr: string | null | undefined
ipv4Cidr: number | null | undefined
routes: string[]
running: boolean
ipv4Addr: string | null | undefined
ipv4Cidr: number | null | undefined
routes: string[]
}
var curVpnStatus: vpnStatus = {
running: false,
ipv4Addr: undefined,
ipv4Cidr: undefined,
routes: []
const curVpnStatus: vpnStatus = {
running: false,
ipv4Addr: undefined,
ipv4Cidr: undefined,
routes: [],
}
async function waitVpnStatus(target_status: boolean, timeout_sec: number) {
let start_time = Date.now()
while (curVpnStatus.running !== target_status) {
if (Date.now() - start_time > timeout_sec * 1000) {
throw new Error('wait vpn status timeout')
}
await new Promise(r => setTimeout(r, 50))
const start_time = Date.now()
while (curVpnStatus.running !== target_status) {
if (Date.now() - start_time > timeout_sec * 1000) {
throw new Error('wait vpn status timeout')
}
await new Promise(r => setTimeout(r, 50))
}
}
async function doStopVpn() {
if (!curVpnStatus.running) {
return
}
console.log('stop vpn')
let stop_ret = await stop_vpn()
console.log('stop vpn', JSON.stringify((stop_ret)))
await waitVpnStatus(false, 3)
if (!curVpnStatus.running) {
return
}
console.log('stop vpn')
const stop_ret = await stop_vpn()
console.log('stop vpn', JSON.stringify((stop_ret)))
await waitVpnStatus(false, 3)
curVpnStatus.ipv4Addr = undefined
curVpnStatus.routes = []
curVpnStatus.ipv4Addr = undefined
curVpnStatus.routes = []
}
async function doStartVpn(ipv4Addr: string, cidr: number, routes: string[]) {
if (curVpnStatus.running) {
return
}
if (curVpnStatus.running) {
return
}
console.log('start vpn')
let start_ret = await start_vpn({
"ipv4Addr": ipv4Addr + '/' + cidr,
"routes": routes,
"disallowedApplications": ["com.kkrainbow.easytier"],
"mtu": 1300,
});
if (start_ret?.errorMsg?.length) {
throw new Error(start_ret.errorMsg)
}
await waitVpnStatus(true, 3)
console.log('start vpn')
const start_ret = await start_vpn({
ipv4Addr: `${ipv4Addr}/${cidr}`,
routes,
disallowedApplications: ['com.kkrainbow.easytier'],
mtu: 1300,
})
if (start_ret?.errorMsg?.length) {
throw new Error(start_ret.errorMsg)
}
await waitVpnStatus(true, 3)
curVpnStatus.ipv4Addr = ipv4Addr
curVpnStatus.routes = routes
curVpnStatus.ipv4Addr = ipv4Addr
curVpnStatus.routes = routes
}
async function onVpnServiceStart(payload: any) {
console.log('vpn service start', JSON.stringify(payload))
curVpnStatus.running = true
if (payload.fd) {
setTunFd(networkStore.networkInstanceIds[0], payload.fd)
}
console.log('vpn service start', JSON.stringify(payload))
curVpnStatus.running = true
if (payload.fd) {
setTunFd(networkStore.networkInstanceIds[0], payload.fd)
}
}
async function onVpnServiceStop(payload: any) {
console.log('vpn service stop', JSON.stringify(payload))
curVpnStatus.running = false
console.log('vpn service stop', JSON.stringify(payload))
curVpnStatus.running = false
}
async function registerVpnServiceListener() {
console.log('register vpn service listener')
await addPluginListener(
'vpnservice',
'vpn_service_start',
onVpnServiceStart
)
console.log('register vpn service listener')
await addPluginListener(
'vpnservice',
'vpn_service_start',
onVpnServiceStart,
)
await addPluginListener(
'vpnservice',
'vpn_service_stop',
onVpnServiceStop
)
await addPluginListener(
'vpnservice',
'vpn_service_stop',
onVpnServiceStop,
)
}
function getRoutesForVpn(routes: Route[]): string[] {
if (!routes) {
return []
}
if (!routes) {
return []
}
let ret = []
for (let r of routes) {
for (let cidr of r.proxy_cidrs) {
if (cidr.indexOf('/') === -1) {
cidr += '/32'
}
ret.push(cidr)
}
const ret = []
for (const r of routes) {
for (let cidr of r.proxy_cidrs) {
if (!cidr.includes('/')) {
cidr += '/32'
}
ret.push(cidr)
}
}
// sort and dedup
return Array.from(new Set(ret)).sort()
// sort and dedup
return Array.from(new Set(ret)).sort()
}
async function onNetworkInstanceChange() {
let insts = networkStore.networkInstanceIds
if (!insts) {
await doStopVpn()
return
const insts = networkStore.networkInstanceIds
if (!insts) {
await doStopVpn()
return
}
const curNetworkInfo = networkStore.networkInfos[insts[0]]
if (!curNetworkInfo || curNetworkInfo?.error_msg?.length) {
await doStopVpn()
return
}
const virtual_ip = curNetworkInfo?.node_info?.virtual_ipv4
if (!virtual_ip || !virtual_ip.length) {
await doStopVpn()
return
}
const routes = getRoutesForVpn(curNetworkInfo?.routes)
const ipChanged = virtual_ip !== curVpnStatus.ipv4Addr
const routesChanged = JSON.stringify(routes) !== JSON.stringify(curVpnStatus.routes)
if (ipChanged || routesChanged) {
console.log('virtual ip changed', JSON.stringify(curVpnStatus), virtual_ip)
try {
await doStopVpn()
}
catch (e) {
console.error(e)
}
const curNetworkInfo = networkStore.networkInfos[insts[0]]
if (!curNetworkInfo || curNetworkInfo?.error_msg?.length) {
await doStopVpn()
return
try {
await doStartVpn(virtual_ip, 24, routes)
}
const virtual_ip = curNetworkInfo?.node_info?.virtual_ipv4
if (!virtual_ip || !virtual_ip.length) {
await doStopVpn()
return
}
const routes = getRoutesForVpn(curNetworkInfo?.routes)
var ipChanged = virtual_ip !== curVpnStatus.ipv4Addr
var routesChanged = JSON.stringify(routes) !== JSON.stringify(curVpnStatus.routes)
if (ipChanged || routesChanged) {
console.log('virtual ip changed', JSON.stringify(curVpnStatus), virtual_ip)
try {
await doStopVpn()
} catch (e) {
console.error(e)
}
try {
await doStartVpn(virtual_ip, 24, routes)
} catch (e) {
console.error("start vpn failed, clear all network insts.", e)
networkStore.clearNetworkInstances()
await retainNetworkInstance(networkStore.networkInstanceIds)
}
return
catch (e) {
console.error('start vpn failed, clear all network insts.', e)
networkStore.clearNetworkInstances()
await retainNetworkInstance(networkStore.networkInstanceIds)
}
}
}
async function watchNetworkInstance() {
var subscribe_running = false
networkStore.$subscribe(async () => {
if (subscribe_running) {
return
}
subscribe_running = true
try {
await onNetworkInstanceChange()
} catch (_) {
}
subscribe_running = false
})
let subscribe_running = false
networkStore.$subscribe(async () => {
if (subscribe_running) {
return
}
subscribe_running = true
try {
await onNetworkInstanceChange()
}
catch (_) {
}
subscribe_running = false
})
}
export async function initMobileVpnService() {
await registerVpnServiceListener()
await watchNetworkInstance()
await registerVpnServiceListener()
await watchNetworkInstance()
}
export async function prepareVpnService() {
console.log('prepare vpn')
let prepare_ret = await prepare_vpn()
console.log('prepare vpn', JSON.stringify((prepare_ret)))
if (prepare_ret?.errorMsg?.length) {
throw new Error(prepare_ret.errorMsg)
}
console.log('prepare vpn')
const prepare_ret = await prepare_vpn()
console.log('prepare vpn', JSON.stringify((prepare_ret)))
if (prepare_ret?.errorMsg?.length) {
throw new Error(prepare_ret.errorMsg)
}
}

View File

@@ -1,4 +1,4 @@
import { invoke } from "@tauri-apps/api/core"
import { invoke } from '@tauri-apps/api/core'
import type { NetworkConfig, NetworkInstanceRunningInfo } from '~/types/network'
@@ -33,3 +33,7 @@ export async function setLoggingLevel(level: string) {
export async function setTunFd(instanceId: string, fd: number) {
return await invoke('set_tun_fd', { instanceId, fd })
}
export async function getEasytierVersion() {
return await invoke<string>('easytier_version')
}

View File

@@ -1,6 +1,6 @@
import { getCurrentWindow } from '@tauri-apps/api/window'
import { Menu, MenuItem, PredefinedMenuItem } from '@tauri-apps/api/menu'
import { TrayIcon } from '@tauri-apps/api/tray'
import { getCurrentWindow } from '@tauri-apps/api/window'
import pkg from '~/../package.json'
const DEFAULT_TRAY_NAME = 'main'
@@ -8,14 +8,15 @@ const DEFAULT_TRAY_NAME = 'main'
async function toggleVisibility() {
if (await getCurrentWindow().isVisible()) {
await getCurrentWindow().hide()
} else {
}
else {
await getCurrentWindow().show()
await getCurrentWindow().setFocus()
}
}
export async function useTray(init: boolean = false) {
let tray;
let tray
try {
tray = await TrayIcon.getById(DEFAULT_TRAY_NAME)
if (!tray) {
@@ -29,17 +30,18 @@ export async function useTray(init: boolean = false) {
}),
action: async () => {
toggleVisibility()
}
},
})
}
} catch (error) {
}
catch (error) {
console.warn('Error while creating tray icon:', error)
return null
}
if (init) {
tray.setTooltip(`EasyTier\n${pkg.version}`)
tray.setMenuOnLeftClick(false);
tray.setMenuOnLeftClick(false)
tray.setMenu(await Menu.new({
id: 'main',
items: await generateMenuItem(),
@@ -59,7 +61,7 @@ export async function generateMenuItem() {
export async function MenuItemExit(text: string) {
return await PredefinedMenuItem.new({
text: text,
text,
item: 'Quit',
})
}
@@ -69,14 +71,15 @@ export async function MenuItemShow(text: string) {
id: 'show',
text,
action: async () => {
await toggleVisibility();
await toggleVisibility()
},
})
}
export async function setTrayMenu(items: (MenuItem | PredefinedMenuItem)[] | undefined = undefined) {
const tray = await useTray()
if (!tray) return
if (!tray)
return
const menu = await Menu.new({
id: 'main',
items: items || await generateMenuItem(),
@@ -86,15 +89,17 @@ export async function setTrayMenu(items: (MenuItem | PredefinedMenuItem)[] | und
export async function setTrayRunState(isRunning: boolean = false) {
const tray = await useTray()
if (!tray) return
if (!tray)
return
tray.setIcon(isRunning ? 'icons/icon-inactive.ico' : 'icons/icon.ico')
}
export async function setTrayTooltip(tooltip: string) {
if (tooltip) {
const tray = await useTray()
if (!tray) return
if (!tray)
return
tray.setTooltip(`EasyTier\n${pkg.version}\n${tooltip}`)
tray.setTitle(`EasyTier\n${pkg.version}\n${tooltip}`)
}
}
}