migrate to tauri2 (#159)
Some checks failed
EasyTier Core / pre_job (push) Has been cancelled
EasyTier GUI / pre_job (push) Has been cancelled
EasyTier Test / pre_job (push) Has been cancelled
EasyTier Core / build (macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (ubuntu-latest, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (ubuntu-latest, arm-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (ubuntu-latest, arm-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (ubuntu-latest, armv7-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (ubuntu-latest, armv7-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (ubuntu-latest, mips-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (ubuntu-latest, mipsel-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (ubuntu-latest, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / core-result (push) Has been cancelled
EasyTier GUI / build-gui (aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (aarch64-unknown-linux-gnu, ubuntu-latest, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (x86_64-unknown-linux-gnu, ubuntu-latest, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / gui-result (push) Has been cancelled
EasyTier Test / test (push) Has been cancelled

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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
71 changed files with 3214 additions and 2277 deletions

View File

@ -136,9 +136,11 @@ jobs:
sudo dpkg --add-architecture arm64
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
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
if: ${{ matrix.GUI_TARGET != '' }}

View File

@ -8,18 +8,18 @@
# dependencies are only needed on ubuntu as that's the only place where
# we make cross-compilation
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
if [[ $GUI_TARGET != '' ]]; then
sudo apt install libwebkit2gtk-4.0-dev \
if [[ $GUI_TARGET != '' && $GUI_TARGET =~ ^x86_64.*$ ]]; then
sudo apt install -qq libwebkit2gtk-4.1-dev \
build-essential \
curl \
wget \
file \
libssl-dev \
libgtk-3-dev \
libayatana-appindicator3-dev \
librsvg2-dev \
libxdo-dev \
libssl-dev \
patchelf
fi
# curl -s musl.cc | grep mipsel
@ -57,8 +57,8 @@ fi
# see https://github.com/rust-lang/rustup/issues/3709
rustup set auto-self-update disable
rustup install 1.75
rustup default 1.75
rustup install 1.79
rustup default 1.79
# mips/mipsel cannot add target from rustup, need compile by ourselves
if [[ $OS =~ ^ubuntu.*$ && $TARGET =~ ^mips.*$ ]]; then

1722
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -71,3 +71,7 @@ stop_network: 停止网络
network_running: 运行中
network_stopped: 已停止
dhcp_experimental_warning: 实验性警告使用DHCP时如果组网环境中发生IP冲突将自动更改IP。
tray:
show: 显示 / 隐藏
exit: 退出

View File

@ -71,3 +71,7 @@ stop_network: Stop Network
network_running: running
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.
tray:
show: Show / Hide
exit: Exit

View File

@ -1,7 +1,7 @@
{
"name": "easytier-gui",
"type": "module",
"version": "0.0.0",
"version": "1.2.0",
"private": true,
"scripts": {
"dev": "vite",
@ -12,39 +12,45 @@
"lint:fix": "eslint . --ignore-pattern src-tauri --fix"
},
"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",
"primeflex": "^3.3.1",
"primeicons": "^7.0.0",
"primevue": "^3.52.0",
"vue": "^3.4.27",
"primevue": "^4.0.0",
"vue": "^3.4.31",
"vue-i18n": "^9.13.1",
"vue-router": "^4.3.2"
"vue-router": "^4.4.0"
},
"devDependencies": {
"@antfu/eslint-config": "^2.17.0",
"@antfu/eslint-config": "^2.21.3",
"@intlify/unplugin-vue-i18n": "^4.0.0",
"@tauri-apps/cli": "^1.5.13",
"@types/node": "^20.12.11",
"@primevue/auto-import-resolver": "^4.0.0",
"@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",
"@vitejs/plugin-vue": "^5.0.4",
"@vue-macros/volar": "^0.19.0",
"@vitejs/plugin-vue": "^5.0.5",
"@vue-macros/volar": "^0.19.1",
"autoprefixer": "^10.4.19",
"eslint": "^9.2.0",
"eslint-plugin-format": "^0.1.1",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3",
"typescript": "^5.4.5",
"eslint": "^9.6.0",
"eslint-plugin-format": "^0.1.2",
"postcss": "^8.4.39",
"tailwindcss": "^3.4.4",
"typescript": "^5.5.3",
"unplugin-auto-import": "^0.17.6",
"unplugin-vue-components": "^0.27.0",
"unplugin-vue-macros": "^2.9.2",
"unplugin-vue-components": "^0.27.2",
"unplugin-vue-macros": "^2.9.5",
"unplugin-vue-markdown": "^0.26.2",
"unplugin-vue-router": "^0.8.6",
"unplugin-vue-router": "^0.8.8",
"uuid": "^9.0.1",
"vite": "^5.2.11",
"vite-plugin-vue-devtools": "^7.1.3",
"vite": "^5.3.3",
"vite-plugin-vue-devtools": "^7.3.5",
"vite-plugin-vue-layouts": "^0.11.0",
"vue-i18n": "^9.13.1",
"vue-tsc": "^2.0.17"
"vue-tsc": "^2.0.26"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package]
name = "easytier-gui"
version = "0.0.0"
version = "1.2.0"
description = "EasyTier GUI"
authors = ["you"]
edition = "2021"
@ -8,14 +8,11 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "1", features = [] }
tauri-build = { version = "2.0.0-beta", features = [] }
[dependencies]
tauri = { version = "1", features = [ "clipboard-all", "path-all",
"process-exit",
"system-tray",
"shell-open",
] }
tauri = { version = "2.0.0-beta", features = [ "tray-icon", "image-png", "image-ico"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
@ -33,6 +30,11 @@ gethostname = "0.4.3"
auto-launch = "0.5.0"
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]
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
custom-protocol = ["tauri/custom-protocol"]

View File

@ -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.

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

View File

@ -16,10 +16,7 @@ use easytier::{
};
use serde::{Deserialize, Serialize};
use tauri::{
CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
Window,
};
use tauri::Manager as _;
#[derive(Deserialize, Serialize, PartialEq, Debug)]
enum NetworkingMethod {
@ -34,6 +31,8 @@ impl Default for NetworkingMethod {
}
}
use tauri::tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent};
#[derive(Deserialize, Serialize, Debug, Default)]
struct NetworkConfig {
instance_id: String,
@ -234,12 +233,14 @@ fn set_logging_level(level: String) -> Result<(), String> {
Ok(())
}
fn toggle_window_visibility(window: &Window) {
if window.is_visible().unwrap() {
window.hide().unwrap();
} else {
window.show().unwrap();
window.set_focus().unwrap();
fn toggle_window_visibility<R: tauri::Runtime>(app: &tauri::AppHandle<R>) {
if let Some(window) = app.get_webview_window("main") {
if window.is_visible().unwrap_or_default() {
let _ = window.hide();
} else {
let _ = window.show();
let _ = window.set_focus();
}
}
}
@ -319,16 +320,13 @@ fn main() {
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()
.plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_shell::init())
.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(());
};
let config = TomlConfigLoader::default();
@ -342,6 +340,22 @@ fn main() {
};
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(())
})
.invoke_handler(tauri::generate_handler![
@ -353,31 +367,9 @@ fn main() {
set_auto_launch_status,
set_logging_level
])
.system_tray(SystemTray::new().with_menu(tray_menu))
.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() {
.on_window_event(|win, event| match event {
tauri::WindowEvent::CloseRequested { api, .. } => {
event.window().hide().unwrap();
let _ = win.hide();
api.prevent_close();
}
_ => {}

View File

@ -2,31 +2,29 @@
"build": {
"beforeDevCommand": "pnpm dev",
"beforeBuildCommand": "pnpm build",
"devPath": "http://localhost:1420",
"distDir": "../dist"
"frontendDist": "../dist",
"devUrl": "http://localhost:1420"
},
"package": {
"productName": "easytier-gui",
"version": "0.0.0"
"bundle": {
"active": true,
"targets": "all",
"icon": [
"icons/icon.png",
"icons/icon.rgba",
"icons/icon.icns",
"icons/icon.ico"
],
"createUpdaterArtifacts": false
},
"tauri": {
"allowlist": {
"all": false,
"shell": {
"all": false,
"open": ".*"
},
"process": {
"exit": true
},
"path": {
"all": true
},
"clipboard": {
"all": true,
"writeText": true,
"readText": true
}
"productName": "easytier-gui",
"version": "1.2.0",
"identifier": "com.kkrainbow.easyiter-client",
"plugins": {},
"app": {
"trayIcon": {
"iconPath": "icons/icon.ico",
"menuOnLeftClick": true,
"iconAsTemplate": true
},
"windows": [
{
@ -37,21 +35,6 @@
],
"security": {
"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"
]
}
}
}
}

View File

@ -1,15 +1,13 @@
{
"tauri": {
"bundle": {
"externalBin": [],
"resources": [
"./wintun.dll",
"./Packet.dll"
],
"windows": {
"webviewInstallMode": {
"type": "embedBootstrapper"
}
"bundle": {
"externalBin": [],
"resources": [
"./wintun.dll",
"./Packet.dll"
],
"windows": {
"webviewInstallMode": {
"type": "embedBootstrapper"
}
}
}

View File

@ -6,6 +6,9 @@
export {}
declare global {
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 collectNetworkInfos: typeof import('./composables/network')['collectNetworkInfos']
const computed: typeof import('vue')['computed']
@ -17,6 +20,7 @@ declare global {
const definePage: typeof import('unplugin-vue-router/runtime')['definePage']
const defineStore: typeof import('pinia')['defineStore']
const effectScope: typeof import('vue')['effectScope']
const generateMenuItem: typeof import('./composables/tray')['generateMenuItem']
const getActivePinia: typeof import('pinia')['getActivePinia']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
@ -62,6 +66,9 @@ declare global {
const setAutoLaunchStatus: typeof import('./composables/network')['setAutoLaunchStatus']
const setLoggingLevel: typeof import('./composables/network')['setLoggingLevel']
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 shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
@ -81,6 +88,7 @@ declare global {
const useRoute: typeof import('vue-router/auto')['useRoute']
const useRouter: typeof import('vue-router/auto')['useRouter']
const useSlots: typeof import('vue')['useSlots']
const useTray: typeof import('./composables/tray')['useTray']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
@ -98,6 +106,8 @@ declare module 'vue' {
interface GlobalComponents {}
interface ComponentCustomProperties {
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 collectNetworkInfos: UnwrapRef<typeof import('./composables/network')['collectNetworkInfos']>
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 defineStore: UnwrapRef<typeof import('pinia')['defineStore']>
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly generateMenuItem: UnwrapRef<typeof import('./composables/tray')['generateMenuItem']>
readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']>
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
@ -154,6 +165,9 @@ declare module 'vue' {
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']>
readonly setTrayRunState: UnwrapRef<typeof import('./composables/tray')['setTrayRunState']>
readonly setTrayTooltip: UnwrapRef<typeof import('./composables/tray')['setTrayTooltip']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
@ -173,6 +187,7 @@ declare module 'vue' {
readonly useRoute: UnwrapRef<typeof import('vue-router/auto')['useRoute']>
readonly useRouter: UnwrapRef<typeof import('vue-router/auto')['useRouter']>
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
readonly useTray: UnwrapRef<typeof import('./composables/tray')['useTray']>
readonly watch: UnwrapRef<typeof import('vue')['watch']>
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
@ -183,6 +198,8 @@ declare module '@vue/runtime-core' {
interface GlobalComponents {}
interface ComponentCustomProperties {
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 collectNetworkInfos: UnwrapRef<typeof import('./composables/network')['collectNetworkInfos']>
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 defineStore: UnwrapRef<typeof import('pinia')['defineStore']>
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly generateMenuItem: UnwrapRef<typeof import('./composables/tray')['generateMenuItem']>
readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']>
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
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 setLoggingLevel: UnwrapRef<typeof import('./composables/network')['setLoggingLevel']>
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 shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
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 useRouter: UnwrapRef<typeof import('vue-router/auto')['useRouter']>
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
readonly useTray: UnwrapRef<typeof import('./composables/tray')['useTray']>
readonly watch: UnwrapRef<typeof import('vue')['watch']>
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>

View File

@ -56,12 +56,12 @@ onMounted(async () => {
<template>
<div class="flex flex-column h-full">
<div class="flex flex-column">
<div class="w-7/12 self-center ">
<div class="w-10/12 self-center ">
<Message severity="warn">
{{ t('dhcp_experimental_warning') }}
</Message>
</div>
<div class="w-7/12 self-center ">
<div class="w-10/12 self-center ">
<Panel :header="t('basic_settings')">
<div class="flex flex-column gap-y-2">
<div class="flex flex-row gap-x-9 flex-wrap">

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'
export async function parseNetworkConfig(cfg: NetworkConfig) {

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}`)
}
}

View File

@ -6,7 +6,7 @@ import ToastService from 'primevue/toastservice'
import App from '~/App.vue'
import '~/styles.css'
import 'primevue/resources/themes/aura-light-green/theme.css'
import Aura from '@primevue/themes/aura'
import 'primeicons/primeicons.css'
import 'primeflex/primeflex.css'
import { i18n, loadLanguageAsync } from '~/modules/i18n'
@ -41,7 +41,15 @@ async function main() {
app.use(router)
app.use(createPinia())
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.mount('#app')
}

View File

@ -1,10 +1,7 @@
<script setup lang="ts">
import Stepper from 'primevue/stepper'
import StepperPanel from 'primevue/stepperpanel'
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 Status from '~/components/Status.vue'
@ -14,14 +11,17 @@ import { getAutoLaunchStatusAsync as getAutoLaunchStatus, loadAutoLaunchStatusAs
import { loadRunningInstanceIdsFromLocalStorage } from '~/stores/network'
import { setLoggingLevel } from '~/composables/network'
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 { writeText } from '@tauri-apps/api/clipboard'
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
import { useTray } from '~/composables/tray';
const { t, locale } = useI18n()
const visible = ref(false)
const tomlConfig = ref('')
useTray(true)
const items = ref([
{
label: () => t('show_config'),
@ -81,8 +81,8 @@ networkStore.$subscribe(async () => {
}
})
async function runNetworkCb(cfg: NetworkConfig, cb: (e: MouseEvent) => void) {
cb({} as MouseEvent)
async function runNetworkCb(cfg: NetworkConfig, cb: () => void) {
cb()
networkStore.removeNetworkInstance(cfg.instance_id)
await retainNetworkInstance(networkStore.networkInstanceIds)
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)
cb({} as MouseEvent)
cb()
networkStore.removeNetworkInstance(cfg.instance_id)
await retainNetworkInstance(networkStore.networkInstanceIds)
}
@ -108,15 +108,19 @@ async function updateNetworkInfos() {
}
let intervalId = 0
onMounted(() => {
onMounted(async () => {
intervalId = window.setInterval(async () => {
await updateNetworkInfos()
}, 500)
await setTrayMenu([
await MenuItemExit(t('tray.exit')),
await MenuItemShow(t('tray.show'))
])
})
onUnmounted(() => clearInterval(intervalId))
const activeStep = computed(() => {
return networkStore.networkInstanceIds.includes(networkStore.curNetworkId) ? 1 : 0
return networkStore.networkInstanceIds.includes(networkStore.curNetworkId) ? '2' : '1'
})
let current_log_level = 'off'
@ -128,6 +132,10 @@ const setting_menu_items = ref([
icon: 'pi pi-language',
command: async () => {
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>
</div>
<Stepper class="h-full overflow-y-auto" :active-step="activeStep">
<StepperPanel :header="t('config_network')">
<template #content="{ nextCallback }">
<Config :instance-id="networkStore.curNetworkId" :config-invalid="messageBarSeverity !== Severity.None"
@run-network="runNetworkCb($event, nextCallback)" />
</template>
</StepperPanel>
<StepperPanel :header="t('running')">
<template #content="{ prevCallback }">
<div class="flex flex-column">
<Status :instance-id="networkStore.curNetworkId" />
</div>
<div class="flex pt-4 justify-content-center">
<Button :label="t('stop_network')" severity="danger" icon="pi pi-arrow-left"
@click="stopNetworkCb(networkStore.curNetwork, prevCallback)" />
</div>
</template>
</StepperPanel>
</Stepper>
<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>
</StepList>
<StepPanels value="1">
<StepPanel v-slot="{ activateCallback = (s: string) => {} } = {}" value="1">
<Config :instance-id="networkStore.curNetworkId" :config-invalid="messageBarSeverity !== Severity.None"
@run-network="runNetworkCb($event, () => activateCallback('2'))" />
</StepPanel>
<StepPanel v-slot="{ activateCallback = (s: string) => {} } = {}" value="2">
<div class="flex flex-column">
<Status :instance-id="networkStore.curNetworkId" />
</div>
<div class="flex pt-4 justify-content-center">
<Button :label="t('stop_network')" severity="danger" icon="pi pi-arrow-left"
@click="stopNetworkCb(networkStore.curNetwork, () => activateCallback('1'))" />
</div>
</StepPanel>
</StepPanels>
</Stepper>
</Panel>
<div>
<Menubar :model="items" breakpoint="300px" />

View File

@ -37,7 +37,7 @@ export function DEFAULT_NETWORK_CONFIG(): NetworkConfig {
return {
instance_id: uuidv4(),
dhcp: false,
dhcp: true,
virtual_ipv4: '',
network_name: 'easytier',
network_secret: '',

View File

@ -9,7 +9,7 @@ import VueI18n from '@intlify/unplugin-vue-i18n/vite'
import VueDevTools from 'vite-plugin-vue-devtools'
import VueRouter from 'unplugin-vue-router/vite'
import { VueRouterAutoImports } from 'unplugin-vue-router'
import { PrimeVueResolver } from 'unplugin-vue-components/resolvers'
import { PrimeVueResolver } from '@primevue/auto-import-resolver';
// https://vitejs.dev/config/
export default defineConfig(async () => ({

View File

@ -1001,6 +1001,9 @@ impl PeerRouteServiceImpl {
_ => {
tracing::error!(?ret, ?my_peer_id, ?dst_peer_id, "sync_route_info failed");
session
.need_sync_initiator_info
.store(true, Ordering::Relaxed);
}
}
return false;