migrate to tauri2 (#159)

migrate gui to tauri2
This commit is contained in:
Sijie.Sun
2024-07-08 23:18:10 +08:00
committed by GitHub
parent 537f6ecf78
commit 4938e3ed2b
71 changed files with 3214 additions and 2277 deletions
+3 -1
View File
@@ -136,9 +136,11 @@ jobs:
sudo dpkg --add-architecture arm64 sudo dpkg --add-architecture arm64
sudo apt-get update && sudo apt-get upgrade -y sudo apt-get update && sudo apt-get upgrade -y
sudo apt install libwebkit2gtk-4.0-dev:arm64 sudo apt install gcc-aarch64-linux-gnu
sudo apt install libwebkit2gtk-4.1-dev:arm64
sudo apt install libssl-dev:arm64 sudo apt install libssl-dev:arm64
echo "PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu/" >> "$GITHUB_ENV" echo "PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu/" >> "$GITHUB_ENV"
echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig/" >> "$GITHUB_ENV"
- name: Build GUI - name: Build GUI
if: ${{ matrix.GUI_TARGET != '' }} if: ${{ matrix.GUI_TARGET != '' }}
+7 -7
View File
@@ -8,18 +8,18 @@
# dependencies are only needed on ubuntu as that's the only place where # dependencies are only needed on ubuntu as that's the only place where
# we make cross-compilation # we make cross-compilation
if [[ $OS =~ ^ubuntu.*$ ]]; then if [[ $OS =~ ^ubuntu.*$ ]]; then
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools libappindicator3-dev
# for easytier-gui # for easytier-gui
if [[ $GUI_TARGET != '' ]]; then if [[ $GUI_TARGET != '' && $GUI_TARGET =~ ^x86_64.*$ ]]; then
sudo apt install libwebkit2gtk-4.0-dev \ sudo apt install -qq libwebkit2gtk-4.1-dev \
build-essential \ build-essential \
curl \ curl \
wget \ wget \
file \ file \
libssl-dev \
libgtk-3-dev \ libgtk-3-dev \
libayatana-appindicator3-dev \
librsvg2-dev \ librsvg2-dev \
libxdo-dev \
libssl-dev \
patchelf patchelf
fi fi
# curl -s musl.cc | grep mipsel # curl -s musl.cc | grep mipsel
@@ -57,8 +57,8 @@ fi
# see https://github.com/rust-lang/rustup/issues/3709 # see https://github.com/rust-lang/rustup/issues/3709
rustup set auto-self-update disable rustup set auto-self-update disable
rustup install 1.75 rustup install 1.79
rustup default 1.75 rustup default 1.79
# mips/mipsel cannot add target from rustup, need compile by ourselves # mips/mipsel cannot add target from rustup, need compile by ourselves
if [[ $OS =~ ^ubuntu.*$ && $TARGET =~ ^mips.*$ ]]; then if [[ $OS =~ ^ubuntu.*$ && $TARGET =~ ^mips.*$ ]]; then
Generated
+1093 -629
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -71,3 +71,7 @@ stop_network: 停止网络
network_running: 运行中 network_running: 运行中
network_stopped: 已停止 network_stopped: 已停止
dhcp_experimental_warning: 实验性警告!使用DHCP时如果组网环境中发生IP冲突,将自动更改IP。 dhcp_experimental_warning: 实验性警告!使用DHCP时如果组网环境中发生IP冲突,将自动更改IP。
tray:
show: 显示 / 隐藏
exit: 退出
+4
View File
@@ -71,3 +71,7 @@ stop_network: Stop Network
network_running: running network_running: running
network_stopped: stopped network_stopped: stopped
dhcp_experimental_warning: Experimental warning! if there is an IP conflict in the network when using DHCP, the IP will be automatically changed. dhcp_experimental_warning: Experimental warning! if there is an IP conflict in the network when using DHCP, the IP will be automatically changed.
tray:
show: Show / Hide
exit: Exit
+27 -21
View File
@@ -1,7 +1,7 @@
{ {
"name": "easytier-gui", "name": "easytier-gui",
"type": "module", "type": "module",
"version": "0.0.0", "version": "1.2.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -12,39 +12,45 @@
"lint:fix": "eslint . --ignore-pattern src-tauri --fix" "lint:fix": "eslint . --ignore-pattern src-tauri --fix"
}, },
"dependencies": { "dependencies": {
"@tauri-apps/api": "^1.5.5", "@primevue/themes": "^4.0.0",
"@tauri-apps/plugin-clipboard-manager": "2.1.0-beta.4",
"@tauri-apps/plugin-process": "2.0.0-beta.6",
"@tauri-apps/plugin-shell": "2.0.0-beta.7",
"aura": "link:@primevue/themes/aura",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"primeflex": "^3.3.1", "primeflex": "^3.3.1",
"primeicons": "^7.0.0", "primeicons": "^7.0.0",
"primevue": "^3.52.0", "primevue": "^4.0.0",
"vue": "^3.4.27", "vue": "^3.4.31",
"vue-i18n": "^9.13.1", "vue-i18n": "^9.13.1",
"vue-router": "^4.3.2" "vue-router": "^4.4.0"
}, },
"devDependencies": { "devDependencies": {
"@antfu/eslint-config": "^2.17.0", "@antfu/eslint-config": "^2.21.3",
"@intlify/unplugin-vue-i18n": "^4.0.0", "@intlify/unplugin-vue-i18n": "^4.0.0",
"@tauri-apps/cli": "^1.5.13", "@primevue/auto-import-resolver": "^4.0.0",
"@types/node": "^20.12.11", "@tauri-apps/api": "2.0.0-beta.14",
"@tauri-apps/cli": "2.0.0-beta.21",
"@types/node": "^20.14.10",
"@types/uuid": "^9.0.8", "@types/uuid": "^9.0.8",
"@vitejs/plugin-vue": "^5.0.4", "@vitejs/plugin-vue": "^5.0.5",
"@vue-macros/volar": "^0.19.0", "@vue-macros/volar": "^0.19.1",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"eslint": "^9.2.0", "eslint": "^9.6.0",
"eslint-plugin-format": "^0.1.1", "eslint-plugin-format": "^0.1.2",
"postcss": "^8.4.38", "postcss": "^8.4.39",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.4",
"typescript": "^5.4.5", "typescript": "^5.5.3",
"unplugin-auto-import": "^0.17.6", "unplugin-auto-import": "^0.17.6",
"unplugin-vue-components": "^0.27.0", "unplugin-vue-components": "^0.27.2",
"unplugin-vue-macros": "^2.9.2", "unplugin-vue-macros": "^2.9.5",
"unplugin-vue-markdown": "^0.26.2", "unplugin-vue-markdown": "^0.26.2",
"unplugin-vue-router": "^0.8.6", "unplugin-vue-router": "^0.8.8",
"uuid": "^9.0.1", "uuid": "^9.0.1",
"vite": "^5.2.11", "vite": "^5.3.3",
"vite-plugin-vue-devtools": "^7.1.3", "vite-plugin-vue-devtools": "^7.3.5",
"vite-plugin-vue-layouts": "^0.11.0", "vite-plugin-vue-layouts": "^0.11.0",
"vue-i18n": "^9.13.1", "vue-i18n": "^9.13.1",
"vue-tsc": "^2.0.17" "vue-tsc": "^2.0.26"
} }
} }
+1786 -1482
View File
File diff suppressed because it is too large Load Diff
+9 -7
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "easytier-gui" name = "easytier-gui"
version = "0.0.0" version = "1.2.0"
description = "EasyTier GUI" description = "EasyTier GUI"
authors = ["you"] authors = ["you"]
edition = "2021" edition = "2021"
@@ -8,14 +8,11 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies] [build-dependencies]
tauri-build = { version = "1", features = [] } tauri-build = { version = "2.0.0-beta", features = [] }
[dependencies] [dependencies]
tauri = { version = "1", features = [ "clipboard-all", "path-all", tauri = { version = "2.0.0-beta", features = [ "tray-icon", "image-png", "image-ico"] }
"process-exit",
"system-tray",
"shell-open",
] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
@@ -33,6 +30,11 @@ gethostname = "0.4.3"
auto-launch = "0.5.0" auto-launch = "0.5.0"
dunce = "1.0.4" dunce = "1.0.4"
tauri-plugin-shell = "2.0.0-beta.8"
tauri-plugin-process = "2.0.0-beta.7"
tauri-plugin-clipboard-manager = "2.1.0-beta.5"
tauri-plugin-positioner = { version = "2.0.0-beta", features = ["tray-icon"] }
[features] [features]
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!! # This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
custom-protocol = ["tauri/custom-protocol"] custom-protocol = ["tauri/custom-protocol"]
@@ -0,0 +1,41 @@
{
"identifier": "migrated",
"description": "permissions that were migrated from v1",
"local": true,
"windows": [
"main"
],
"permissions": [
"path:default",
"event:default",
"window:default",
"window:allow-is-visible",
"window:allow-show",
"window:allow-hide",
"window:allow-set-focus",
"app:default",
"resources:default",
"menu:default",
"tray:default",
"shell:allow-open",
"process:allow-exit",
"clipboard-manager:allow-read-text",
"clipboard-manager:allow-write-text",
"shell:default",
"process:default",
"clipboard-manager:default",
"tray:default",
"tray:allow-new",
"tray:allow-set-menu",
"tray:allow-set-title",
"tray:allow-remove-by-id",
"tray:allow-get-by-id",
"tray:allow-set-icon",
"tray:allow-set-icon-as-template",
"tray:allow-set-show-menu-on-left-click",
"tray:allow-set-tooltip"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+34 -42
View File
@@ -16,10 +16,7 @@ use easytier::{
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tauri::{ use tauri::Manager as _;
CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
Window,
};
#[derive(Deserialize, Serialize, PartialEq, Debug)] #[derive(Deserialize, Serialize, PartialEq, Debug)]
enum NetworkingMethod { enum NetworkingMethod {
@@ -34,6 +31,8 @@ impl Default for NetworkingMethod {
} }
} }
use tauri::tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent};
#[derive(Deserialize, Serialize, Debug, Default)] #[derive(Deserialize, Serialize, Debug, Default)]
struct NetworkConfig { struct NetworkConfig {
instance_id: String, instance_id: String,
@@ -234,12 +233,14 @@ fn set_logging_level(level: String) -> Result<(), String> {
Ok(()) Ok(())
} }
fn toggle_window_visibility(window: &Window) { fn toggle_window_visibility<R: tauri::Runtime>(app: &tauri::AppHandle<R>) {
if window.is_visible().unwrap() { if let Some(window) = app.get_webview_window("main") {
window.hide().unwrap(); if window.is_visible().unwrap_or_default() {
} else { let _ = window.hide();
window.show().unwrap(); } else {
window.set_focus().unwrap(); let _ = window.show();
let _ = window.set_focus();
}
} }
} }
@@ -319,16 +320,13 @@ fn main() {
process::exit(0); process::exit(0);
} }
let quit = CustomMenuItem::new("quit".to_string(), "退出 Quit");
let hide = CustomMenuItem::new("hide".to_string(), "显示 Show / 隐藏 Hide");
let tray_menu = SystemTrayMenu::new()
.add_item(quit)
.add_native_item(SystemTrayMenuItem::Separator)
.add_item(hide);
tauri::Builder::default() tauri::Builder::default()
.plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_shell::init())
.setup(|app| { .setup(|app| {
let Some(log_dir) = app.path_resolver().app_log_dir() else { // for logging config
let Ok(log_dir) = app.path().app_log_dir() else {
return Ok(()); return Ok(());
}; };
let config = TomlConfigLoader::default(); let config = TomlConfigLoader::default();
@@ -342,6 +340,22 @@ fn main() {
}; };
unsafe { LOGGER_LEVEL_SENDER.replace(logger_reinit) }; unsafe { LOGGER_LEVEL_SENDER.replace(logger_reinit) };
// for tray icon, menu need to be built in js
let _tray_menu = TrayIconBuilder::with_id("main")
.menu_on_left_click(false)
.on_tray_icon_event(|tray, event| {
if let TrayIconEvent::Click {
button: MouseButton::Left,
button_state: MouseButtonState::Up,
..
} = event
{
let app = tray.app_handle();
toggle_window_visibility(app);
}
})
.build(app)?;
Ok(()) Ok(())
}) })
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
@@ -353,31 +367,9 @@ fn main() {
set_auto_launch_status, set_auto_launch_status,
set_logging_level set_logging_level
]) ])
.system_tray(SystemTray::new().with_menu(tray_menu)) .on_window_event(|win, event| match event {
.on_system_tray_event(|app, event| match event {
SystemTrayEvent::DoubleClick {
position: _,
size: _,
..
} => {
let window = app.get_window("main").unwrap();
toggle_window_visibility(&window);
}
SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
"quit" => {
std::process::exit(0);
}
"hide" => {
let window = app.get_window("main").unwrap();
toggle_window_visibility(&window);
}
_ => {}
},
_ => {}
})
.on_window_event(|event| match event.event() {
tauri::WindowEvent::CloseRequested { api, .. } => { tauri::WindowEvent::CloseRequested { api, .. } => {
event.window().hide().unwrap(); let _ = win.hide();
api.prevent_close(); api.prevent_close();
} }
_ => {} _ => {}
+22 -39
View File
@@ -2,31 +2,29 @@
"build": { "build": {
"beforeDevCommand": "pnpm dev", "beforeDevCommand": "pnpm dev",
"beforeBuildCommand": "pnpm build", "beforeBuildCommand": "pnpm build",
"devPath": "http://localhost:1420", "frontendDist": "../dist",
"distDir": "../dist" "devUrl": "http://localhost:1420"
}, },
"package": { "bundle": {
"productName": "easytier-gui", "active": true,
"version": "0.0.0" "targets": "all",
"icon": [
"icons/icon.png",
"icons/icon.rgba",
"icons/icon.icns",
"icons/icon.ico"
],
"createUpdaterArtifacts": false
}, },
"tauri": { "productName": "easytier-gui",
"allowlist": { "version": "1.2.0",
"all": false, "identifier": "com.kkrainbow.easyiter-client",
"shell": { "plugins": {},
"all": false, "app": {
"open": ".*" "trayIcon": {
}, "iconPath": "icons/icon.ico",
"process": { "menuOnLeftClick": true,
"exit": true "iconAsTemplate": true
},
"path": {
"all": true
},
"clipboard": {
"all": true,
"writeText": true,
"readText": true
}
}, },
"windows": [ "windows": [
{ {
@@ -37,21 +35,6 @@
], ],
"security": { "security": {
"csp": null "csp": null
},
"systemTray": {
"iconPath": "icons/icon.ico",
"iconAsTemplate": true
},
"bundle": {
"active": true,
"targets": "all",
"identifier": "com.kkrainbow.easyiter-client",
"icon": [
"icons/icon.png",
"icons/icon.rgba",
"icons/icon.icns",
"icons/icon.ico"
]
} }
} }
} }
+9 -11
View File
@@ -1,15 +1,13 @@
{ {
"tauri": { "bundle": {
"bundle": { "externalBin": [],
"externalBin": [], "resources": [
"resources": [ "./wintun.dll",
"./wintun.dll", "./Packet.dll"
"./Packet.dll" ],
], "windows": {
"windows": { "webviewInstallMode": {
"webviewInstallMode": { "type": "embedBootstrapper"
"type": "embedBootstrapper"
}
} }
} }
} }
+22
View File
@@ -6,6 +6,9 @@
export {} export {}
declare global { declare global {
const EffectScope: typeof import('vue')['EffectScope'] const EffectScope: typeof import('vue')['EffectScope']
const MenuItemExit: typeof import('./composables/tray')['MenuItemExit']
const MenuItemShow: typeof import('./composables/tray')['MenuItemShow']
const ReinitTray: typeof import('./composables/tray')['ReinitTray']
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate'] const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
const collectNetworkInfos: typeof import('./composables/network')['collectNetworkInfos'] const collectNetworkInfos: typeof import('./composables/network')['collectNetworkInfos']
const computed: typeof import('vue')['computed'] const computed: typeof import('vue')['computed']
@@ -17,6 +20,7 @@ declare global {
const definePage: typeof import('unplugin-vue-router/runtime')['definePage'] const definePage: typeof import('unplugin-vue-router/runtime')['definePage']
const defineStore: typeof import('pinia')['defineStore'] const defineStore: typeof import('pinia')['defineStore']
const effectScope: typeof import('vue')['effectScope'] const effectScope: typeof import('vue')['effectScope']
const generateMenuItem: typeof import('./composables/tray')['generateMenuItem']
const getActivePinia: typeof import('pinia')['getActivePinia'] const getActivePinia: typeof import('pinia')['getActivePinia']
const getCurrentInstance: typeof import('vue')['getCurrentInstance'] const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope'] const getCurrentScope: typeof import('vue')['getCurrentScope']
@@ -62,6 +66,9 @@ declare global {
const setAutoLaunchStatus: typeof import('./composables/network')['setAutoLaunchStatus'] const setAutoLaunchStatus: typeof import('./composables/network')['setAutoLaunchStatus']
const setLoggingLevel: typeof import('./composables/network')['setLoggingLevel'] const setLoggingLevel: typeof import('./composables/network')['setLoggingLevel']
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix'] const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
const setTrayMenu: typeof import('./composables/tray')['setTrayMenu']
const setTrayRunState: typeof import('./composables/tray')['setTrayRunState']
const setTrayTooltip: typeof import('./composables/tray')['setTrayTooltip']
const shallowReactive: typeof import('vue')['shallowReactive'] const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly'] const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef'] const shallowRef: typeof import('vue')['shallowRef']
@@ -81,6 +88,7 @@ declare global {
const useRoute: typeof import('vue-router/auto')['useRoute'] const useRoute: typeof import('vue-router/auto')['useRoute']
const useRouter: typeof import('vue-router/auto')['useRouter'] const useRouter: typeof import('vue-router/auto')['useRouter']
const useSlots: typeof import('vue')['useSlots'] const useSlots: typeof import('vue')['useSlots']
const useTray: typeof import('./composables/tray')['useTray']
const watch: typeof import('vue')['watch'] const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect'] const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect'] const watchPostEffect: typeof import('vue')['watchPostEffect']
@@ -98,6 +106,8 @@ declare module 'vue' {
interface GlobalComponents {} interface GlobalComponents {}
interface ComponentCustomProperties { interface ComponentCustomProperties {
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly MenuItemExit: UnwrapRef<typeof import('./composables/tray')['MenuItemExit']>
readonly MenuItemShow: UnwrapRef<typeof import('./composables/tray')['MenuItemShow']>
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']> readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
readonly collectNetworkInfos: UnwrapRef<typeof import('./composables/network')['collectNetworkInfos']> readonly collectNetworkInfos: UnwrapRef<typeof import('./composables/network')['collectNetworkInfos']>
readonly computed: UnwrapRef<typeof import('vue')['computed']> readonly computed: UnwrapRef<typeof import('vue')['computed']>
@@ -109,6 +119,7 @@ declare module 'vue' {
readonly definePage: UnwrapRef<typeof import('unplugin-vue-router/runtime')['definePage']> readonly definePage: UnwrapRef<typeof import('unplugin-vue-router/runtime')['definePage']>
readonly defineStore: UnwrapRef<typeof import('pinia')['defineStore']> readonly defineStore: UnwrapRef<typeof import('pinia')['defineStore']>
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']> readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly generateMenuItem: UnwrapRef<typeof import('./composables/tray')['generateMenuItem']>
readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']> readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']>
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']> readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']> readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
@@ -154,6 +165,9 @@ declare module 'vue' {
readonly setAutoLaunchStatus: UnwrapRef<typeof import('./composables/network')['setAutoLaunchStatus']> readonly setAutoLaunchStatus: UnwrapRef<typeof import('./composables/network')['setAutoLaunchStatus']>
readonly setLoggingLevel: UnwrapRef<typeof import('./composables/network')['setLoggingLevel']> readonly setLoggingLevel: UnwrapRef<typeof import('./composables/network')['setLoggingLevel']>
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']> readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
readonly setTrayMenu: UnwrapRef<typeof import('./composables/tray')['setTrayMenu']>
readonly setTrayRunState: UnwrapRef<typeof import('./composables/tray')['setTrayRunState']>
readonly setTrayTooltip: UnwrapRef<typeof import('./composables/tray')['setTrayTooltip']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']> readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']> readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']> readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
@@ -173,6 +187,7 @@ declare module 'vue' {
readonly useRoute: UnwrapRef<typeof import('vue-router/auto')['useRoute']> readonly useRoute: UnwrapRef<typeof import('vue-router/auto')['useRoute']>
readonly useRouter: UnwrapRef<typeof import('vue-router/auto')['useRouter']> readonly useRouter: UnwrapRef<typeof import('vue-router/auto')['useRouter']>
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']> readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
readonly useTray: UnwrapRef<typeof import('./composables/tray')['useTray']>
readonly watch: UnwrapRef<typeof import('vue')['watch']> readonly watch: UnwrapRef<typeof import('vue')['watch']>
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']> readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']> readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
@@ -183,6 +198,8 @@ declare module '@vue/runtime-core' {
interface GlobalComponents {} interface GlobalComponents {}
interface ComponentCustomProperties { interface ComponentCustomProperties {
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly MenuItemExit: UnwrapRef<typeof import('./composables/tray')['MenuItemExit']>
readonly MenuItemShow: UnwrapRef<typeof import('./composables/tray')['MenuItemShow']>
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']> readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
readonly collectNetworkInfos: UnwrapRef<typeof import('./composables/network')['collectNetworkInfos']> readonly collectNetworkInfos: UnwrapRef<typeof import('./composables/network')['collectNetworkInfos']>
readonly computed: UnwrapRef<typeof import('vue')['computed']> readonly computed: UnwrapRef<typeof import('vue')['computed']>
@@ -194,6 +211,7 @@ declare module '@vue/runtime-core' {
readonly definePage: UnwrapRef<typeof import('unplugin-vue-router/runtime')['definePage']> readonly definePage: UnwrapRef<typeof import('unplugin-vue-router/runtime')['definePage']>
readonly defineStore: UnwrapRef<typeof import('pinia')['defineStore']> readonly defineStore: UnwrapRef<typeof import('pinia')['defineStore']>
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']> readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly generateMenuItem: UnwrapRef<typeof import('./composables/tray')['generateMenuItem']>
readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']> readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']>
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']> readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']> readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
@@ -239,6 +257,9 @@ declare module '@vue/runtime-core' {
readonly setAutoLaunchStatus: UnwrapRef<typeof import('./composables/network')['setAutoLaunchStatus']> readonly setAutoLaunchStatus: UnwrapRef<typeof import('./composables/network')['setAutoLaunchStatus']>
readonly setLoggingLevel: UnwrapRef<typeof import('./composables/network')['setLoggingLevel']> readonly setLoggingLevel: UnwrapRef<typeof import('./composables/network')['setLoggingLevel']>
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']> readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
readonly setTrayMenu: UnwrapRef<typeof import('./composables/tray')['setTrayMenu']>
readonly setTrayRunState: UnwrapRef<typeof import('./composables/tray')['setTrayRunState']>
readonly setTrayTooltip: UnwrapRef<typeof import('./composables/tray')['setTrayTooltip']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']> readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']> readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']> readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
@@ -258,6 +279,7 @@ declare module '@vue/runtime-core' {
readonly useRoute: UnwrapRef<typeof import('vue-router/auto')['useRoute']> readonly useRoute: UnwrapRef<typeof import('vue-router/auto')['useRoute']>
readonly useRouter: UnwrapRef<typeof import('vue-router/auto')['useRouter']> readonly useRouter: UnwrapRef<typeof import('vue-router/auto')['useRouter']>
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']> readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
readonly useTray: UnwrapRef<typeof import('./composables/tray')['useTray']>
readonly watch: UnwrapRef<typeof import('vue')['watch']> readonly watch: UnwrapRef<typeof import('vue')['watch']>
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']> readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']> readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
+2 -2
View File
@@ -56,12 +56,12 @@ onMounted(async () => {
<template> <template>
<div class="flex flex-column h-full"> <div class="flex flex-column h-full">
<div class="flex flex-column"> <div class="flex flex-column">
<div class="w-7/12 self-center "> <div class="w-10/12 self-center ">
<Message severity="warn"> <Message severity="warn">
{{ t('dhcp_experimental_warning') }} {{ t('dhcp_experimental_warning') }}
</Message> </Message>
</div> </div>
<div class="w-7/12 self-center "> <div class="w-10/12 self-center ">
<Panel :header="t('basic_settings')"> <Panel :header="t('basic_settings')">
<div class="flex flex-column gap-y-2"> <div class="flex flex-column gap-y-2">
<div class="flex flex-row gap-x-9 flex-wrap"> <div class="flex flex-row gap-x-9 flex-wrap">
+2 -1
View File
@@ -1,4 +1,5 @@
import { invoke } from '@tauri-apps/api/tauri' import { invoke } from "@tauri-apps/api/core"
import type { NetworkConfig, NetworkInstanceRunningInfo } from '~/types/network' import type { NetworkConfig, NetworkInstanceRunningInfo } from '~/types/network'
export async function parseNetworkConfig(cfg: NetworkConfig) { export async function parseNetworkConfig(cfg: NetworkConfig) {
+91
View File
@@ -0,0 +1,91 @@
import { getCurrent } from '@tauri-apps/api/window'
import { Menu, MenuItem, PredefinedMenuItem } from '@tauri-apps/api/menu'
import { TrayIcon } from '@tauri-apps/api/tray'
import pkg from '~/../package.json'
const DEFAULT_TRAY_NAME = 'main'
async function toggleVisibility() {
if (await getCurrent().isVisible()) {
await getCurrent().hide()
} else {
await getCurrent().show()
await getCurrent().setFocus()
}
}
export async function useTray(init: boolean = false) {
let tray = await TrayIcon.getById(DEFAULT_TRAY_NAME)
if (!tray) {
tray = await TrayIcon.new({
tooltip: `EasyTier\n${pkg.version}`,
title: `EasyTier\n${pkg.version}`,
id: DEFAULT_TRAY_NAME,
menu: await Menu.new({
id: 'main',
items: await generateMenuItem(),
}),
action: async () => {
toggleVisibility()
}
})
}
if (init) {
tray.setTooltip(`EasyTier\n${pkg.version}`)
tray.setMenuOnLeftClick(false);
tray.setMenu(await Menu.new({
id: 'main',
items: await generateMenuItem(),
}))
}
return tray
}
export async function generateMenuItem() {
return [
await MenuItemExit('Exit'),
await PredefinedMenuItem.new({ item: 'Separator' }),
await MenuItemShow('Show / Hide'),
] || []
}
export async function MenuItemExit(text: string) {
return await PredefinedMenuItem.new({
text: text,
item: 'Quit',
})
}
export async function MenuItemShow(text: string) {
return await MenuItem.new({
id: 'show',
text,
action: async () => {
await toggleVisibility();
},
})
}
export async function setTrayMenu(items: (MenuItem | PredefinedMenuItem)[] | undefined = undefined) {
const tray = await useTray()
const menu = await Menu.new({
id: 'main',
items: items || await generateMenuItem(),
})
tray.setMenu(menu)
}
export async function setTrayRunState(isRunning: boolean = false) {
const tray = await useTray()
tray.setIcon(isRunning ? 'icons/icon-inactive.ico' : 'icons/icon.ico')
}
export async function setTrayTooltip(tooltip: string) {
if (tooltip) {
const tray = await useTray()
tray.setTooltip(`EasyTier\n${pkg.version}\n${tooltip}`)
tray.setTitle(`EasyTier\n${pkg.version}\n${tooltip}`)
}
}
+10 -2
View File
@@ -6,7 +6,7 @@ import ToastService from 'primevue/toastservice'
import App from '~/App.vue' import App from '~/App.vue'
import '~/styles.css' import '~/styles.css'
import 'primevue/resources/themes/aura-light-green/theme.css' import Aura from '@primevue/themes/aura'
import 'primeicons/primeicons.css' import 'primeicons/primeicons.css'
import 'primeflex/primeflex.css' import 'primeflex/primeflex.css'
import { i18n, loadLanguageAsync } from '~/modules/i18n' import { i18n, loadLanguageAsync } from '~/modules/i18n'
@@ -41,7 +41,15 @@ async function main() {
app.use(router) app.use(router)
app.use(createPinia()) app.use(createPinia())
app.use(i18n, { useScope: 'global' }) app.use(i18n, { useScope: 'global' })
app.use(PrimeVue) app.use(PrimeVue, {
theme: {
preset: Aura,
options: {
prefix: 'p',
darkModeSelector: 'system',
cssLayer: false
}
}})
app.use(ToastService) app.use(ToastService)
app.mount('#app') app.mount('#app')
} }
+43 -31
View File
@@ -1,10 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import Stepper from 'primevue/stepper'
import StepperPanel from 'primevue/stepperpanel'
import { useToast } from 'primevue/usetoast' import { useToast } from 'primevue/usetoast'
import { exit } from '@tauri-apps/api/process' import { exit } from '@tauri-apps/plugin-process';
import Config from '~/components/Config.vue' import Config from '~/components/Config.vue'
import Status from '~/components/Status.vue' import Status from '~/components/Status.vue'
@@ -14,14 +11,17 @@ import { getAutoLaunchStatusAsync as getAutoLaunchStatus, loadAutoLaunchStatusAs
import { loadRunningInstanceIdsFromLocalStorage } from '~/stores/network' import { loadRunningInstanceIdsFromLocalStorage } from '~/stores/network'
import { setLoggingLevel } from '~/composables/network' import { setLoggingLevel } from '~/composables/network'
import TieredMenu from 'primevue/tieredmenu' import TieredMenu from 'primevue/tieredmenu'
import { open } from '@tauri-apps/api/shell' import { open } from '@tauri-apps/plugin-shell';
import { appLogDir } from '@tauri-apps/api/path' import { appLogDir } from '@tauri-apps/api/path'
import { writeText } from '@tauri-apps/api/clipboard' import { writeText } from '@tauri-apps/plugin-clipboard-manager';
import { useTray } from '~/composables/tray';
const { t, locale } = useI18n() const { t, locale } = useI18n()
const visible = ref(false) const visible = ref(false)
const tomlConfig = ref('') const tomlConfig = ref('')
useTray(true)
const items = ref([ const items = ref([
{ {
label: () => t('show_config'), label: () => t('show_config'),
@@ -81,8 +81,8 @@ networkStore.$subscribe(async () => {
} }
}) })
async function runNetworkCb(cfg: NetworkConfig, cb: (e: MouseEvent) => void) { async function runNetworkCb(cfg: NetworkConfig, cb: () => void) {
cb({} as MouseEvent) cb()
networkStore.removeNetworkInstance(cfg.instance_id) networkStore.removeNetworkInstance(cfg.instance_id)
await retainNetworkInstance(networkStore.networkInstanceIds) await retainNetworkInstance(networkStore.networkInstanceIds)
networkStore.addNetworkInstance(cfg.instance_id) networkStore.addNetworkInstance(cfg.instance_id)
@@ -96,9 +96,9 @@ async function runNetworkCb(cfg: NetworkConfig, cb: (e: MouseEvent) => void) {
} }
} }
async function stopNetworkCb(cfg: NetworkConfig, cb: (e: MouseEvent) => void) { async function stopNetworkCb(cfg: NetworkConfig, cb: () => void) {
// console.log('stopNetworkCb', cfg, cb) // console.log('stopNetworkCb', cfg, cb)
cb({} as MouseEvent) cb()
networkStore.removeNetworkInstance(cfg.instance_id) networkStore.removeNetworkInstance(cfg.instance_id)
await retainNetworkInstance(networkStore.networkInstanceIds) await retainNetworkInstance(networkStore.networkInstanceIds)
} }
@@ -108,15 +108,19 @@ async function updateNetworkInfos() {
} }
let intervalId = 0 let intervalId = 0
onMounted(() => { onMounted(async () => {
intervalId = window.setInterval(async () => { intervalId = window.setInterval(async () => {
await updateNetworkInfos() await updateNetworkInfos()
}, 500) }, 500)
await setTrayMenu([
await MenuItemExit(t('tray.exit')),
await MenuItemShow(t('tray.show'))
])
}) })
onUnmounted(() => clearInterval(intervalId)) onUnmounted(() => clearInterval(intervalId))
const activeStep = computed(() => { const activeStep = computed(() => {
return networkStore.networkInstanceIds.includes(networkStore.curNetworkId) ? 1 : 0 return networkStore.networkInstanceIds.includes(networkStore.curNetworkId) ? '2' : '1'
}) })
let current_log_level = 'off' let current_log_level = 'off'
@@ -128,6 +132,10 @@ const setting_menu_items = ref([
icon: 'pi pi-language', icon: 'pi pi-language',
command: async () => { command: async () => {
await loadLanguageAsync((locale.value === 'en' ? 'cn' : 'en')) await loadLanguageAsync((locale.value === 'en' ? 'cn' : 'en'))
await setTrayMenu([
await MenuItemExit(t('tray.exit')),
await MenuItemShow(t('tray.show'))
])
}, },
}, },
{ {
@@ -274,25 +282,29 @@ function isRunning(id: string) {
</Toolbar> </Toolbar>
</div> </div>
<Stepper class="h-full overflow-y-auto" :active-step="activeStep"> <Panel class="h-full overflow-y-auto" >
<StepperPanel :header="t('config_network')"> <Stepper :value="activeStep">
<template #content="{ nextCallback }"> <StepList value="1">
<Config :instance-id="networkStore.curNetworkId" :config-invalid="messageBarSeverity !== Severity.None" <Step value="1">{{ t('config_network') }}</Step>
@run-network="runNetworkCb($event, nextCallback)" /> <Step value="2">{{ t('running') }}</Step>
</template> </StepList>
</StepperPanel> <StepPanels value="1">
<StepperPanel :header="t('running')"> <StepPanel v-slot="{ activateCallback = (s: string) => {} } = {}" value="1">
<template #content="{ prevCallback }"> <Config :instance-id="networkStore.curNetworkId" :config-invalid="messageBarSeverity !== Severity.None"
<div class="flex flex-column"> @run-network="runNetworkCb($event, () => activateCallback('2'))" />
<Status :instance-id="networkStore.curNetworkId" /> </StepPanel>
</div> <StepPanel v-slot="{ activateCallback = (s: string) => {} } = {}" value="2">
<div class="flex pt-4 justify-content-center"> <div class="flex flex-column">
<Button :label="t('stop_network')" severity="danger" icon="pi pi-arrow-left" <Status :instance-id="networkStore.curNetworkId" />
@click="stopNetworkCb(networkStore.curNetwork, prevCallback)" /> </div>
</div> <div class="flex pt-4 justify-content-center">
</template> <Button :label="t('stop_network')" severity="danger" icon="pi pi-arrow-left"
</StepperPanel> @click="stopNetworkCb(networkStore.curNetwork, () => activateCallback('1'))" />
</Stepper> </div>
</StepPanel>
</StepPanels>
</Stepper>
</Panel>
<div> <div>
<Menubar :model="items" breakpoint="300px" /> <Menubar :model="items" breakpoint="300px" />
+1 -1
View File
@@ -37,7 +37,7 @@ export function DEFAULT_NETWORK_CONFIG(): NetworkConfig {
return { return {
instance_id: uuidv4(), instance_id: uuidv4(),
dhcp: false, dhcp: true,
virtual_ipv4: '', virtual_ipv4: '',
network_name: 'easytier', network_name: 'easytier',
network_secret: '', network_secret: '',
+1 -1
View File
@@ -9,7 +9,7 @@ import VueI18n from '@intlify/unplugin-vue-i18n/vite'
import VueDevTools from 'vite-plugin-vue-devtools' import VueDevTools from 'vite-plugin-vue-devtools'
import VueRouter from 'unplugin-vue-router/vite' import VueRouter from 'unplugin-vue-router/vite'
import { VueRouterAutoImports } from 'unplugin-vue-router' import { VueRouterAutoImports } from 'unplugin-vue-router'
import { PrimeVueResolver } from 'unplugin-vue-components/resolvers' import { PrimeVueResolver } from '@primevue/auto-import-resolver';
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig(async () => ({ export default defineConfig(async () => ({
+3
View File
@@ -1001,6 +1001,9 @@ impl PeerRouteServiceImpl {
_ => { _ => {
tracing::error!(?ret, ?my_peer_id, ?dst_peer_id, "sync_route_info failed"); tracing::error!(?ret, ?my_peer_id, ?dst_peer_id, "sync_route_info failed");
session
.need_sync_initiator_info
.store(true, Ordering::Relaxed);
} }
} }
return false; return false;