Compare commits
77 Commits
1
.gitignore
vendored
@@ -6,3 +6,4 @@ dist-ssr
|
||||
update.json
|
||||
scripts/_env.sh
|
||||
.vscode
|
||||
.tool-version
|
||||
1
.tool-versions
Normal file
@@ -0,0 +1 @@
|
||||
nodejs 21.7.1
|
||||
52
README.md
@@ -9,33 +9,21 @@
|
||||
A Clash Meta GUI based on <a href="https://github.com/tauri-apps/tauri">Tauri</a>.
|
||||
</h3>
|
||||
|
||||
## Preview
|
||||
|
||||

|
||||
|
||||
## Install
|
||||
|
||||
Click on the corresponding link below to download the installation package. Supports Windows (x64/x86), Linux (x64/arm64) and macOS 10.15+ (intel/apple).
|
||||
请到发布页面下载对应的安装包:[Release page](https://github.com/clash-verge-rev/clash-verge-rev/releases)<br>
|
||||
Go to the [release page](https://github.com/clash-verge-rev/clash-verge-rev/releases) to download the corresponding installation package<br>
|
||||
Supports Windows (x64/x86), Linux (x64/arm64) and macOS 10.15+ (intel/apple).
|
||||
|
||||
[[Windows x64](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.5.2/Clash.Verge_1.5.2_x64-setup.exe)]
|
||||
[[Windows arm64](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.5.2/Clash.Verge_1.5.2_arm64-setup.exe)]
|
||||
### 安装说明和常见问题,请到[文档页](https://clash-verge-rev.github.io/)查看:[Doc](https://clash-verge-rev.github.io/)
|
||||
|
||||
[[macOS intel](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.5.2/Clash.Verge_1.5.2_x64.dmg)]
|
||||
[[macOS apple](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.5.2/Clash.Verge_1.5.2_aarch64.dmg)]
|
||||
---
|
||||
|
||||
[[Linux x64 AppImage](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.5.2/clash-verge_1.5.2_amd64.AppImage)]
|
||||
[[Linux x64 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.5.2/clash-verge_1.5.2_amd64.deb)]
|
||||
[[Linux arm64 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.5.2/clash-verge_1.5.2_arm64.deb)]
|
||||
|
||||
Or you can build it yourself. Supports Windows, Linux and macOS 10.15+
|
||||
|
||||
Notes: If you could not start the app on Windows, please check that you have [Webview2](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section) installed.
|
||||
|
||||
## Features
|
||||
|
||||
- Since the clash core has been removed. The project no longer maintains the clash core, but only the Clash Meta core.
|
||||
- Profiles management and enhancement (by yaml and Javascript). [Doc](https://clash-verge-rev.github.io)
|
||||
- Simple UI and supports custom theme color.
|
||||
- Built-in support [Clash.Meta(mihomo)](https://github.com/MetaCubeX/mihomo) core.
|
||||
- System proxy setting and guard.
|
||||
|
||||
#### TG Group: [@clash_verge_rev](https://t.me/clash_verge_rev)
|
||||
### TG Group: [@clash_verge_rev](https://t.me/clash_verge_rev)
|
||||
|
||||
## Promotion
|
||||
|
||||
@@ -51,15 +39,17 @@ Notes: If you could not start the app on Windows, please check that you have [We
|
||||
- 解锁流媒体及 ChatGPT
|
||||
- 官网:https://狗狗加速.com
|
||||
|
||||
## Preview
|
||||
## Features
|
||||
|
||||

|
||||
- Since the clash core has been removed. The project no longer maintains the clash core, but only the Clash Meta core.
|
||||
- Profiles management and enhancement (by yaml and Javascript). [Doc](https://clash-verge-rev.github.io)
|
||||
- Improved UI and supports custom theme color.
|
||||
- Built-in support [Clash.Meta(mihomo)](https://github.com/MetaCubeX/mihomo) core.
|
||||
- System proxy setting and guard.
|
||||
|
||||
### FAQ
|
||||
|
||||
#### 1. **macOS** "Clash Verge" is damaged and can't be opened
|
||||
|
||||
open the terminal and run `sudo xattr -r -d com.apple.quarantine /Applications/Clash\ Verge.app`
|
||||
Refer to [Doc FAQ Page](https://clash-verge-rev.github.io/faq.html)
|
||||
|
||||
## Development
|
||||
|
||||
@@ -73,14 +63,6 @@ pnpm run check
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## Todos
|
||||
|
||||
> This keng is a little big...
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This is a learning project for Rust practice.
|
||||
|
||||
## Contributions
|
||||
|
||||
Issue and PR welcome!
|
||||
|
||||
69
UPDATELOG.md
@@ -1,3 +1,72 @@
|
||||
## v1.5.8
|
||||
|
||||
### Features
|
||||
|
||||
- 优化 UI 细节
|
||||
- Linux 绘制窗口圆角
|
||||
- 开放 DevTools
|
||||
|
||||
### Bugs Fixes
|
||||
|
||||
- 修复 MacOS 下开启 Tun 内核崩溃的问题
|
||||
|
||||
---
|
||||
|
||||
## v1.5.7
|
||||
|
||||
### Features
|
||||
|
||||
- 优化 UI 各种细节
|
||||
- 提供菜单栏图标样式切换选项(单色/彩色/禁用)
|
||||
- 添加自动检查更新开关
|
||||
- MacOS 开启 Tun 模式自动修改 DNS
|
||||
- 调整可拖动区域(尝试修复触摸屏无法拖动的问题)
|
||||
|
||||
---
|
||||
|
||||
## v1.5.6
|
||||
|
||||
### Features
|
||||
|
||||
- 全新专属 Verge rev UI 界面 (by @Amnesiash) 及细节调整
|
||||
- 提供允许无效证书的开关
|
||||
- 删除不必要的快捷键
|
||||
- Provider 更新添加动画
|
||||
- Merge 支持 Provider
|
||||
- 更换订阅框的粘贴按钮,删除默认的"Remote File" Profile 名称
|
||||
- 链接菜单添加节点显示
|
||||
|
||||
### Bugs Fixes
|
||||
|
||||
- Linux 下图片显示错误
|
||||
|
||||
---
|
||||
|
||||
## v1.5.4
|
||||
|
||||
### Features
|
||||
|
||||
- 支持自定义托盘图标
|
||||
- 支持禁用代理组图标
|
||||
- 代理组显示当前代理
|
||||
- 修改 `打开面板` 快捷键为`打开/关闭面板`
|
||||
|
||||
---
|
||||
|
||||
## v1.5.3
|
||||
|
||||
### Features
|
||||
|
||||
- Tun 设置添加重置按钮
|
||||
|
||||
### Bugs Fixes
|
||||
|
||||
- Tun 设置项显示错误的问题
|
||||
- 修改一些默认值
|
||||
- 启动时不更改启动项设置
|
||||
|
||||
---
|
||||
|
||||
## v1.5.2
|
||||
|
||||
### Features
|
||||
|
||||
BIN
docs/preview.gif
|
Before Width: | Height: | Size: 6.7 MiB |
BIN
docs/preview.png
Normal file
|
After Width: | Height: | Size: 576 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clash-verge",
|
||||
"version": "1.5.2",
|
||||
"version": "1.5.8",
|
||||
"license": "GPL-3.0-only",
|
||||
"scripts": {
|
||||
"dev": "tauri dev",
|
||||
|
||||
@@ -13,20 +13,24 @@ const FORCE = process.argv.includes("--force");
|
||||
|
||||
const PLATFORM_MAP = {
|
||||
"x86_64-pc-windows-msvc": "win32",
|
||||
"i686-pc-windows-msvc": "win32",
|
||||
"aarch64-pc-windows-msvc": "win32",
|
||||
"x86_64-apple-darwin": "darwin",
|
||||
"aarch64-apple-darwin": "darwin",
|
||||
"x86_64-unknown-linux-gnu": "linux",
|
||||
"i686-unknown-linux-gnu": "linux",
|
||||
"aarch64-unknown-linux-gnu": "linux",
|
||||
"armv7-unknown-linux-gnueabihf": "linux",
|
||||
"loongarch64-unknown-linux-gnu": "linux",
|
||||
};
|
||||
const ARCH_MAP = {
|
||||
"x86_64-pc-windows-msvc": "x64",
|
||||
"i686-pc-windows-msvc": "ia32",
|
||||
"aarch64-pc-windows-msvc": "arm64",
|
||||
"x86_64-apple-darwin": "x64",
|
||||
"aarch64-apple-darwin": "arm64",
|
||||
"x86_64-unknown-linux-gnu": "x64",
|
||||
"i686-unknown-linux-gnu": "ia32",
|
||||
"aarch64-unknown-linux-gnu": "arm64",
|
||||
"armv7-unknown-linux-gnueabihf": "arm",
|
||||
"loongarch64-unknown-linux-gnu": "loong64",
|
||||
@@ -53,10 +57,12 @@ let META_ALPHA_VERSION;
|
||||
|
||||
const META_ALPHA_MAP = {
|
||||
"win32-x64": "mihomo-windows-amd64-compatible",
|
||||
"win32-ia32": "mihomo-windows-386",
|
||||
"win32-arm64": "mihomo-windows-arm64",
|
||||
"darwin-x64": "mihomo-darwin-amd64",
|
||||
"darwin-arm64": "mihomo-darwin-arm64",
|
||||
"linux-x64": "mihomo-linux-amd64-compatible",
|
||||
"linux-ia32": "mihomo-linux-386",
|
||||
"linux-arm64": "mihomo-linux-arm64",
|
||||
"linux-arm": "mihomo-linux-armv7",
|
||||
"linux-loong64": "mihomo-linux-loong64",
|
||||
@@ -97,10 +103,12 @@ let META_VERSION;
|
||||
|
||||
const META_MAP = {
|
||||
"win32-x64": "mihomo-windows-amd64-compatible",
|
||||
"win32-ia32": "mihomo-windows-386",
|
||||
"win32-arm64": "mihomo-windows-arm64",
|
||||
"darwin-x64": "mihomo-darwin-amd64",
|
||||
"darwin-arm64": "mihomo-darwin-arm64",
|
||||
"linux-x64": "mihomo-linux-amd64-compatible",
|
||||
"linux-ia32": "mihomo-linux-386",
|
||||
"linux-arm64": "mihomo-linux-arm64",
|
||||
"linux-arm": "mihomo-linux-armv7",
|
||||
"linux-loong64": "mihomo-linux-loong64",
|
||||
@@ -362,6 +370,16 @@ const resolveUninstall = () =>
|
||||
file: "uninstall-service.exe",
|
||||
downloadURL: `${SERVICE_URL}/uninstall-service.exe`,
|
||||
});
|
||||
const resolveSetDnsScript = () =>
|
||||
resolveResource({
|
||||
file: "set_dns.sh",
|
||||
downloadURL: `https://github.com/clash-verge-rev/set-dns-script/releases/download/script/set_dns.sh`,
|
||||
});
|
||||
const resolveUnSetDnsScript = () =>
|
||||
resolveResource({
|
||||
file: "unset_dns.sh",
|
||||
downloadURL: `https://github.com/clash-verge-rev/set-dns-script/releases/download/script/unset_dns.sh`,
|
||||
});
|
||||
const resolveMmdb = () =>
|
||||
resolveResource({
|
||||
file: "Country.mmdb",
|
||||
@@ -401,6 +419,8 @@ const tasks = [
|
||||
{ name: "service", func: resolveService, retry: 5, winOnly: true },
|
||||
{ name: "install", func: resolveInstall, retry: 5, winOnly: true },
|
||||
{ name: "uninstall", func: resolveUninstall, retry: 5, winOnly: true },
|
||||
{ name: "set_dns_script", func: resolveSetDnsScript, retry: 5 },
|
||||
{ name: "unset_dns_script", func: resolveUnSetDnsScript, retry: 5 },
|
||||
{ name: "mmdb", func: resolveMmdb, retry: 5 },
|
||||
{ name: "geosite", func: resolveGeosite, retry: 5 },
|
||||
{ name: "geoip", func: resolveGeoIP, retry: 5 },
|
||||
|
||||
2
src-tauri/Cargo.lock
generated
@@ -598,7 +598,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clash-verge"
|
||||
version = "1.5.2"
|
||||
version = "1.5.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"auto-launch",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "clash-verge"
|
||||
version = "1.5.2"
|
||||
version = "1.5.8"
|
||||
description = "clash verge"
|
||||
authors = ["zzzgydi", "wonfen", "MystiPanda"]
|
||||
license = "GPL-3.0-only"
|
||||
@@ -39,7 +39,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
reqwest = { version = "0.11", features = ["json", "rustls-tls"] }
|
||||
sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" }
|
||||
auto-launch = { git="https://github.com/zzzgydi/auto-launch", branch = "main" }
|
||||
tauri = { version = "1.5", features = [ "dialog-open", "notification-all", "icon-png", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all"] }
|
||||
tauri = { version = "1.5", features = [ "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
runas = "=1.0.0" # 高版本会返回错误 Status
|
||||
|
||||
@@ -9,7 +9,7 @@ use anyhow::{Context, Result};
|
||||
use serde_yaml::Mapping;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use sysproxy::Sysproxy;
|
||||
use tauri::api;
|
||||
use tauri::{api, Manager};
|
||||
type CmdResult<T = ()> = Result<T, String>;
|
||||
|
||||
#[tauri::command]
|
||||
@@ -267,6 +267,44 @@ pub async fn test_delay(url: String) -> CmdResult<u32> {
|
||||
Ok(feat::test_delay(url).await.unwrap_or(10000u32))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_app_dir() -> CmdResult<String> {
|
||||
let app_home_dir = wrap_err!(dirs::app_home_dir())?
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
Ok(app_home_dir)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn copy_icon_file(path: String, name: String) -> CmdResult<String> {
|
||||
let file_path = std::path::Path::new(&path);
|
||||
let icon_dir = wrap_err!(dirs::app_home_dir())?.join("icons");
|
||||
if !icon_dir.exists() {
|
||||
let _ = std::fs::create_dir_all(&icon_dir);
|
||||
}
|
||||
let dest_path = icon_dir.join(name);
|
||||
|
||||
if file_path.exists() {
|
||||
match std::fs::copy(file_path, &dest_path) {
|
||||
Ok(_) => Ok(dest_path.to_string_lossy().to_string()),
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
} else {
|
||||
return Err("file not found".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn open_devtools(app_handle: tauri::AppHandle) {
|
||||
if let Some(window) = app_handle.get_window("main") {
|
||||
if !window.is_devtools_open() {
|
||||
window.open_devtools();
|
||||
} else {
|
||||
window.close_devtools();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn exit_app(app_handle: tauri::AppHandle) {
|
||||
let _ = resolve::save_window_size_position(&app_handle, true);
|
||||
|
||||
@@ -32,12 +32,12 @@ impl IClashTemp {
|
||||
pub fn template() -> Self {
|
||||
let mut map = Mapping::new();
|
||||
let mut tun = Mapping::new();
|
||||
tun.insert("stack".into(), "gVisor".into());
|
||||
tun.insert("stack".into(), "gvisor".into());
|
||||
tun.insert("device".into(), "Meta".into());
|
||||
tun.insert("auto-route".into(), true.into());
|
||||
tun.insert("strict-route".into(), true.into());
|
||||
tun.insert("strict-route".into(), false.into());
|
||||
tun.insert("auto-detect-interface".into(), true.into());
|
||||
tun.insert("dns-hijack".into(), vec!["any:53", "tcp://any:53"].into());
|
||||
tun.insert("dns-hijack".into(), vec!["any:53"].into());
|
||||
tun.insert("mtu".into(), 9000.into());
|
||||
|
||||
map.insert("mixed-port".into(), 7897.into());
|
||||
|
||||
@@ -84,6 +84,12 @@ pub struct PrfOption {
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub update_interval: Option<u64>,
|
||||
|
||||
/// for `remote` profile
|
||||
/// disable certificate validation
|
||||
/// default is `false`
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub danger_accept_invalid_certs: Option<bool>,
|
||||
}
|
||||
|
||||
impl PrfOption {
|
||||
@@ -93,6 +99,7 @@ impl PrfOption {
|
||||
a.user_agent = b.user_agent.or(a.user_agent);
|
||||
a.with_proxy = b.with_proxy.or(a.with_proxy);
|
||||
a.self_proxy = b.self_proxy.or(a.self_proxy);
|
||||
a.danger_accept_invalid_certs = b.danger_accept_invalid_certs.or(a.danger_accept_invalid_certs);
|
||||
a.update_interval = b.update_interval.or(a.update_interval);
|
||||
Some(a)
|
||||
}
|
||||
@@ -170,6 +177,7 @@ impl PrfItem {
|
||||
let opt_ref = option.as_ref();
|
||||
let with_proxy = opt_ref.map_or(false, |o| o.with_proxy.unwrap_or(false));
|
||||
let self_proxy = opt_ref.map_or(false, |o| o.self_proxy.unwrap_or(false));
|
||||
let accept_invalid_certs = opt_ref.map_or(false, |o| o.danger_accept_invalid_certs.unwrap_or(false));
|
||||
let user_agent = opt_ref.and_then(|o| o.user_agent.clone());
|
||||
let update_interval = opt_ref.and_then(|o| o.update_interval);
|
||||
|
||||
@@ -216,6 +224,7 @@ impl PrfItem {
|
||||
None => "clash-verge/unknown".to_string(),
|
||||
};
|
||||
|
||||
builder = builder.danger_accept_invalid_certs(accept_invalid_certs);
|
||||
builder = builder.user_agent(user_agent.unwrap_or(version));
|
||||
|
||||
let resp = builder.build()?.get(url).send().await?;
|
||||
|
||||
@@ -36,6 +36,21 @@ pub struct IVerge {
|
||||
/// show memory info (only for Clash Meta)
|
||||
pub enable_memory_usage: Option<bool>,
|
||||
|
||||
/// enable group icon
|
||||
pub enable_group_icon: Option<bool>,
|
||||
|
||||
/// common tray icon
|
||||
pub common_tray_icon: Option<bool>,
|
||||
|
||||
/// menu icon
|
||||
pub menu_icon: Option<String>,
|
||||
|
||||
/// sysproxy tray icon
|
||||
pub sysproxy_tray_icon: Option<bool>,
|
||||
|
||||
/// tun tray icon
|
||||
pub tun_tray_icon: Option<bool>,
|
||||
|
||||
/// clash tun mode
|
||||
pub enable_tun_mode: Option<bool>,
|
||||
|
||||
@@ -78,6 +93,9 @@ pub struct IVerge {
|
||||
/// 切换代理时自动关闭连接
|
||||
pub auto_close_connection: Option<bool>,
|
||||
|
||||
/// 是否自动检查更新
|
||||
pub auto_check_update: Option<bool>,
|
||||
|
||||
/// 默认的延迟测试连接
|
||||
pub default_latency_test: Option<String>,
|
||||
|
||||
@@ -163,6 +181,11 @@ impl IVerge {
|
||||
start_page: Some("/".into()),
|
||||
traffic_graph: Some(true),
|
||||
enable_memory_usage: Some(true),
|
||||
enable_group_icon: Some(true),
|
||||
menu_icon: Some("monochrome".into()),
|
||||
common_tray_icon: Some(false),
|
||||
sysproxy_tray_icon: Some(false),
|
||||
tun_tray_icon: Some(false),
|
||||
enable_auto_launch: Some(false),
|
||||
enable_silent_start: Some(false),
|
||||
enable_system_proxy: Some(false),
|
||||
@@ -173,6 +196,7 @@ impl IVerge {
|
||||
enable_proxy_guard: Some(false),
|
||||
proxy_guard_duration: Some(30),
|
||||
auto_close_connection: Some(true),
|
||||
auto_check_update: Some(true),
|
||||
enable_builtin_enhanced: Some(true),
|
||||
auto_log_clean: Some(3),
|
||||
..Self::default()
|
||||
@@ -204,6 +228,11 @@ impl IVerge {
|
||||
patch!(startup_script);
|
||||
patch!(traffic_graph);
|
||||
patch!(enable_memory_usage);
|
||||
patch!(enable_group_icon);
|
||||
patch!(menu_icon);
|
||||
patch!(common_tray_icon);
|
||||
patch!(sysproxy_tray_icon);
|
||||
patch!(tun_tray_icon);
|
||||
|
||||
patch!(enable_tun_mode);
|
||||
patch!(enable_service_mode);
|
||||
@@ -224,6 +253,7 @@ impl IVerge {
|
||||
patch!(hotkeys);
|
||||
|
||||
patch!(auto_close_connection);
|
||||
patch!(auto_check_update);
|
||||
patch!(default_latency_test);
|
||||
patch!(default_latency_timeout);
|
||||
patch!(enable_builtin_enhanced);
|
||||
|
||||
@@ -144,10 +144,9 @@ impl CoreManager {
|
||||
|
||||
let config_path = dirs::path_to_str(&config_path)?;
|
||||
|
||||
// fix #212
|
||||
let args = match clash_core.as_str() {
|
||||
"clash-meta" => vec!["-m", "-d", app_dir, "-f", config_path],
|
||||
"clash-meta-alpha" => vec!["-m", "-d", app_dir, "-f", config_path],
|
||||
"clash-meta" => vec!["-d", app_dir, "-f", config_path],
|
||||
"clash-meta-alpha" => vec!["-d", app_dir, "-f", config_path],
|
||||
_ => vec!["-d", app_dir, "-f", config_path],
|
||||
};
|
||||
|
||||
|
||||
@@ -65,17 +65,12 @@ impl Hotkey {
|
||||
}
|
||||
|
||||
let f = match func.trim() {
|
||||
"open_dashboard" => feat::open_dashboard,
|
||||
"open_or_close_dashboard" => feat::open_or_close_dashboard,
|
||||
"clash_mode_rule" => || feat::change_clash_mode("rule".into()),
|
||||
"clash_mode_global" => || feat::change_clash_mode("global".into()),
|
||||
"clash_mode_direct" => || feat::change_clash_mode("direct".into()),
|
||||
"clash_mode_script" => || feat::change_clash_mode("script".into()),
|
||||
"toggle_system_proxy" => feat::toggle_system_proxy,
|
||||
"enable_system_proxy" => feat::enable_system_proxy,
|
||||
"disable_system_proxy" => feat::disable_system_proxy,
|
||||
"toggle_tun_mode" => feat::toggle_tun_mode,
|
||||
"enable_tun_mode" => feat::enable_tun_mode,
|
||||
"disable_tun_mode" => feat::disable_tun_mode,
|
||||
|
||||
_ => bail!("invalid function \"{func}\""),
|
||||
};
|
||||
|
||||
@@ -148,9 +148,6 @@ impl Sysopt {
|
||||
|
||||
/// init the auto launch
|
||||
pub fn init_launch(&self) -> Result<()> {
|
||||
let enable = { Config::verge().latest().enable_auto_launch };
|
||||
let enable = enable.unwrap_or(false);
|
||||
|
||||
let app_exe = current_exe()?;
|
||||
let app_exe = dunce::canonicalize(app_exe)?;
|
||||
let app_name = app_exe
|
||||
@@ -204,28 +201,6 @@ impl Sysopt {
|
||||
.set_app_path(&app_path)
|
||||
.build()?;
|
||||
|
||||
// 避免在开发时将自启动关了
|
||||
#[cfg(feature = "verge-dev")]
|
||||
if !enable {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
if enable && !auto.is_enabled().unwrap_or(false) {
|
||||
// 避免重复设置登录项
|
||||
let _ = auto.disable();
|
||||
auto.enable()?;
|
||||
} else if !enable {
|
||||
let _ = auto.disable();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
if enable {
|
||||
auto.enable()?;
|
||||
}
|
||||
|
||||
*self.auto_launch.lock() = Some(auto);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
use crate::{cmds, config::Config, feat, utils::resolve};
|
||||
use crate::{
|
||||
cmds,
|
||||
config::Config,
|
||||
feat,
|
||||
utils::{dirs, resolve},
|
||||
};
|
||||
use anyhow::Result;
|
||||
use tauri::{
|
||||
api, AppHandle, CustomMenuItem, Manager, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
|
||||
@@ -129,26 +134,47 @@ impl Tray {
|
||||
let verge = verge.latest();
|
||||
let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false);
|
||||
let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false);
|
||||
let common_tray_icon = verge.common_tray_icon.as_ref().unwrap_or(&false);
|
||||
let sysproxy_tray_icon = verge.sysproxy_tray_icon.as_ref().unwrap_or(&false);
|
||||
let tun_tray_icon = verge.tun_tray_icon.as_ref().unwrap_or(&false);
|
||||
|
||||
let mut indication_icon = if *system_proxy {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let icon = include_bytes!("../../icons/tray-icon-sys.png").to_vec();
|
||||
let mut icon = include_bytes!("../../icons/tray-icon-sys.png").to_vec();
|
||||
#[cfg(target_os = "macos")]
|
||||
let icon = include_bytes!("../../icons/mac-tray-icon-sys.png").to_vec();
|
||||
let mut icon = include_bytes!("../../icons/mac-tray-icon-sys.png").to_vec();
|
||||
if *sysproxy_tray_icon {
|
||||
let path = dirs::app_home_dir()?.join("icons").join("sysproxy.png");
|
||||
if path.exists() {
|
||||
icon = std::fs::read(path).unwrap();
|
||||
}
|
||||
}
|
||||
icon
|
||||
} else {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let icon = include_bytes!("../../icons/tray-icon.png").to_vec();
|
||||
let mut icon = include_bytes!("../../icons/tray-icon.png").to_vec();
|
||||
#[cfg(target_os = "macos")]
|
||||
let icon = include_bytes!("../../icons/mac-tray-icon.png").to_vec();
|
||||
let mut icon = include_bytes!("../../icons/mac-tray-icon.png").to_vec();
|
||||
if *common_tray_icon {
|
||||
let path = dirs::app_home_dir()?.join("icons").join("common.png");
|
||||
if path.exists() {
|
||||
icon = std::fs::read(path).unwrap();
|
||||
}
|
||||
}
|
||||
icon
|
||||
};
|
||||
|
||||
if *tun_mode {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let icon = include_bytes!("../../icons/tray-icon-tun.png").to_vec();
|
||||
let mut icon = include_bytes!("../../icons/tray-icon-tun.png").to_vec();
|
||||
#[cfg(target_os = "macos")]
|
||||
let icon = include_bytes!("../../icons/mac-tray-icon-tun.png").to_vec();
|
||||
let mut icon = include_bytes!("../../icons/mac-tray-icon-tun.png").to_vec();
|
||||
if *tun_tray_icon {
|
||||
let path = dirs::app_home_dir()?.join("icons").join("tun.png");
|
||||
if path.exists() {
|
||||
icon = std::fs::read(path).unwrap();
|
||||
}
|
||||
}
|
||||
indication_icon = icon
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
use super::{use_filter, use_lowercase};
|
||||
use serde_yaml::{self, Mapping, Sequence, Value};
|
||||
|
||||
const MERGE_FIELDS: [&str; 6] = [
|
||||
const MERGE_FIELDS: [&str; 10] = [
|
||||
"prepend-rules",
|
||||
"append-rules",
|
||||
"prepend-rule-providers",
|
||||
"append-rule-providers",
|
||||
"prepend-proxies",
|
||||
"append-proxies",
|
||||
"prepend-proxy-providers",
|
||||
"append-proxy-providers",
|
||||
"prepend-proxy-groups",
|
||||
"append-proxy-groups",
|
||||
];
|
||||
@@ -22,6 +26,39 @@ pub fn use_merge(merge: Mapping, mut config: Mapping) -> Mapping {
|
||||
let merge_list = MERGE_FIELDS.iter().map(|s| s.to_string());
|
||||
let merge = use_filter(merge, &merge_list.collect());
|
||||
|
||||
["rule-providers", "proxy-providers"]
|
||||
.iter()
|
||||
.for_each(|key_str| {
|
||||
let key_val = Value::from(key_str.to_string());
|
||||
|
||||
let mut map = Mapping::default();
|
||||
|
||||
map = config.get(&key_val).map_or(map.clone(), |val| {
|
||||
val.as_mapping().map_or(map, |v| v.clone())
|
||||
});
|
||||
|
||||
let pre_key = Value::from(format!("prepend-{key_str}"));
|
||||
let post_key = Value::from(format!("append-{key_str}"));
|
||||
|
||||
if let Some(pre_val) = merge.get(&pre_key) {
|
||||
if pre_val.is_mapping() {
|
||||
let mut pre_val = pre_val.as_mapping().unwrap().clone();
|
||||
pre_val.extend(map);
|
||||
map = pre_val;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(post_val) = merge.get(&post_key) {
|
||||
if post_val.is_mapping() {
|
||||
map.extend(post_val.as_mapping().unwrap().clone());
|
||||
}
|
||||
}
|
||||
|
||||
if !map.is_empty() {
|
||||
config.insert(key_val, Value::from(map));
|
||||
}
|
||||
});
|
||||
|
||||
["rules", "proxies", "proxy-groups"]
|
||||
.iter()
|
||||
.for_each(|key_str| {
|
||||
@@ -49,7 +86,9 @@ pub fn use_merge(merge: Mapping, mut config: Mapping) -> Mapping {
|
||||
}
|
||||
}
|
||||
|
||||
config.insert(key_val, Value::from(list));
|
||||
if !list.is_empty() {
|
||||
config.insert(key_val, Value::from(list));
|
||||
}
|
||||
});
|
||||
config
|
||||
}
|
||||
|
||||
@@ -34,8 +34,38 @@ pub fn use_tun(mut config: Mapping, enable: bool) -> Mapping {
|
||||
revise!(config, "tun", tun_val);
|
||||
|
||||
if enable {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use crate::utils::dirs;
|
||||
use tauri::api::process::Command;
|
||||
log::info!(target: "app", "try to set system dns");
|
||||
let resource_dir = dirs::app_resources_dir().unwrap();
|
||||
let script = resource_dir.join("set_dns.sh");
|
||||
let script = script.to_string_lossy();
|
||||
match Command::new("bash").args([script]).output() {
|
||||
Ok(_) => log::info!(target: "app", "set system dns successfully"),
|
||||
Err(err) => {
|
||||
log::error!(target: "app", "set system dns failed: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
use_dns_for_tun(config)
|
||||
} else {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use crate::utils::dirs;
|
||||
use tauri::api::process::Command;
|
||||
log::info!(target: "app", "try to unset system dns");
|
||||
let resource_dir = dirs::app_resources_dir().unwrap();
|
||||
let script = resource_dir.join("unset_dns.sh");
|
||||
let script = script.to_string_lossy();
|
||||
match Command::new("bash").args([script]).output() {
|
||||
Ok(_) => log::info!(target: "app", "unset system dns successfully"),
|
||||
Err(err) => {
|
||||
log::error!(target: "app", "unset system dns failed: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
config
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,19 @@ use crate::log_err;
|
||||
use crate::utils::resolve;
|
||||
use anyhow::{bail, Result};
|
||||
use serde_yaml::{Mapping, Value};
|
||||
use tauri::{AppHandle, ClipboardManager};
|
||||
use tauri::{AppHandle, ClipboardManager, Manager};
|
||||
|
||||
// 打开面板
|
||||
pub fn open_dashboard() {
|
||||
pub fn open_or_close_dashboard() {
|
||||
let handle = handle::Handle::global();
|
||||
let app_handle = handle.app_handle.lock();
|
||||
if let Some(app_handle) = app_handle.as_ref() {
|
||||
if let Some(window) = app_handle.get_window("main") {
|
||||
if let Ok(true) = window.is_focused() {
|
||||
let _ = window.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolve::create_window(app_handle);
|
||||
}
|
||||
}
|
||||
@@ -78,36 +84,6 @@ pub fn toggle_system_proxy() {
|
||||
});
|
||||
}
|
||||
|
||||
// 打开系统代理
|
||||
pub fn enable_system_proxy() {
|
||||
tauri::async_runtime::spawn(async {
|
||||
match patch_verge(IVerge {
|
||||
enable_system_proxy: Some(true),
|
||||
..IVerge::default()
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(_) => handle::Handle::refresh_verge(),
|
||||
Err(err) => log::error!(target: "app", "{err}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 关闭系统代理
|
||||
pub fn disable_system_proxy() {
|
||||
tauri::async_runtime::spawn(async {
|
||||
match patch_verge(IVerge {
|
||||
enable_system_proxy: Some(false),
|
||||
..IVerge::default()
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(_) => handle::Handle::refresh_verge(),
|
||||
Err(err) => log::error!(target: "app", "{err}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 切换tun模式
|
||||
pub fn toggle_tun_mode() {
|
||||
let enable = Config::verge().data().enable_tun_mode;
|
||||
@@ -126,36 +102,6 @@ pub fn toggle_tun_mode() {
|
||||
});
|
||||
}
|
||||
|
||||
// 打开tun模式
|
||||
pub fn enable_tun_mode() {
|
||||
tauri::async_runtime::spawn(async {
|
||||
match patch_verge(IVerge {
|
||||
enable_tun_mode: Some(true),
|
||||
..IVerge::default()
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(_) => handle::Handle::refresh_verge(),
|
||||
Err(err) => log::error!(target: "app", "{err}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 关闭tun模式
|
||||
pub fn disable_tun_mode() {
|
||||
tauri::async_runtime::spawn(async {
|
||||
match patch_verge(IVerge {
|
||||
enable_tun_mode: Some(false),
|
||||
..IVerge::default()
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(_) => handle::Handle::refresh_verge(),
|
||||
Err(err) => log::error!(target: "app", "{err}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// 修改clash的订阅
|
||||
pub async fn patch_clash(patch: Mapping) -> Result<()> {
|
||||
Config::clash().draft().patch_config(patch.clone());
|
||||
@@ -230,6 +176,9 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
|
||||
let proxy_bypass = patch.system_proxy_bypass;
|
||||
let language = patch.language;
|
||||
let port = patch.verge_mixed_port;
|
||||
let common_tray_icon = patch.common_tray_icon;
|
||||
let sysproxy_tray_icon = patch.sysproxy_tray_icon;
|
||||
let tun_tray_icon = patch.tun_tray_icon;
|
||||
|
||||
match {
|
||||
#[cfg(target_os = "windows")]
|
||||
@@ -269,7 +218,12 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
|
||||
|
||||
if language.is_some() {
|
||||
handle::Handle::update_systray()?;
|
||||
} else if system_proxy.or(tun_mode).is_some() {
|
||||
} else if system_proxy.is_some()
|
||||
|| tun_mode.is_some()
|
||||
|| common_tray_icon.is_some()
|
||||
|| sysproxy_tray_icon.is_some()
|
||||
|| tun_tray_icon.is_some()
|
||||
{
|
||||
handle::Handle::update_systray_part()?;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,9 @@ fn main() -> std::io::Result<()> {
|
||||
cmds::get_verge_config,
|
||||
cmds::patch_verge_config,
|
||||
cmds::test_delay,
|
||||
cmds::get_app_dir,
|
||||
cmds::copy_icon_file,
|
||||
cmds::open_devtools,
|
||||
cmds::exit_app,
|
||||
// cmds::update_hotkeys,
|
||||
// profile
|
||||
|
||||
@@ -141,7 +141,10 @@ pub fn create_window(app_handle: &AppHandle) {
|
||||
_ => {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
builder = builder.inner_size(800.0, 636.0).center();
|
||||
builder = builder
|
||||
.additional_browser_args("--enable-features=msWebView2EnableDraggableRegions")
|
||||
.inner_size(800.0, 636.0)
|
||||
.center();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -168,7 +171,7 @@ pub fn create_window(app_handle: &AppHandle) {
|
||||
.title_bar_style(tauri::TitleBarStyle::Overlay)
|
||||
.build();
|
||||
#[cfg(target_os = "linux")]
|
||||
let window = builder.decorations(true).transparent(false).build();
|
||||
let window = builder.decorations(false).transparent(true).build();
|
||||
|
||||
match window {
|
||||
Ok(win) => {
|
||||
@@ -243,6 +246,7 @@ pub async fn resolve_scheme(param: String) {
|
||||
user_agent: None,
|
||||
with_proxy: Some(true),
|
||||
self_proxy: None,
|
||||
danger_accept_invalid_certs: None,
|
||||
update_interval: None,
|
||||
};
|
||||
if let Ok(item) = PrfItem::from_url(url, None, None, Some(option)).await {
|
||||
|
||||
@@ -16,14 +16,22 @@ pub const ITEM_MERGE: &str = "# Merge Template for clash verge
|
||||
|
||||
prepend-rules:
|
||||
|
||||
prepend-rule-providers:
|
||||
|
||||
prepend-proxies:
|
||||
|
||||
prepend-proxy-providers:
|
||||
|
||||
prepend-proxy-groups:
|
||||
|
||||
append-rules:
|
||||
|
||||
append-rule-providers:
|
||||
|
||||
append-proxies:
|
||||
|
||||
append-proxy-providers:
|
||||
|
||||
append-proxy-groups:
|
||||
";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "Clash Verge",
|
||||
"version": "1.5.2"
|
||||
"version": "1.5.8"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
@@ -58,11 +58,18 @@
|
||||
"dialog": {
|
||||
"all": false,
|
||||
"open": true
|
||||
},
|
||||
"protocol": {
|
||||
"asset": true,
|
||||
"assetScope": ["$APPDATA/**", "$RESOURCE/../**"]
|
||||
},
|
||||
"path": {
|
||||
"all": true
|
||||
}
|
||||
},
|
||||
"windows": [],
|
||||
"security": {
|
||||
"csp": "script-src 'unsafe-eval' 'self'; default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; img-src http: https: data: 'self';"
|
||||
"csp": "script-src 'unsafe-eval' 'self'; default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; img-src asset: http: https: data: 'self';"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
src/assets/image/itemicon/connections.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="36" height="36" rx="18" fill="url(#paint0_linear_971_118)"/>
|
||||
<path d="M17.9917 9.66675C13.3917 9.66675 9.66669 13.4001 9.66669 18.0001C9.66669 22.6001 13.3917 26.3334 17.9917 26.3334C22.6 26.3334 26.3334 22.6001 26.3334 18.0001C26.3334 13.4001 22.6 9.66675 17.9917 9.66675ZM23.7667 14.6667H21.3084C21.0417 13.6251 20.6584 12.6251 20.1584 11.7001C21.6917 12.2251 22.9667 13.2917 23.7667 14.6667ZM18 11.3667C18.6917 12.3667 19.2334 13.4751 19.5917 14.6667H16.4084C16.7667 13.4751 17.3084 12.3667 18 11.3667ZM11.55 19.6667C11.4167 19.1334 11.3334 18.5751 11.3334 18.0001C11.3334 17.4251 11.4167 16.8667 11.55 16.3334H14.3667C14.3 16.8834 14.25 17.4334 14.25 18.0001C14.25 18.5667 14.3 19.1167 14.3667 19.6667H11.55ZM12.2334 21.3334H14.6917C14.9584 22.3751 15.3417 23.3751 15.8417 24.3001C14.3084 23.7751 13.0334 22.7167 12.2334 21.3334ZM14.6917 14.6667H12.2334C13.0334 13.2834 14.3084 12.2251 15.8417 11.7001C15.3417 12.6251 14.9584 13.6251 14.6917 14.6667ZM18 24.6334C17.3084 23.6334 16.7667 22.5251 16.4084 21.3334H19.5917C19.2334 22.5251 18.6917 23.6334 18 24.6334ZM19.95 19.6667H16.05C15.975 19.1167 15.9167 18.5667 15.9167 18.0001C15.9167 17.4334 15.975 16.8751 16.05 16.3334H19.95C20.025 16.8751 20.0834 17.4334 20.0834 18.0001C20.0834 18.5667 20.025 19.1167 19.95 19.6667ZM20.1584 24.3001C20.6584 23.3751 21.0417 22.3751 21.3084 21.3334H23.7667C22.9667 22.7084 21.6917 23.7751 20.1584 24.3001ZM21.6334 19.6667C21.7 19.1167 21.75 18.5667 21.75 18.0001C21.75 17.4334 21.7 16.8834 21.6334 16.3334H24.45C24.5834 16.8667 24.6667 17.4251 24.6667 18.0001C24.6667 18.5751 24.5834 19.1334 24.45 19.6667H21.6334Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_971_118" x1="31" y1="27.5" x2="6.5" y2="7" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#009038"/>
|
||||
<stop offset="1" stop-color="#1CA350"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
10
src/assets/image/itemicon/logs.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="36" height="36" rx="18" fill="url(#paint0_linear_971_127)"/>
|
||||
<path d="M18.8334 22.1667H12.1667C11.7084 22.1667 11.3334 22.5417 11.3334 23.0001C11.3334 23.4584 11.7084 23.8334 12.1667 23.8334H18.8334C19.2917 23.8334 19.6667 23.4584 19.6667 23.0001C19.6667 22.5417 19.2917 22.1667 18.8334 22.1667ZM23.8334 15.5001H12.1667C11.7084 15.5001 11.3334 15.8751 11.3334 16.3334C11.3334 16.7917 11.7084 17.1667 12.1667 17.1667H23.8334C24.2917 17.1667 24.6667 16.7917 24.6667 16.3334C24.6667 15.8751 24.2917 15.5001 23.8334 15.5001ZM12.1667 20.5001H23.8334C24.2917 20.5001 24.6667 20.1251 24.6667 19.6667C24.6667 19.2084 24.2917 18.8334 23.8334 18.8334H12.1667C11.7084 18.8334 11.3334 19.2084 11.3334 19.6667C11.3334 20.1251 11.7084 20.5001 12.1667 20.5001ZM11.3334 13.0001C11.3334 13.4584 11.7084 13.8334 12.1667 13.8334H23.8334C24.2917 13.8334 24.6667 13.4584 24.6667 13.0001C24.6667 12.5417 24.2917 12.1667 23.8334 12.1667H12.1667C11.7084 12.1667 11.3334 12.5417 11.3334 13.0001Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_971_127" x1="6" y1="6.5" x2="29.5" y2="30.5" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#E96038"/>
|
||||
<stop offset="1" stop-color="#E1451D"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
10
src/assets/image/itemicon/profiles.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="36" height="36" rx="18" fill="url(#paint0_linear_971_113)"/>
|
||||
<path d="M23.8333 18.8333H12.1667C11.25 18.8333 10.5 19.5833 10.5 20.5V23.8333C10.5 24.75 11.25 25.5 12.1667 25.5H23.8333C24.75 25.5 25.5 24.75 25.5 23.8333V20.5C25.5 19.5833 24.75 18.8333 23.8333 18.8333ZM13.8333 23.8333C12.9167 23.8333 12.1667 23.0833 12.1667 22.1667C12.1667 21.25 12.9167 20.5 13.8333 20.5C14.75 20.5 15.5 21.25 15.5 22.1667C15.5 23.0833 14.75 23.8333 13.8333 23.8333ZM23.8333 10.5H12.1667C11.25 10.5 10.5 11.25 10.5 12.1667V15.5C10.5 16.4167 11.25 17.1667 12.1667 17.1667H23.8333C24.75 17.1667 25.5 16.4167 25.5 15.5V12.1667C25.5 11.25 24.75 10.5 23.8333 10.5ZM13.8333 15.5C12.9167 15.5 12.1667 14.75 12.1667 13.8333C12.1667 12.9167 12.9167 12.1667 13.8333 12.1667C14.75 12.1667 15.5 12.9167 15.5 13.8333C15.5 14.75 14.75 15.5 13.8333 15.5Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_971_113" x1="31" y1="27.5" x2="6.5" y2="7" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#6038CB"/>
|
||||
<stop offset="1" stop-color="#704ADC"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
10
src/assets/image/itemicon/proxies.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="36" height="36" rx="18" fill="url(#paint0_linear_971_108)"/>
|
||||
<path d="M9.7167 16.3834C10.1417 16.8084 10.8167 16.85 11.275 16.4667C15.1667 13.2667 20.8167 13.2667 24.7167 16.4583C25.1834 16.8417 25.8667 16.8084 26.2917 16.3834C26.7834 15.8917 26.75 15.075 26.2084 14.6333C21.45 10.7417 14.5667 10.7417 9.80003 14.6333C9.25836 15.0667 9.2167 15.8834 9.7167 16.3834ZM16.1834 22.85L17.4084 24.075C17.7334 24.4 18.2584 24.4 18.5834 24.075L19.8084 22.85C20.2 22.4583 20.1167 21.7833 19.6167 21.525C18.6 21 17.3834 21 16.3584 21.525C15.8834 21.7833 15.7917 22.4583 16.1834 22.85ZM13.075 19.7417C13.4834 20.15 14.125 20.1917 14.6 19.85C16.6334 18.4084 19.3667 18.4084 21.4 19.85C21.875 20.1834 22.5167 20.15 22.925 19.7417L22.9334 19.7333C23.4334 19.2333 23.4 18.3834 22.825 17.975C19.9584 15.9 16.05 15.9 13.175 17.975C12.6 18.3917 12.5667 19.2333 13.075 19.7417Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_971_108" x1="31" y1="27.5" x2="6.5" y2="7" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#21B2CB"/>
|
||||
<stop offset="1" stop-color="#3EC5D2"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
10
src/assets/image/itemicon/rules.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="36" height="36" rx="18" fill="url(#paint0_linear_971_122)"/>
|
||||
<path d="M15.5 24.6666C15.5 25.125 15.875 25.5 16.3333 25.5C16.7917 25.5 17.1667 25.125 17.1667 24.6666V22.1666C17.775 20.0166 19.725 19.275 21.475 19.6666L20.7416 20.4C20.4166 20.725 20.4166 21.25 20.7416 21.575C21.0666 21.9 21.5917 21.9 21.9167 21.575L24.075 19.4166C24.4 19.0916 24.4 18.5666 24.075 18.2416L21.9167 16.0833C21.8396 16.006 21.748 15.9447 21.6472 15.9029C21.5464 15.8611 21.4383 15.8396 21.3291 15.8396C21.22 15.8396 21.1119 15.8611 21.0111 15.9029C20.9103 15.9447 20.8187 16.006 20.7416 16.0833C20.4166 16.4083 20.4166 16.9333 20.7416 17.2583L21.475 18C20.2166 17.725 18.3667 18.0666 17.1667 19.1333V13.6916L17.9 14.425C18.225 14.75 18.75 14.75 19.075 14.425C19.4 14.1 19.4 13.575 19.075 13.25L16.9167 11.0916C16.8396 11.0144 16.748 10.9531 16.6472 10.9113C16.5464 10.8694 16.4383 10.8479 16.3292 10.8479C16.22 10.8479 16.1119 10.8694 16.0111 10.9113C15.9103 10.9531 15.8187 11.0144 15.7417 11.0916L13.5917 13.2416C13.2667 13.5666 13.2667 14.0916 13.5917 14.4166C13.9167 14.7416 14.4417 14.7416 14.7667 14.4166L15.5 13.6916V24.6666Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_971_122" x1="31" y1="27.5" x2="6.5" y2="7" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FB4293"/>
|
||||
<stop offset="1" stop-color="#F957A1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
10
src/assets/image/itemicon/settings.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="36" height="36" rx="18" fill="url(#paint0_linear_971_137)"/>
|
||||
<path d="M24.25 18.0001C24.25 17.8084 24.2416 17.6251 24.225 17.4334L25.775 16.2584C26.1083 16.0084 26.2 15.5417 25.9916 15.1751L24.4333 12.4834C24.225 12.1167 23.775 11.9667 23.3916 12.1334L21.6 12.8917C21.2916 12.6751 20.9666 12.4834 20.625 12.3251L20.3833 10.4001C20.3333 9.98341 19.975 9.66675 19.5583 9.66675H16.45C16.025 9.66675 15.6666 9.98341 15.6166 10.4001L15.375 12.3251C15.0333 12.4834 14.7083 12.6751 14.4 12.8917L12.6083 12.1334C12.225 11.9667 11.775 12.1167 11.5666 12.4834L10.0083 15.1834C9.79997 15.5501 9.89163 16.0084 10.225 16.2667L11.775 17.4417C11.7583 17.6251 11.75 17.8084 11.75 18.0001C11.75 18.1917 11.7583 18.3751 11.775 18.5667L10.225 19.7417C9.89163 19.9917 9.79997 20.4584 10.0083 20.8251L11.5666 23.5167C11.775 23.8834 12.225 24.0334 12.6083 23.8667L14.4 23.1084C14.7083 23.3251 15.0333 23.5167 15.375 23.6751L15.6166 25.6001C15.6666 26.0167 16.025 26.3334 16.4416 26.3334H19.55C19.9666 26.3334 20.325 26.0167 20.375 25.6001L20.6166 23.6751C20.9583 23.5167 21.2833 23.3251 21.5916 23.1084L23.3833 23.8667C23.7666 24.0334 24.2166 23.8834 24.425 23.5167L25.9833 20.8251C26.1916 20.4584 26.1 20.0001 25.7666 19.7417L24.2166 18.5667C24.2416 18.3751 24.25 18.1917 24.25 18.0001ZM18.0333 20.9167C16.425 20.9167 15.1166 19.6084 15.1166 18.0001C15.1166 16.3917 16.425 15.0834 18.0333 15.0834C19.6416 15.0834 20.95 16.3917 20.95 18.0001C20.95 19.6084 19.6416 20.9167 18.0333 20.9167Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_971_137" x1="6" y1="6.5" x2="29.5" y2="30.5" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#56718E"/>
|
||||
<stop offset="1" stop-color="#4B6683"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
10
src/assets/image/itemicon/test.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="36" height="36" rx="18" fill="url(#paint0_linear_971_132)"/>
|
||||
<path d="M18 17.1668C17.0834 17.1668 16.3334 17.9168 16.3334 18.8335C16.3334 19.7502 17.0834 20.5002 18 20.5002C18.9167 20.5002 19.6667 19.7502 19.6667 18.8335C19.6667 17.9168 18.9167 17.1668 18 17.1668ZM23 18.8335C23 15.8668 20.4084 13.5002 17.375 13.8752C15.1917 14.1418 13.3917 15.8835 13.0584 18.0585C12.7834 19.8502 13.4667 21.4835 14.6667 22.5585C15.0667 22.9168 15.6917 22.8335 15.9667 22.3668L15.975 22.3585C16.175 22.0085 16.0917 21.5835 15.7917 21.3085C14.9334 20.5335 14.4667 19.3335 14.775 18.0252C15.05 16.8418 16.0084 15.8835 17.1917 15.6002C19.375 15.0752 21.3334 16.7252 21.3334 18.8335C21.3334 19.8168 20.9 20.6918 20.225 21.3002C19.925 21.5668 19.8334 22.0002 20.0334 22.3502L20.0417 22.3585C20.3 22.8002 20.9 22.9335 21.2917 22.5918C22.3334 21.6752 23 20.3335 23 18.8335ZM17.025 10.5585C13.175 10.9918 10.0667 14.1668 9.70838 18.0252C9.41671 21.1085 10.8084 23.8752 13.0584 25.5335C13.4584 25.8252 14.025 25.7002 14.275 25.2752C14.4834 24.9168 14.3917 24.4502 14.0584 24.2002C12.1584 22.7918 11.0167 20.4085 11.425 17.7835C11.875 14.8668 14.3084 12.5418 17.2417 12.2168C21.2584 11.7585 24.6667 14.9002 24.6667 18.8335C24.6667 21.0418 23.5917 22.9835 21.9417 24.2002C21.6084 24.4502 21.5167 24.9085 21.725 25.2752C21.975 25.7085 22.5417 25.8252 22.9417 25.5335C25 24.0168 26.3334 21.5835 26.3334 18.8335C26.3334 13.9085 22.0584 9.98349 17.025 10.5585Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_971_132" x1="31" y1="27.5" x2="6.5" y2="7" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFA800"/>
|
||||
<stop offset="1" stop-color="#FFAC4B"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
18
src/assets/image/logo.bak.svg
Normal file
@@ -0,0 +1,18 @@
|
||||
<svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400"
|
||||
height="400" viewBox="0, 0, 400,400">
|
||||
<defs>
|
||||
<linearGradient id="Gradient2" x1="0" x2="-0.1" y1="0" y2="1">
|
||||
<stop offset="0%" stop-color="#5b5c9d" />
|
||||
<stop offset="80%" stop-color="rgb(63, 64, 109)" />
|
||||
<stop offset="100%" stop-color="rgb(63, 64, 109)" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="svgg">
|
||||
<path id="path0"
|
||||
d="M118.124 39.858 C 116.645 40.182,114.562 42.930,113.283 46.247 C 111.908 49.812,110.887 54.542,107.205 74.400 C 106.736 76.930,105.926 81.160,105.404 83.800 C 104.527 88.237,103.654 92.889,102.177 101.000 C 101.856 102.760,101.413 105.100,101.192 106.200 C 100.754 108.375,100.784 108.199,98.436 122.200 C 96.675 132.702,95.947 137.215,94.984 143.600 C 94.636 145.910,94.098 149.420,93.789 151.400 C 92.649 158.697,91.961 164.413,92.180 164.768 C 92.304 164.968,92.223 165.192,92.000 165.266 C 91.777 165.340,96.852 165.347,103.277 165.282 C 116.520 165.149,115.721 165.379,116.358 161.519 C 122.839 122.279,179.334 121.580,186.617 160.650 C 186.981 162.602,187.463 164.425,187.689 164.700 C 188.328 165.481,229.717 165.423,230.367 164.640 C 230.622 164.332,231.013 162.937,231.235 161.540 C 237.531 121.949,295.239 121.807,301.620 161.367 C 302.274 165.421,301.855 165.252,310.962 165.117 C 315.273 165.052,318.861 165.090,318.935 165.200 C 319.009 165.310,319.005 165.152,318.927 164.848 C 318.849 164.545,318.519 162.610,318.193 160.548 C 317.867 158.487,317.330 155.135,317.000 153.100 C 316.162 147.934,315.312 142.663,314.823 139.600 C 314.595 138.170,314.226 136.010,314.004 134.800 C 313.781 133.590,312.423 125.400,310.985 116.600 C 304.278 75.545,304.008 74.156,298.145 50.400 C 295.961 41.553,294.621 39.584,290.800 39.611 C 287.927 39.631,283.053 43.395,279.420 48.400 C 277.509 51.032,261.566 79.109,256.960 87.953 C 253.991 93.654,253.647 93.789,245.600 92.402 C 218.757 87.774,194.454 87.780,170.478 92.420 C 162.868 93.893,163.987 94.596,157.579 84.306 C 133.879 46.247,126.566 38.009,118.124 39.858 M147.277 134.807 C 123.365 138.118,111.083 165.918,124.948 185.349 C 140.543 207.202,173.704 202.274,182.466 176.800 C 190.000 154.900,170.471 131.596,147.277 134.807 M262.051 134.810 C 235.780 138.440,224.730 170.720,243.356 189.422 C 264.398 210.548,299.874 195.275,298.689 165.600 C 297.927 146.523,280.892 132.207,262.051 134.810 M157.600 153.840 C 163.092 156.341,166.343 161.914,165.902 168.074 C 164.875 182.425,145.082 186.221,138.715 173.287 C 132.759 161.189,145.324 148.250,157.600 153.840 M273.193 153.597 C 279.788 156.926,283.287 165.159,280.844 171.600 C 275.229 186.406,253.594 183.910,252.135 168.287 C 251.125 157.467,263.609 148.758,273.193 153.597 M91.200 168.809 C 91.200 169.522,90.939 171.836,90.621 173.952 C 89.933 178.523,87.567 196.170,85.788 210.000 C 85.462 212.530,85.012 215.860,84.786 217.400 C 84.561 218.940,84.191 221.820,83.964 223.800 C 83.737 225.780,83.288 229.560,82.965 232.200 C 81.886 241.026,80.172 255.664,79.404 262.600 C 78.867 267.450,78.532 270.381,76.987 283.800 C 76.251 290.187,75.405 297.881,74.568 305.800 C 74.220 309.100,73.789 313.150,73.613 314.800 C 73.436 316.450,73.063 320.230,72.784 323.200 C 72.504 326.170,72.169 328.723,72.038 328.874 C 71.701 329.262,59.638 327.033,54.028 325.546 C 34.668 320.412,26.096 301.951,35.625 285.911 C 38.026 281.869,41.515 278.587,49.795 272.581 C 58.081 266.570,59.262 265.247,59.510 261.702 C 59.969 255.136,50.677 252.070,40.551 255.447 C -6.127 271.014,-3.894 337.227,43.806 351.951 C 50.541 354.030,58.050 355.239,67.760 355.807 C 72.410 356.079,75.202 356.542,82.181 358.199 C 88.822 359.777,100.215 360.425,156.000 362.398 C 170.725 362.918,255.192 362.921,267.760 362.401 C 273.062 362.182,281.900 361.820,287.400 361.597 C 302.851 360.972,326.558 359.339,333.200 358.444 C 343.055 357.116,343.889 354.966,341.839 336.200 C 341.502 333.120,340.948 327.900,340.607 324.600 C 340.266 321.300,339.709 315.990,339.370 312.800 C 339.030 309.610,338.499 304.570,338.189 301.600 C 337.022 290.393,335.650 278.160,334.622 269.800 C 333.105 257.460,332.638 254.027,330.408 238.800 C 329.716 234.070,328.983 229.030,328.781 227.600 C 328.579 226.170,328.231 223.920,328.008 222.600 C 327.785 221.280,326.695 214.260,325.587 207.000 C 324.478 199.740,323.124 191.010,322.578 187.600 C 322.032 184.190,321.325 179.780,321.007 177.800 C 320.689 175.820,320.203 172.711,319.925 170.892 C 319.508 168.155,319.315 167.635,318.810 167.885 C 318.475 168.051,314.780 168.279,310.600 168.393 C 301.870 168.631,302.159 168.535,301.810 171.300 C 299.468 189.825,283.036 203.371,264.230 202.279 C 247.552 201.310,233.532 188.465,231.203 172.020 C 230.651 168.125,232.337 168.400,209.000 168.400 C 185.703 168.400,187.432 168.114,186.814 172.064 C 180.639 211.474,123.556 212.329,116.559 173.117 C 115.684 168.218,116.787 168.629,103.881 168.400 C 97.676 168.290,92.285 168.046,91.900 167.857 C 91.307 167.567,91.200 167.712,91.200 168.809 M211.015 197.632 C 214.247 200.942,215.394 201.357,220.447 201.050 C 225.236 200.759,225.846 201.071,224.310 203.023 C 221.899 206.089,216.333 205.843,210.779 202.425 C 208.312 200.907,207.846 200.906,205.600 202.405 C 200.180 206.022,193.561 206.136,191.600 202.647 C 190.824 201.267,191.555 200.665,193.600 201.001 C 199.643 201.993,201.561 201.450,204.900 197.805 C 207.534 194.929,208.352 194.906,211.015 197.632 "
|
||||
stroke="none" fill="url(#Gradient2)" fill-rule="evenodd"></path>
|
||||
<path id="path1"
|
||||
d="M148.000 131.622 C 132.020 133.140,119.114 145.293,116.377 161.400 C 115.675 165.535,116.697 165.239,103.579 165.112 C 97.252 165.050,92.159 165.135,92.261 165.300 C 92.364 165.465,92.279 165.600,92.074 165.600 C 91.391 165.600,91.684 167.617,92.424 168.013 C 92.839 168.235,97.730 168.400,103.897 168.400 C 116.551 168.400,115.666 168.070,116.562 173.117 C 123.522 212.326,180.639 211.470,186.814 172.064 C 187.432 168.114,185.703 168.400,209.000 168.400 C 232.337 168.400,230.651 168.125,231.203 172.020 C 233.532 188.465,247.552 201.310,264.230 202.279 C 283.039 203.371,299.468 189.826,301.811 171.294 C 302.169 168.458,302.345 168.400,310.600 168.400 C 318.988 168.400,319.609 168.159,318.852 165.200 C 318.824 165.090,315.273 165.052,310.961 165.117 C 301.855 165.252,302.274 165.421,301.620 161.367 C 295.239 121.807,237.531 121.949,231.235 161.540 C 231.013 162.937,230.622 164.332,230.367 164.640 C 229.717 165.423,188.328 165.481,187.689 164.700 C 187.463 164.425,186.981 162.602,186.617 160.650 C 183.194 142.288,166.648 129.850,148.000 131.622 M159.886 135.622 C 183.880 141.759,192.035 172.033,174.435 189.636 C 156.404 207.671,125.892 198.962,119.944 174.084 C 114.368 150.761,136.343 129.601,159.886 135.622 M274.658 135.615 C 299.082 141.861,307.061 172.817,288.734 190.222 C 267.975 209.936,234.188 195.420,234.219 166.800 C 234.241 145.502,253.935 130.315,274.658 135.615 M148.542 152.793 C 139.499 154.706,134.598 164.925,138.715 173.287 C 145.082 186.221,164.875 182.425,165.902 168.074 C 166.591 158.446,157.916 150.811,148.542 152.793 M262.091 153.188 C 253.922 156.127,249.883 165.408,253.408 173.139 C 257.835 182.850,271.593 184.491,278.201 176.097 C 287.389 164.426,275.974 148.192,262.091 153.188 M204.900 197.805 C 201.561 201.450,199.643 201.993,193.600 201.001 C 191.555 200.665,190.824 201.267,191.600 202.647 C 193.561 206.136,200.180 206.022,205.600 202.405 C 207.846 200.906,208.312 200.907,210.779 202.425 C 216.333 205.843,221.899 206.089,224.310 203.023 C 225.846 201.071,225.236 200.759,220.447 201.050 C 215.394 201.357,214.247 200.942,211.015 197.632 C 208.352 194.906,207.534 194.929,204.900 197.805 "
|
||||
stroke="none" fill="#ffffff" fill-rule="evenodd"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.6 KiB |
@@ -1,18 +1,25 @@
|
||||
<svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400"
|
||||
height="400" viewBox="0, 0, 400,400">
|
||||
<defs>
|
||||
<linearGradient id="Gradient2" x1="0" x2="-0.1" y1="0" y2="1">
|
||||
<stop offset="0%" stop-color="#5b5c9d" />
|
||||
<stop offset="80%" stop-color="rgb(63, 64, 109)" />
|
||||
<stop offset="100%" stop-color="rgb(63, 64, 109)" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="svgg">
|
||||
<path id="path0"
|
||||
d="M118.124 39.858 C 116.645 40.182,114.562 42.930,113.283 46.247 C 111.908 49.812,110.887 54.542,107.205 74.400 C 106.736 76.930,105.926 81.160,105.404 83.800 C 104.527 88.237,103.654 92.889,102.177 101.000 C 101.856 102.760,101.413 105.100,101.192 106.200 C 100.754 108.375,100.784 108.199,98.436 122.200 C 96.675 132.702,95.947 137.215,94.984 143.600 C 94.636 145.910,94.098 149.420,93.789 151.400 C 92.649 158.697,91.961 164.413,92.180 164.768 C 92.304 164.968,92.223 165.192,92.000 165.266 C 91.777 165.340,96.852 165.347,103.277 165.282 C 116.520 165.149,115.721 165.379,116.358 161.519 C 122.839 122.279,179.334 121.580,186.617 160.650 C 186.981 162.602,187.463 164.425,187.689 164.700 C 188.328 165.481,229.717 165.423,230.367 164.640 C 230.622 164.332,231.013 162.937,231.235 161.540 C 237.531 121.949,295.239 121.807,301.620 161.367 C 302.274 165.421,301.855 165.252,310.962 165.117 C 315.273 165.052,318.861 165.090,318.935 165.200 C 319.009 165.310,319.005 165.152,318.927 164.848 C 318.849 164.545,318.519 162.610,318.193 160.548 C 317.867 158.487,317.330 155.135,317.000 153.100 C 316.162 147.934,315.312 142.663,314.823 139.600 C 314.595 138.170,314.226 136.010,314.004 134.800 C 313.781 133.590,312.423 125.400,310.985 116.600 C 304.278 75.545,304.008 74.156,298.145 50.400 C 295.961 41.553,294.621 39.584,290.800 39.611 C 287.927 39.631,283.053 43.395,279.420 48.400 C 277.509 51.032,261.566 79.109,256.960 87.953 C 253.991 93.654,253.647 93.789,245.600 92.402 C 218.757 87.774,194.454 87.780,170.478 92.420 C 162.868 93.893,163.987 94.596,157.579 84.306 C 133.879 46.247,126.566 38.009,118.124 39.858 M147.277 134.807 C 123.365 138.118,111.083 165.918,124.948 185.349 C 140.543 207.202,173.704 202.274,182.466 176.800 C 190.000 154.900,170.471 131.596,147.277 134.807 M262.051 134.810 C 235.780 138.440,224.730 170.720,243.356 189.422 C 264.398 210.548,299.874 195.275,298.689 165.600 C 297.927 146.523,280.892 132.207,262.051 134.810 M157.600 153.840 C 163.092 156.341,166.343 161.914,165.902 168.074 C 164.875 182.425,145.082 186.221,138.715 173.287 C 132.759 161.189,145.324 148.250,157.600 153.840 M273.193 153.597 C 279.788 156.926,283.287 165.159,280.844 171.600 C 275.229 186.406,253.594 183.910,252.135 168.287 C 251.125 157.467,263.609 148.758,273.193 153.597 M91.200 168.809 C 91.200 169.522,90.939 171.836,90.621 173.952 C 89.933 178.523,87.567 196.170,85.788 210.000 C 85.462 212.530,85.012 215.860,84.786 217.400 C 84.561 218.940,84.191 221.820,83.964 223.800 C 83.737 225.780,83.288 229.560,82.965 232.200 C 81.886 241.026,80.172 255.664,79.404 262.600 C 78.867 267.450,78.532 270.381,76.987 283.800 C 76.251 290.187,75.405 297.881,74.568 305.800 C 74.220 309.100,73.789 313.150,73.613 314.800 C 73.436 316.450,73.063 320.230,72.784 323.200 C 72.504 326.170,72.169 328.723,72.038 328.874 C 71.701 329.262,59.638 327.033,54.028 325.546 C 34.668 320.412,26.096 301.951,35.625 285.911 C 38.026 281.869,41.515 278.587,49.795 272.581 C 58.081 266.570,59.262 265.247,59.510 261.702 C 59.969 255.136,50.677 252.070,40.551 255.447 C -6.127 271.014,-3.894 337.227,43.806 351.951 C 50.541 354.030,58.050 355.239,67.760 355.807 C 72.410 356.079,75.202 356.542,82.181 358.199 C 88.822 359.777,100.215 360.425,156.000 362.398 C 170.725 362.918,255.192 362.921,267.760 362.401 C 273.062 362.182,281.900 361.820,287.400 361.597 C 302.851 360.972,326.558 359.339,333.200 358.444 C 343.055 357.116,343.889 354.966,341.839 336.200 C 341.502 333.120,340.948 327.900,340.607 324.600 C 340.266 321.300,339.709 315.990,339.370 312.800 C 339.030 309.610,338.499 304.570,338.189 301.600 C 337.022 290.393,335.650 278.160,334.622 269.800 C 333.105 257.460,332.638 254.027,330.408 238.800 C 329.716 234.070,328.983 229.030,328.781 227.600 C 328.579 226.170,328.231 223.920,328.008 222.600 C 327.785 221.280,326.695 214.260,325.587 207.000 C 324.478 199.740,323.124 191.010,322.578 187.600 C 322.032 184.190,321.325 179.780,321.007 177.800 C 320.689 175.820,320.203 172.711,319.925 170.892 C 319.508 168.155,319.315 167.635,318.810 167.885 C 318.475 168.051,314.780 168.279,310.600 168.393 C 301.870 168.631,302.159 168.535,301.810 171.300 C 299.468 189.825,283.036 203.371,264.230 202.279 C 247.552 201.310,233.532 188.465,231.203 172.020 C 230.651 168.125,232.337 168.400,209.000 168.400 C 185.703 168.400,187.432 168.114,186.814 172.064 C 180.639 211.474,123.556 212.329,116.559 173.117 C 115.684 168.218,116.787 168.629,103.881 168.400 C 97.676 168.290,92.285 168.046,91.900 167.857 C 91.307 167.567,91.200 167.712,91.200 168.809 M211.015 197.632 C 214.247 200.942,215.394 201.357,220.447 201.050 C 225.236 200.759,225.846 201.071,224.310 203.023 C 221.899 206.089,216.333 205.843,210.779 202.425 C 208.312 200.907,207.846 200.906,205.600 202.405 C 200.180 206.022,193.561 206.136,191.600 202.647 C 190.824 201.267,191.555 200.665,193.600 201.001 C 199.643 201.993,201.561 201.450,204.900 197.805 C 207.534 194.929,208.352 194.906,211.015 197.632 "
|
||||
stroke="none" fill="url(#Gradient2)" fill-rule="evenodd"></path>
|
||||
<path id="path1"
|
||||
d="M148.000 131.622 C 132.020 133.140,119.114 145.293,116.377 161.400 C 115.675 165.535,116.697 165.239,103.579 165.112 C 97.252 165.050,92.159 165.135,92.261 165.300 C 92.364 165.465,92.279 165.600,92.074 165.600 C 91.391 165.600,91.684 167.617,92.424 168.013 C 92.839 168.235,97.730 168.400,103.897 168.400 C 116.551 168.400,115.666 168.070,116.562 173.117 C 123.522 212.326,180.639 211.470,186.814 172.064 C 187.432 168.114,185.703 168.400,209.000 168.400 C 232.337 168.400,230.651 168.125,231.203 172.020 C 233.532 188.465,247.552 201.310,264.230 202.279 C 283.039 203.371,299.468 189.826,301.811 171.294 C 302.169 168.458,302.345 168.400,310.600 168.400 C 318.988 168.400,319.609 168.159,318.852 165.200 C 318.824 165.090,315.273 165.052,310.961 165.117 C 301.855 165.252,302.274 165.421,301.620 161.367 C 295.239 121.807,237.531 121.949,231.235 161.540 C 231.013 162.937,230.622 164.332,230.367 164.640 C 229.717 165.423,188.328 165.481,187.689 164.700 C 187.463 164.425,186.981 162.602,186.617 160.650 C 183.194 142.288,166.648 129.850,148.000 131.622 M159.886 135.622 C 183.880 141.759,192.035 172.033,174.435 189.636 C 156.404 207.671,125.892 198.962,119.944 174.084 C 114.368 150.761,136.343 129.601,159.886 135.622 M274.658 135.615 C 299.082 141.861,307.061 172.817,288.734 190.222 C 267.975 209.936,234.188 195.420,234.219 166.800 C 234.241 145.502,253.935 130.315,274.658 135.615 M148.542 152.793 C 139.499 154.706,134.598 164.925,138.715 173.287 C 145.082 186.221,164.875 182.425,165.902 168.074 C 166.591 158.446,157.916 150.811,148.542 152.793 M262.091 153.188 C 253.922 156.127,249.883 165.408,253.408 173.139 C 257.835 182.850,271.593 184.491,278.201 176.097 C 287.389 164.426,275.974 148.192,262.091 153.188 M204.900 197.805 C 201.561 201.450,199.643 201.993,193.600 201.001 C 191.555 200.665,190.824 201.267,191.600 202.647 C 193.561 206.136,200.180 206.022,205.600 202.405 C 207.846 200.906,208.312 200.907,210.779 202.425 C 216.333 205.843,221.899 206.089,224.310 203.023 C 225.846 201.071,225.236 200.759,220.447 201.050 C 215.394 201.357,214.247 200.942,211.015 197.632 C 208.352 194.906,207.534 194.929,204.900 197.805 "
|
||||
stroke="none" fill="#ffffff" fill-rule="evenodd"></path>
|
||||
</g>
|
||||
<svg width="157" height="28" viewBox="0 0 157 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="logo" clip-path="url(#clip0_189_16)">
|
||||
<g id="代理组">
|
||||
<path id="Vector" d="M155.711 21.92C155.205 22.2266 154.611 22.4533 153.931 22.6C153.265 22.7466 152.618 22.82 151.991 22.82C149.858 22.82 148.238 22.3133 147.131 21.3C146.038 20.2866 145.491 18.8667 145.491 17.04C145.491 15.2267 145.978 13.84 146.951 12.88C147.938 11.9066 149.278 11.42 150.971 11.42C152.651 11.42 153.978 11.9066 154.951 12.88C155.938 13.84 156.431 15.2267 156.431 17.04C156.431 17.24 156.418 17.5266 156.391 17.9H148.611C148.905 19.62 150.031 20.48 151.991 20.48C153.365 20.48 154.605 20.0733 155.711 19.26V21.92ZM153.411 15.66C153.238 14.9933 152.938 14.5 152.511 14.18C152.085 13.86 151.571 13.7 150.971 13.7C150.411 13.7 149.931 13.8666 149.531 14.2C149.145 14.5333 148.871 15.02 148.711 15.66H153.411Z" fill="black" fill-opacity="0.88"/>
|
||||
<path id="Vector_2" d="M138.386 27.06C137.572 27.06 136.752 27.0067 135.926 26.9C135.112 26.7933 134.379 26.64 133.726 26.44V23.82C135.152 24.14 136.579 24.3 138.006 24.3C138.912 24.3 139.599 24.1 140.066 23.7C140.532 23.3 140.766 22.7467 140.766 22.04C140.032 22.52 139.159 22.76 138.146 22.76C137.159 22.76 136.292 22.52 135.546 22.04C134.799 21.56 134.226 20.9 133.826 20.06C133.426 19.2067 133.226 18.2267 133.226 17.12C133.226 16.0133 133.426 15.0333 133.826 14.18C134.239 13.3133 134.812 12.64 135.546 12.16C136.292 11.68 137.159 11.44 138.146 11.44C139.066 11.44 139.939 11.7467 140.766 12.36V11.7H143.886V22.46C143.886 25.5267 142.052 27.06 138.386 27.06ZM136.286 17.12C136.286 17.7333 136.406 18.2933 136.646 18.8C136.899 19.3067 137.226 19.7133 137.626 20.02C138.039 20.3133 138.472 20.46 138.926 20.46C139.259 20.46 139.632 20.3867 140.046 20.24C140.459 20.08 140.812 19.7533 141.106 19.26L141.206 18.86V15.16C140.926 14.5867 140.566 14.2133 140.126 14.04C139.686 13.8533 139.286 13.76 138.926 13.76C138.472 13.76 138.039 13.9067 137.626 14.2C137.226 14.4933 136.899 14.9 136.646 15.42C136.406 15.9267 136.286 16.4933 136.286 17.12Z" fill="black" fill-opacity="0.88"/>
|
||||
<path id="Vector_3" d="M129.052 11.7V12.86C129.399 12.4867 129.812 12.2 130.292 12C130.786 11.7867 131.272 11.68 131.752 11.68C132.086 11.68 132.399 11.7267 132.692 11.82V14.28C132.319 14.1867 131.966 14.14 131.632 14.14C131.126 14.14 130.646 14.2267 130.192 14.4C129.739 14.56 129.359 14.82 129.052 15.18V22.5H125.852V11.7H129.052Z" fill="black" fill-opacity="0.88"/>
|
||||
<path id="Vector_4" d="M123.524 21.92C123.017 22.2266 122.424 22.4533 121.744 22.6C121.077 22.7466 120.43 22.82 119.804 22.82C117.67 22.82 116.05 22.3133 114.944 21.3C113.85 20.2866 113.304 18.8667 113.304 17.04C113.304 15.2267 113.79 13.84 114.764 12.88C115.75 11.9066 117.09 11.42 118.784 11.42C120.464 11.42 121.79 11.9066 122.764 12.88C123.75 13.84 124.244 15.2267 124.244 17.04C124.244 17.24 124.23 17.5266 124.204 17.9H116.424C116.717 19.62 117.844 20.48 119.804 20.48C121.177 20.48 122.417 20.0733 123.524 19.26V21.92ZM121.224 15.66C121.05 14.9933 120.75 14.5 120.324 14.18C119.897 13.86 119.384 13.7 118.784 13.7C118.224 13.7 117.744 13.8666 117.344 14.2C116.957 14.5333 116.684 15.02 116.524 15.66H121.224Z" fill="black" fill-opacity="0.88"/>
|
||||
<path id="Vector_5" d="M99.3491 8.5H102.929L106.289 20.28H106.369L109.729 8.5H113.309L108.989 22.5H103.669L99.3491 8.5Z" fill="black" fill-opacity="0.88"/>
|
||||
<path id="Vector_6" d="M86.2201 7.12V12.86C86.7001 12.46 87.2335 12.1533 87.8201 11.94C88.4068 11.7133 89.0001 11.6 89.6001 11.6C90.6268 11.6 91.4401 11.9 92.0401 12.5C92.6535 13.1 92.9601 13.88 92.9601 14.84V22.5H89.7601V15.38C89.7601 14.9933 89.6001 14.68 89.2801 14.44C88.9601 14.1867 88.5801 14.06 88.1401 14.06C87.8868 14.06 87.5735 14.14 87.2001 14.3C86.8268 14.46 86.5001 14.66 86.2201 14.9V22.5H83.0201V7.12H86.2201Z" fill="black" fill-opacity="0.88"/>
|
||||
<path id="Vector_7" d="M77.7898 22.74C76.9765 22.78 76.1498 22.7133 75.3098 22.54C74.4832 22.38 73.7632 22.1267 73.1498 21.78V18.9C73.6965 19.3 74.3498 19.6333 75.1098 19.9C75.8832 20.1533 76.5632 20.26 77.1498 20.22C77.5632 20.1933 77.8632 20.1067 78.0498 19.96C78.2365 19.8 78.3432 19.64 78.3698 19.48C78.4365 19.0667 78.3365 18.7533 78.0698 18.54C77.8032 18.3267 77.3032 18.12 76.5698 17.92C75.7565 17.6933 75.1098 17.4333 74.6298 17.14C74.1498 16.8333 73.7832 16.4933 73.5298 16.12C73.2898 15.7333 73.1698 15.2467 73.1698 14.66C73.1698 14.0467 73.3298 13.5 73.6498 13.02C73.9698 12.5267 74.4765 12.14 75.1698 11.86C75.8632 11.58 76.6098 11.44 77.4098 11.44C78.0098 11.44 78.6165 11.5 79.2298 11.62C79.8432 11.7267 80.3565 11.8733 80.7698 12.06V14.64C80.3432 14.4267 79.8365 14.24 79.2498 14.08C78.6765 13.9067 78.1765 13.82 77.7498 13.82C76.8432 13.82 76.3498 14.06 76.2698 14.54C76.2298 14.82 76.3565 15.0667 76.6498 15.28C76.9565 15.4933 77.3898 15.6867 77.9498 15.86C78.7498 16.1133 79.4032 16.3733 79.9098 16.64C80.4298 16.9067 80.8365 17.2533 81.1298 17.68C81.4232 18.1067 81.5698 18.6533 81.5698 19.32C81.5698 20.3067 81.2165 21.1133 80.5098 21.74C79.8032 22.3533 78.8965 22.6867 77.7898 22.74Z" fill="black" fill-opacity="0.88"/>
|
||||
<path id="Vector_8" d="M65.667 22.76C64.6537 22.76 63.767 22.52 63.007 22.04C62.2603 21.56 61.6803 20.9 61.267 20.06C60.867 19.22 60.667 18.24 60.667 17.12C60.667 16.0133 60.867 15.0333 61.267 14.18C61.6803 13.3133 62.2537 12.64 62.987 12.16C63.7337 11.68 64.6003 11.44 65.587 11.44C66.0403 11.44 66.4937 11.5267 66.947 11.7C67.4137 11.86 67.847 12.0867 68.247 12.38V11.7H71.447V19.98C71.447 21.06 71.5803 21.9 71.847 22.5H68.847C68.7537 22.3133 68.6737 22.0733 68.607 21.78C67.7803 22.4333 66.8003 22.76 65.667 22.76ZM63.727 17.12C63.727 17.7333 63.847 18.2933 64.087 18.8C64.3403 19.3067 64.667 19.7133 65.067 20.02C65.4803 20.3133 65.9137 20.46 66.367 20.46C66.687 20.46 67.047 20.3933 67.447 20.26C67.847 20.1133 68.1937 19.8067 68.487 19.34V14.86C68.1937 14.3933 67.847 14.0933 67.447 13.96C67.0603 13.8267 66.7003 13.76 66.367 13.76C65.9137 13.76 65.4803 13.9067 65.067 14.2C64.667 14.4933 64.3403 14.9 64.087 15.42C63.847 15.9267 63.727 16.4933 63.727 17.12Z" fill="black" fill-opacity="0.88"/>
|
||||
<path id="Vector_9" d="M58.3398 22.66C57.1398 22.66 56.2332 22.3267 55.6198 21.66C55.0065 20.98 54.6998 19.9867 54.6998 18.68V7.12H57.8998V17.88C57.8998 18.4133 57.9398 18.82 58.0198 19.1C58.0998 19.38 58.2332 19.5933 58.4198 19.74C58.5665 19.86 58.7265 19.94 58.8998 19.98C59.0865 20.0067 59.4065 20.02 59.8598 20.02V22.66H58.3398Z" fill="black" fill-opacity="0.88"/>
|
||||
<path id="Vector_10" d="M48.6679 22.76C47.1479 22.76 45.7946 22.48 44.6079 21.92C43.4346 21.36 42.5079 20.5467 41.8279 19.48C41.1613 18.4133 40.8279 17.1467 40.8279 15.68C40.8279 14.1333 41.1546 12.8067 41.8079 11.7C42.4613 10.58 43.3746 9.72666 44.5479 9.13999C45.7213 8.53999 47.0613 8.23999 48.5679 8.23999C49.3146 8.23999 50.0679 8.31332 50.8279 8.45999C51.5879 8.60666 52.2146 8.79332 52.7079 9.01999V11.5C51.3613 11.0067 50.1079 10.76 48.9479 10.76C47.5613 10.76 46.4346 11.1667 45.5679 11.98C44.7146 12.7933 44.2879 14.0267 44.2879 15.68C44.2879 16.56 44.5013 17.34 44.9279 18.02C45.3546 18.6867 45.9146 19.2067 46.6079 19.58C47.3013 19.9533 48.0479 20.1667 48.8479 20.22L49.2879 20.24C49.9013 20.24 50.5079 20.1533 51.1079 19.98C51.7079 19.8067 52.2413 19.5733 52.7079 19.28V22.04C52.1346 22.3067 51.5213 22.4933 50.8679 22.6C50.2279 22.7067 49.4946 22.76 48.6679 22.76Z" fill="black" fill-opacity="0.88"/>
|
||||
</g>
|
||||
<g id="svgg">
|
||||
<path id="path0" fill-rule="evenodd" clip-rule="evenodd" d="M9.45822 0.677484C9.3398 0.703426 9.17301 0.923458 9.0706 1.18905C8.96051 1.4745 8.87876 1.85323 8.58394 3.44325C8.54639 3.64583 8.48153 3.98453 8.43973 4.19591C8.36951 4.55118 8.29961 4.92366 8.18135 5.57311C8.15565 5.71403 8.12018 5.9014 8.10248 5.98947C8.06741 6.16362 8.06981 6.14953 7.88181 7.27059C7.7408 8.11148 7.68251 8.47284 7.60541 8.98408C7.57754 9.16904 7.53446 9.45009 7.50972 9.60863C7.41844 10.1929 7.36336 10.6506 7.38089 10.679C7.39082 10.695 7.38433 10.7129 7.36648 10.7189C7.34862 10.7248 7.75498 10.7254 8.26943 10.7202C9.32979 10.7095 9.26581 10.7279 9.31682 10.4189C9.83575 7.27691 14.3593 7.22095 14.9424 10.3493C14.9716 10.5056 15.0102 10.6515 15.0283 10.6736C15.0794 10.7361 18.3935 10.7314 18.4455 10.6687C18.4659 10.6441 18.4972 10.5324 18.515 10.4205C19.0191 7.25049 23.6398 7.23912 24.1507 10.4067C24.2031 10.7313 24.1695 10.7178 24.8987 10.7069C25.2439 10.7017 25.5312 10.7048 25.5371 10.7136C25.543 10.7224 25.5427 10.7097 25.5365 10.6854C25.5302 10.6611 25.5038 10.5062 25.4777 10.3411C25.4516 10.1761 25.4086 9.90769 25.3822 9.74475C25.3151 9.3311 25.247 8.90906 25.2079 8.6638C25.1896 8.5493 25.1601 8.37635 25.1423 8.27947C25.1244 8.18258 25.0157 7.52681 24.9006 6.8222C24.3635 3.53493 24.3419 3.42372 23.8725 1.52158C23.6976 0.813202 23.5903 0.655544 23.2844 0.657706C23.0543 0.659308 22.6641 0.96069 22.3732 1.36144C22.2201 1.57218 20.9436 3.8203 20.5748 4.52844C20.3371 4.98492 20.3095 4.99573 19.6652 4.88467C17.5159 4.51411 15.5699 4.51459 13.6502 4.88611C13.0409 5.00405 13.1305 5.06034 12.6174 4.23642C10.7197 1.18905 10.1342 0.529434 9.45822 0.677484ZM11.7925 8.28003C9.87787 8.54514 8.89445 10.7711 10.0046 12.3269C11.2533 14.0767 13.9085 13.6821 14.6101 11.6424C15.2133 9.88887 13.6496 8.02292 11.7925 8.28003ZM20.9824 8.28027C18.8789 8.57092 17.9941 11.1556 19.4855 12.653C21.1704 14.3446 24.0109 13.1217 23.916 10.7456C23.855 9.21813 22.491 8.07185 20.9824 8.28027ZM12.6191 9.804C13.0588 10.0043 13.3191 10.4505 13.2838 10.9437C13.2016 12.0928 11.6167 12.3967 11.1069 11.3611C10.63 10.3924 11.6361 9.35641 12.6191 9.804ZM21.8746 9.78454C22.4026 10.0511 22.6828 10.7103 22.4872 11.226C22.0376 12.4115 20.3053 12.2117 20.1885 10.9608C20.1076 10.0944 21.1072 9.39708 21.8746 9.78454ZM7.30242 11.0026C7.30242 11.0597 7.28152 11.2449 7.25606 11.4144C7.20097 11.7804 7.01153 13.1933 6.86908 14.3007C6.84298 14.5033 6.80695 14.7699 6.78885 14.8932C6.77084 15.0165 6.74121 15.2471 6.72304 15.4057C6.70486 15.5642 6.66891 15.8669 6.64305 16.0783C6.55665 16.785 6.41941 17.957 6.35792 18.5124C6.31492 18.9007 6.2881 19.1354 6.16439 20.2099C6.10546 20.7213 6.03772 21.3373 5.9707 21.9714C5.94284 22.2356 5.90833 22.5599 5.89423 22.692C5.88006 22.8241 5.8502 23.1268 5.82786 23.3646C5.80544 23.6024 5.77861 23.8068 5.76813 23.8189C5.74114 23.85 4.77526 23.6715 4.32607 23.5525C2.77592 23.1414 2.08956 21.6632 2.85254 20.3789C3.04479 20.0552 3.32416 19.7925 3.98713 19.3116C4.65059 18.8303 4.74515 18.7243 4.76501 18.4405C4.80176 17.9147 4.05775 17.6693 3.24697 17.9396C-0.49053 19.1861 -0.311734 24.4878 3.5076 25.6667C4.04687 25.8332 4.64811 25.93 5.42559 25.9754C5.79791 25.9972 6.02147 26.0343 6.58027 26.167C7.11202 26.2933 8.02425 26.3452 12.4909 26.5032C13.67 26.5448 20.4332 26.5451 21.4395 26.5034C21.8641 26.4859 22.5717 26.4569 23.0121 26.4391C24.2493 26.389 26.1475 26.2583 26.6793 26.1866C27.4684 26.0803 27.5352 25.9081 27.371 24.4055C27.3441 24.1589 27.2997 23.7409 27.2724 23.4767C27.2451 23.2125 27.2005 22.7873 27.1733 22.5319C27.1461 22.2765 27.1036 21.8729 27.0788 21.6351C26.9853 20.7378 26.8755 19.7583 26.7932 19.0889C26.6717 18.1008 26.6343 17.8259 26.4558 16.6067C26.4003 16.228 26.3417 15.8244 26.3255 15.7099C26.3093 15.5954 26.2814 15.4153 26.2636 15.3096C26.2457 15.2039 26.1585 14.6418 26.0697 14.0605C25.9809 13.4792 25.8725 12.7802 25.8288 12.5072C25.7851 12.2341 25.7285 11.881 25.703 11.7225C25.6776 11.5639 25.6386 11.315 25.6164 11.1693C25.583 10.9502 25.5675 10.9086 25.5271 10.9286C25.5003 10.9419 25.2044 10.9601 24.8697 10.9693C24.1707 10.9883 24.1939 10.9806 24.1659 11.202C23.9784 12.6853 22.6627 13.7699 21.1569 13.6825C19.8215 13.6049 18.6989 12.5764 18.5124 11.2597C18.4682 10.9478 18.6032 10.9698 16.7346 10.9698C14.8693 10.9698 15.0077 10.9469 14.9582 11.2632C14.4638 14.4187 9.89316 14.4872 9.33291 11.3475C9.26285 10.9552 9.35117 10.9881 8.31779 10.9698C7.82095 10.961 7.3893 10.9415 7.35847 10.9263C7.31099 10.9031 7.30242 10.9147 7.30242 11.0026ZM16.896 13.3104C17.1548 13.5754 17.2466 13.6087 17.6512 13.5841C18.0347 13.5608 18.0835 13.5858 17.9605 13.7421C17.7675 13.9876 17.3218 13.9679 16.8771 13.6942C16.6796 13.5726 16.6422 13.5726 16.4624 13.6926C16.0284 13.9822 15.4984 13.9913 15.3414 13.712C15.2793 13.6015 15.3378 13.5533 15.5016 13.5802C15.9854 13.6596 16.139 13.6161 16.4064 13.3243C16.6173 13.094 16.6828 13.0921 16.896 13.3104Z" fill="#40416F"/>
|
||||
<path id="path1" fill-rule="evenodd" clip-rule="evenodd" d="M11.8504 8.025C10.5709 8.14655 9.53748 9.11964 9.31833 10.4093C9.26212 10.7404 9.34395 10.7167 8.29359 10.7065C7.78699 10.7016 7.3792 10.7084 7.38736 10.7216C7.39561 10.7348 7.38881 10.7456 7.37239 10.7456C7.3177 10.7456 7.34116 10.9071 7.40042 10.9388C7.43364 10.9566 7.82527 10.9698 8.31906 10.9698C9.33226 10.9698 9.2614 10.9434 9.33314 11.3475C9.89043 14.487 14.4638 14.4184 14.9582 11.2632C15.0077 10.9469 14.8692 10.9698 16.7346 10.9698C18.6032 10.9698 18.4682 10.9478 18.5124 11.2597C18.6989 12.5764 19.8215 13.6049 21.1569 13.6825C22.6629 13.7699 23.9784 12.6854 24.166 11.2015C24.1947 10.9745 24.2087 10.9698 24.8697 10.9698C25.5413 10.9698 25.5911 10.9505 25.5305 10.7136C25.5282 10.7048 25.2439 10.7017 24.8986 10.7069C24.1695 10.7177 24.2031 10.7313 24.1507 10.4067C23.6398 7.23912 19.0191 7.25049 18.515 10.4205C18.4972 10.5324 18.4659 10.6441 18.4455 10.6687C18.3934 10.7314 15.0794 10.7361 15.0283 10.6736C15.0102 10.6515 14.9716 10.5056 14.9424 10.3493C14.6683 8.87903 13.3435 7.88312 11.8504 8.025ZM12.8021 8.34528C14.7233 8.83667 15.3762 11.2607 13.967 12.6702C12.5233 14.1142 10.0802 13.4169 9.60394 11.4249C9.15747 9.55746 10.917 7.86318 12.8021 8.34528ZM21.9918 8.34472C23.9475 8.84484 24.5864 11.3235 23.1189 12.7171C21.4567 14.2956 18.7514 13.1333 18.7539 10.8417C18.7557 9.13637 20.3326 7.92035 21.9918 8.34472ZM11.8938 9.72016C11.1697 9.87333 10.7773 10.6916 11.1069 11.3611C11.6167 12.3967 13.2016 12.0928 13.2838 10.9437C13.339 10.1728 12.6443 9.56146 11.8938 9.72016ZM20.9856 9.75179C20.3315 9.98711 20.0081 10.7302 20.2904 11.3493C20.6448 12.1268 21.7464 12.2582 22.2755 11.5861C23.0112 10.6516 22.0972 9.35176 20.9856 9.75179ZM16.4063 13.3243C16.139 13.6161 15.9854 13.6596 15.5016 13.5802C15.3378 13.5533 15.2793 13.6015 15.3414 13.712C15.4984 13.9913 16.0284 13.9822 16.4624 13.6926C16.6422 13.5726 16.6795 13.5726 16.8771 13.6942C17.3218 13.9679 17.7674 13.9876 17.9605 13.7421C18.0835 13.5858 18.0346 13.5608 17.6512 13.5841C17.2466 13.6087 17.1548 13.5754 16.896 13.3104C16.6827 13.0921 16.6172 13.094 16.4063 13.3243Z" fill="white"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_189_16">
|
||||
<rect width="157" height="27" fill="white" transform="translate(0 0.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 14 KiB |
20
src/assets/image/logo_dark.svg
Normal file
@@ -0,0 +1,20 @@
|
||||
<svg width="157" height="27" viewBox="0 0 157 27" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_745_54)">
|
||||
<path d="M155.711 21.42C155.205 21.7266 154.611 21.9533 153.931 22.1C153.265 22.2466 152.618 22.32 151.991 22.32C149.858 22.32 148.238 21.8133 147.131 20.8C146.038 19.7866 145.491 18.3667 145.491 16.54C145.491 14.7267 145.978 13.34 146.951 12.38C147.938 11.4066 149.278 10.92 150.971 10.92C152.651 10.92 153.978 11.4066 154.951 12.38C155.938 13.34 156.431 14.7267 156.431 16.54C156.431 16.74 156.418 17.0266 156.391 17.4H148.611C148.905 19.12 150.031 19.98 151.991 19.98C153.365 19.98 154.605 19.5733 155.711 18.76V21.42ZM153.411 15.16C153.238 14.4933 152.938 14 152.511 13.68C152.085 13.36 151.571 13.2 150.971 13.2C150.411 13.2 149.931 13.3666 149.531 13.7C149.145 14.0333 148.871 14.52 148.711 15.16H153.411Z" fill="white"/>
|
||||
<path d="M138.386 26.56C137.572 26.56 136.752 26.5067 135.926 26.4C135.112 26.2933 134.379 26.14 133.726 25.94V23.32C135.152 23.64 136.579 23.8 138.006 23.8C138.912 23.8 139.599 23.6 140.066 23.2C140.532 22.8 140.766 22.2467 140.766 21.54C140.032 22.02 139.159 22.26 138.146 22.26C137.159 22.26 136.292 22.02 135.546 21.54C134.799 21.06 134.226 20.4 133.826 19.56C133.426 18.7067 133.226 17.7267 133.226 16.62C133.226 15.5133 133.426 14.5333 133.826 13.68C134.239 12.8133 134.812 12.14 135.546 11.66C136.292 11.18 137.159 10.94 138.146 10.94C139.066 10.94 139.939 11.2467 140.766 11.86V11.2H143.886V21.96C143.886 25.0267 142.052 26.56 138.386 26.56ZM136.286 16.62C136.286 17.2333 136.406 17.7933 136.646 18.3C136.899 18.8067 137.226 19.2133 137.626 19.52C138.039 19.8133 138.472 19.96 138.926 19.96C139.259 19.96 139.632 19.8867 140.046 19.74C140.459 19.58 140.812 19.2533 141.106 18.76L141.206 18.36V14.66C140.926 14.0867 140.566 13.7133 140.126 13.54C139.686 13.3533 139.286 13.26 138.926 13.26C138.472 13.26 138.039 13.4067 137.626 13.7C137.226 13.9933 136.899 14.4 136.646 14.92C136.406 15.4267 136.286 15.9933 136.286 16.62Z" fill="white"/>
|
||||
<path d="M129.052 11.2V12.36C129.399 11.9867 129.812 11.7 130.292 11.5C130.786 11.2867 131.272 11.18 131.752 11.18C132.086 11.18 132.399 11.2267 132.692 11.32V13.78C132.319 13.6867 131.966 13.64 131.632 13.64C131.126 13.64 130.646 13.7267 130.192 13.9C129.739 14.06 129.359 14.32 129.052 14.68V22H125.852V11.2H129.052Z" fill="white"/>
|
||||
<path d="M123.524 21.42C123.017 21.7266 122.424 21.9533 121.744 22.1C121.077 22.2466 120.43 22.32 119.804 22.32C117.67 22.32 116.05 21.8133 114.944 20.8C113.85 19.7866 113.304 18.3667 113.304 16.54C113.304 14.7267 113.79 13.34 114.764 12.38C115.75 11.4066 117.09 10.92 118.784 10.92C120.464 10.92 121.79 11.4066 122.764 12.38C123.75 13.34 124.244 14.7267 124.244 16.54C124.244 16.74 124.23 17.0266 124.204 17.4H116.424C116.717 19.12 117.844 19.98 119.804 19.98C121.177 19.98 122.417 19.5733 123.524 18.76V21.42ZM121.224 15.16C121.05 14.4933 120.75 14 120.324 13.68C119.897 13.36 119.384 13.2 118.784 13.2C118.224 13.2 117.744 13.3666 117.344 13.7C116.957 14.0333 116.684 14.52 116.524 15.16H121.224Z" fill="white"/>
|
||||
<path d="M99.3491 8H102.929L106.289 19.78H106.369L109.729 8H113.309L108.989 22H103.669L99.3491 8Z" fill="white"/>
|
||||
<path d="M86.2201 6.62V12.36C86.7001 11.96 87.2335 11.6533 87.8201 11.44C88.4068 11.2133 89.0001 11.1 89.6001 11.1C90.6268 11.1 91.4401 11.4 92.0401 12C92.6535 12.6 92.9601 13.38 92.9601 14.34V22H89.7601V14.88C89.7601 14.4933 89.6001 14.18 89.2801 13.94C88.9601 13.6867 88.5801 13.56 88.1401 13.56C87.8868 13.56 87.5735 13.64 87.2001 13.8C86.8268 13.96 86.5001 14.16 86.2201 14.4V22H83.0201V6.62H86.2201Z" fill="white"/>
|
||||
<path d="M77.7898 22.24C76.9765 22.28 76.1498 22.2133 75.3098 22.04C74.4832 21.88 73.7632 21.6267 73.1498 21.28V18.4C73.6965 18.8 74.3498 19.1333 75.1098 19.4C75.8832 19.6533 76.5632 19.76 77.1498 19.72C77.5632 19.6933 77.8632 19.6067 78.0498 19.46C78.2365 19.3 78.3432 19.14 78.3698 18.98C78.4365 18.5667 78.3365 18.2533 78.0698 18.04C77.8032 17.8267 77.3032 17.62 76.5698 17.42C75.7565 17.1933 75.1098 16.9333 74.6298 16.64C74.1498 16.3333 73.7832 15.9933 73.5298 15.62C73.2898 15.2333 73.1698 14.7467 73.1698 14.16C73.1698 13.5467 73.3298 13 73.6498 12.52C73.9698 12.0267 74.4765 11.64 75.1698 11.36C75.8632 11.08 76.6098 10.94 77.4098 10.94C78.0098 10.94 78.6165 11 79.2298 11.12C79.8432 11.2267 80.3565 11.3733 80.7698 11.56V14.14C80.3432 13.9267 79.8365 13.74 79.2498 13.58C78.6765 13.4067 78.1765 13.32 77.7498 13.32C76.8432 13.32 76.3498 13.56 76.2698 14.04C76.2298 14.32 76.3565 14.5667 76.6498 14.78C76.9565 14.9933 77.3898 15.1867 77.9498 15.36C78.7498 15.6133 79.4032 15.8733 79.9098 16.14C80.4298 16.4067 80.8365 16.7533 81.1298 17.18C81.4232 17.6067 81.5698 18.1533 81.5698 18.82C81.5698 19.8067 81.2165 20.6133 80.5098 21.24C79.8032 21.8533 78.8965 22.1867 77.7898 22.24Z" fill="white"/>
|
||||
<path d="M65.667 22.26C64.6537 22.26 63.767 22.02 63.007 21.54C62.2603 21.06 61.6803 20.4 61.267 19.56C60.867 18.72 60.667 17.74 60.667 16.62C60.667 15.5133 60.867 14.5333 61.267 13.68C61.6803 12.8133 62.2537 12.14 62.987 11.66C63.7337 11.18 64.6003 10.94 65.587 10.94C66.0403 10.94 66.4937 11.0267 66.947 11.2C67.4137 11.36 67.847 11.5867 68.247 11.88V11.2H71.447V19.48C71.447 20.56 71.5803 21.4 71.847 22H68.847C68.7537 21.8133 68.6737 21.5733 68.607 21.28C67.7803 21.9333 66.8003 22.26 65.667 22.26ZM63.727 16.62C63.727 17.2333 63.847 17.7933 64.087 18.3C64.3403 18.8067 64.667 19.2133 65.067 19.52C65.4803 19.8133 65.9137 19.96 66.367 19.96C66.687 19.96 67.047 19.8933 67.447 19.76C67.847 19.6133 68.1937 19.3067 68.487 18.84V14.36C68.1937 13.8933 67.847 13.5933 67.447 13.46C67.0603 13.3267 66.7003 13.26 66.367 13.26C65.9137 13.26 65.4803 13.4067 65.067 13.7C64.667 13.9933 64.3403 14.4 64.087 14.92C63.847 15.4267 63.727 15.9933 63.727 16.62Z" fill="white"/>
|
||||
<path d="M58.3398 22.16C57.1398 22.16 56.2332 21.8267 55.6198 21.16C55.0065 20.48 54.6998 19.4867 54.6998 18.18V6.62H57.8998V17.38C57.8998 17.9133 57.9398 18.32 58.0198 18.6C58.0998 18.88 58.2332 19.0933 58.4198 19.24C58.5665 19.36 58.7265 19.44 58.8998 19.48C59.0865 19.5067 59.4065 19.52 59.8598 19.52V22.16H58.3398Z" fill="white"/>
|
||||
<path d="M48.6679 22.26C47.1479 22.26 45.7946 21.98 44.6079 21.42C43.4346 20.86 42.5079 20.0467 41.8279 18.98C41.1613 17.9133 40.8279 16.6467 40.8279 15.18C40.8279 13.6333 41.1546 12.3067 41.8079 11.2C42.4613 10.08 43.3746 9.22666 44.5479 8.63999C45.7213 8.03999 47.0613 7.73999 48.5679 7.73999C49.3146 7.73999 50.0679 7.81332 50.8279 7.95999C51.5879 8.10666 52.2146 8.29332 52.7079 8.51999V11C51.3613 10.5067 50.1079 10.26 48.9479 10.26C47.5613 10.26 46.4346 10.6667 45.5679 11.48C44.7146 12.2933 44.2879 13.5267 44.2879 15.18C44.2879 16.06 44.5013 16.84 44.9279 17.52C45.3546 18.1867 45.9146 18.7067 46.6079 19.08C47.3013 19.4533 48.0479 19.6667 48.8479 19.72L49.2879 19.74C49.9013 19.74 50.5079 19.6533 51.1079 19.48C51.7079 19.3067 52.2413 19.0733 52.7079 18.78V21.54C52.1346 21.8067 51.5213 21.9933 50.8679 22.1C50.2279 22.2067 49.4946 22.26 48.6679 22.26Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.45822 0.177484C9.3398 0.203426 9.17301 0.423458 9.0706 0.689049C8.96051 0.974498 8.87876 1.35323 8.58394 2.94325C8.54639 3.14583 8.48153 3.48453 8.43973 3.69591C8.36951 4.05118 8.29961 4.42366 8.18135 5.07311C8.15565 5.21403 8.12018 5.4014 8.10248 5.48947C8.06741 5.66362 8.06981 5.64953 7.88181 6.77059C7.7408 7.61148 7.68251 7.97284 7.60541 8.48408C7.57754 8.66904 7.53446 8.95009 7.50972 9.10863C7.41844 9.69289 7.36336 10.1506 7.38089 10.179C7.39082 10.195 7.38433 10.2129 7.36648 10.2189C7.34862 10.2248 7.75498 10.2254 8.26943 10.2202C9.32979 10.2095 9.26581 10.2279 9.31682 9.91885C9.83575 6.77691 14.3593 6.72095 14.9424 9.84927C14.9716 10.0056 15.0102 10.1515 15.0283 10.1736C15.0794 10.2361 18.3935 10.2314 18.4455 10.1687C18.4659 10.1441 18.4972 10.0324 18.515 9.92053C19.0191 6.75049 23.6398 6.73912 24.1507 9.90668C24.2031 10.2313 24.1695 10.2178 24.8987 10.2069C25.2439 10.2017 25.5312 10.2048 25.5371 10.2136C25.543 10.2224 25.5427 10.2097 25.5365 10.1854C25.5302 10.1611 25.5038 10.0062 25.4777 9.8411C25.4516 9.67608 25.4086 9.40769 25.3822 9.24475C25.3151 8.8311 25.247 8.40906 25.2079 8.1638C25.1896 8.0493 25.1601 7.87635 25.1423 7.77947C25.1244 7.68258 25.0157 7.02681 24.9006 6.3222C24.3635 3.03493 24.3419 2.92372 23.8725 1.02158C23.6976 0.313202 23.5903 0.155544 23.2844 0.157706C23.0543 0.159308 22.6641 0.46069 22.3732 0.86144C22.2201 1.07218 20.9436 3.3203 20.5748 4.02844C20.3371 4.48492 20.3095 4.49573 19.6652 4.38467C17.5159 4.01411 15.5699 4.01459 13.6502 4.38611C13.0409 4.50405 13.1305 4.56034 12.6174 3.73642C10.7197 0.689049 10.1342 0.0294346 9.45822 0.177484ZM11.7925 7.78003C9.87787 8.04514 8.89445 10.2711 10.0046 11.8269C11.2533 13.5767 13.9085 13.1821 14.6101 11.1424C15.2133 9.38887 13.6496 7.52292 11.7925 7.78003ZM20.9824 7.78027C18.8789 8.07092 17.9941 10.6556 19.4855 12.153C21.1704 13.8446 24.0109 12.6217 23.916 10.2456C23.855 8.71813 22.491 7.57185 20.9824 7.78027ZM12.6191 9.304C13.0588 9.50425 13.3191 9.95048 13.2838 10.4437C13.2016 11.5928 11.6167 11.8967 11.1069 10.8611C10.63 9.89243 11.6361 8.85641 12.6191 9.304ZM21.8746 9.28454C22.4026 9.55109 22.6828 10.2103 22.4872 10.726C22.0376 11.9115 20.3053 11.7117 20.1885 10.4608C20.1076 9.59441 21.1072 8.89708 21.8746 9.28454ZM7.30242 10.5026C7.30242 10.5597 7.28152 10.7449 7.25606 10.9144C7.20097 11.2804 7.01153 12.6933 6.86908 13.8007C6.84298 14.0033 6.80695 14.2699 6.78885 14.3932C6.77084 14.5165 6.74121 14.7471 6.72304 14.9057C6.70486 15.0642 6.66891 15.3669 6.64305 15.5783C6.55665 16.285 6.41941 17.457 6.35792 18.0124C6.31492 18.4007 6.2881 18.6354 6.16439 19.7099C6.10546 20.2213 6.03772 20.8373 5.9707 21.4714C5.94284 21.7356 5.90833 22.0599 5.89423 22.192C5.88006 22.3241 5.8502 22.6268 5.82786 22.8646C5.80544 23.1024 5.77861 23.3068 5.76813 23.3189C5.74114 23.35 4.77526 23.1715 4.32607 23.0525C2.77592 22.6414 2.08956 21.1632 2.85254 19.8789C3.04479 19.5552 3.32416 19.2925 3.98713 18.8116C4.65059 18.3303 4.74515 18.2243 4.76501 17.9405C4.80176 17.4147 4.05775 17.1693 3.24697 17.4396C-0.490531 18.6861 -0.311735 23.9878 3.5076 25.1667C4.04687 25.3332 4.64811 25.43 5.42559 25.4754C5.79791 25.4972 6.02147 25.5343 6.58027 25.667C7.11202 25.7933 8.02425 25.8452 12.4909 26.0032C13.67 26.0448 20.4332 26.0451 21.4395 26.0034C21.8641 25.9859 22.5717 25.9569 23.0121 25.9391C24.2493 25.889 26.1475 25.7583 26.6793 25.6866C27.4684 25.5803 27.5352 25.4081 27.371 23.9055C27.3441 23.6589 27.2997 23.2409 27.2724 22.9767C27.2451 22.7125 27.2005 22.2873 27.1733 22.0319C27.1461 21.7765 27.1036 21.3729 27.0788 21.1351C26.9853 20.2378 26.8755 19.2583 26.7932 18.5889C26.6717 17.6008 26.6343 17.3259 26.4558 16.1067C26.4003 15.728 26.3417 15.3244 26.3255 15.2099C26.3093 15.0954 26.2814 14.9153 26.2636 14.8096C26.2457 14.7039 26.1585 14.1418 26.0697 13.5605C25.9809 12.9792 25.8725 12.2802 25.8288 12.0072C25.7851 11.7341 25.7285 11.381 25.703 11.2225C25.6776 11.0639 25.6386 10.815 25.6164 10.6693C25.583 10.4502 25.5675 10.4086 25.5271 10.4286C25.5003 10.4419 25.2044 10.4601 24.8697 10.4693C24.1707 10.4883 24.1939 10.4806 24.1659 10.702C23.9784 12.1853 22.6627 13.2699 21.1569 13.1825C19.8215 13.1049 18.6989 12.0764 18.5124 10.7597C18.4682 10.4478 18.6032 10.4698 16.7346 10.4698C14.8693 10.4698 15.0077 10.4469 14.9582 10.7632C14.4638 13.9187 9.89316 13.9872 9.33291 10.8475C9.26285 10.4552 9.35117 10.4881 8.31779 10.4698C7.82095 10.461 7.3893 10.4415 7.35847 10.4263C7.31099 10.4031 7.30242 10.4147 7.30242 10.5026ZM16.896 12.8104C17.1548 13.0754 17.2466 13.1087 17.6512 13.0841C18.0347 13.0608 18.0835 13.0858 17.9605 13.2421C17.7675 13.4876 17.3218 13.4679 16.8771 13.1942C16.6796 13.0726 16.6422 13.0726 16.4624 13.1926C16.0284 13.4822 15.4984 13.4913 15.3414 13.212C15.2793 13.1015 15.3378 13.0533 15.5016 13.0802C15.9854 13.1596 16.139 13.1161 16.4064 12.8243C16.6173 12.594 16.6828 12.5921 16.896 12.8104Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_745_54">
|
||||
<rect width="157" height="27" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -13,10 +13,10 @@ body {
|
||||
|
||||
:root {
|
||||
--primary-main: #5b5c9d;
|
||||
--text-primary: #637381;
|
||||
--text-primary: #1f1f1f;
|
||||
--selection-color: #f5f5f5;
|
||||
--scroller-color: #90939980;
|
||||
--background-color: #ffffff;
|
||||
--scroller-color: #8c8c8c;
|
||||
--background-color: #f5f5f5;
|
||||
--background-color-alpha: rgba(24, 103, 192, 0.1);
|
||||
--border-radius: 8px;
|
||||
}
|
||||
@@ -35,6 +35,9 @@ body {
|
||||
border-radius: 6px;
|
||||
background-color: var(--scroller-color);
|
||||
}
|
||||
*::-webkit-scrollbar-corner {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
@@ -44,11 +47,11 @@ body {
|
||||
@import "./page.scss";
|
||||
@import "./font.scss";
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
background-color: rgba(18, 18, 18, 1);
|
||||
}
|
||||
}
|
||||
// @media (prefers-color-scheme: dark) {
|
||||
// :root {
|
||||
// background-color: rgba(18, 18, 18, 1);
|
||||
// }
|
||||
// }
|
||||
|
||||
.user-none {
|
||||
user-select: none;
|
||||
@@ -56,3 +59,7 @@ body {
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
[data-tauri-drag-region] {
|
||||
app-region: drag;
|
||||
}
|
||||
|
||||
@@ -5,33 +5,44 @@
|
||||
overflow: hidden;
|
||||
|
||||
&__left {
|
||||
flex: 1 0 15%;
|
||||
flex: 1 0 200px;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
max-width: 225px;
|
||||
min-width: 125px;
|
||||
width: 100%;
|
||||
// max-width: 225px;
|
||||
// min-width: 225px;
|
||||
padding: 16px 0 8px;
|
||||
position: relative;
|
||||
// position: relative;
|
||||
flex-direction: column;
|
||||
align-self: stretch;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
overflow: hidden;
|
||||
background-color: var(--background-color-alpha);
|
||||
border-right: 1px solid var(--divider-color);
|
||||
// background-color: var(--background-color-alpha);
|
||||
|
||||
$maxLogo: 100px;
|
||||
// $maxLogo: 100px;
|
||||
|
||||
.the-logo {
|
||||
position: relative;
|
||||
flex: 0 1 $maxLogo;
|
||||
width: 100%;
|
||||
max-width: $maxLogo + 32px;
|
||||
max-height: $maxLogo;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
text-align: center;
|
||||
flex: 1 0 58px;
|
||||
// width: 100%;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding: 0px 20px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
align-self: stretch;
|
||||
// border-bottom: 1px solid var(--divider-color);
|
||||
// max-width: $maxLogo + 32px;
|
||||
// max-height: $maxLogo;
|
||||
// margin: 0 auto;
|
||||
// padding: 0 auto;
|
||||
// text-align: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
img,
|
||||
@@ -39,17 +50,19 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
fill: var(--primary-main);
|
||||
// fill: var(--primary-main);
|
||||
|
||||
#bg {
|
||||
fill: var(--background-color);
|
||||
}
|
||||
// #bg {
|
||||
// fill: var(--background-color);
|
||||
// }
|
||||
}
|
||||
|
||||
.the-newbtn {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 0px;
|
||||
top: 0px;
|
||||
border-radius: 8px;
|
||||
padding: 2px 4px;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
}
|
||||
@@ -58,6 +71,7 @@
|
||||
flex: 1 1 80%;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 0px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.the-traffic {
|
||||
@@ -65,23 +79,25 @@
|
||||
|
||||
> div {
|
||||
margin: 0 auto;
|
||||
padding: 0px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__right {
|
||||
position: relative;
|
||||
flex: 1 1 75%;
|
||||
flex: 1 1 100%;
|
||||
height: 100%;
|
||||
background-color: var(--background-color-alpha);
|
||||
// background-color: var(--background-color-alpha);
|
||||
|
||||
.the-bar {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
// position: absolute;
|
||||
// top: 0px;
|
||||
// right: 0px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// align-items: center;
|
||||
justify-content: end;
|
||||
box-sizing: border-box;
|
||||
z-index: 2;
|
||||
}
|
||||
@@ -100,15 +116,16 @@
|
||||
.windows,
|
||||
.unknown {
|
||||
&.layout {
|
||||
$maxLogo: 115px;
|
||||
.layout__left {
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
.layout__left .the-logo {
|
||||
flex: 0 1 $maxLogo;
|
||||
max-width: $maxLogo + 32px;
|
||||
max-height: $maxLogo;
|
||||
flex: 1 0 58px;
|
||||
}
|
||||
|
||||
.layout__right .the-content {
|
||||
top: 30px;
|
||||
top: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,7 +136,7 @@
|
||||
padding-top: 24px;
|
||||
}
|
||||
.layout__right .the-content {
|
||||
top: 20px;
|
||||
top: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,23 +3,24 @@
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> header {
|
||||
flex: 0 0 58px;
|
||||
width: 100%;
|
||||
// max-width: 850px;
|
||||
margin: 0 auto;
|
||||
padding-right: 8px;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
|
||||
.base-container {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border-top-left-radius: var(--border-radius);
|
||||
// border-radius: 10px;
|
||||
// border-top-left-radius: var(--border-radius);
|
||||
|
||||
> section {
|
||||
position: relative;
|
||||
@@ -30,7 +31,6 @@
|
||||
padding: 10px 0;
|
||||
box-sizing: border-box;
|
||||
scrollbar-gutter: stable;
|
||||
|
||||
.base-content {
|
||||
width: calc(100% - 10px * 2);
|
||||
margin: 0 auto;
|
||||
@@ -41,7 +41,6 @@
|
||||
> section {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
|
||||
.base-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { ReactNode, useState } from "react";
|
||||
import { ReactNode, useState, useEffect } from "react";
|
||||
import { Box, IconButton, Slide, Snackbar, Typography } from "@mui/material";
|
||||
import { Close, CheckCircleRounded, ErrorRounded } from "@mui/icons-material";
|
||||
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
interface InnerProps {
|
||||
type: string;
|
||||
duration?: number;
|
||||
message: ReactNode;
|
||||
isDark?: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const NoticeInner = (props: InnerProps) => {
|
||||
const { type, message, duration = 1500, onClose } = props;
|
||||
const [visible, setVisible] = useState(true);
|
||||
|
||||
const [isDark, setIsDark] = useState(false);
|
||||
const { verge } = useVerge();
|
||||
const { theme_mode } = verge ?? {};
|
||||
const onBtnClose = () => {
|
||||
setVisible(false);
|
||||
onClose();
|
||||
@@ -22,6 +26,26 @@ const NoticeInner = (props: InnerProps) => {
|
||||
if (reason !== "clickaway") onBtnClose();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const themeMode = ["light", "dark", "system"].includes(theme_mode!)
|
||||
? theme_mode!
|
||||
: "light";
|
||||
|
||||
if (themeMode !== "system") {
|
||||
setIsDark(themeMode === "dark");
|
||||
return;
|
||||
}
|
||||
|
||||
appWindow.theme().then((m) => m && setIsDark(m === "dark"));
|
||||
const unlisten = appWindow.onThemeChanged((e) =>
|
||||
setIsDark(e.payload === "dark")
|
||||
);
|
||||
|
||||
return () => {
|
||||
unlisten.then((fn) => fn());
|
||||
};
|
||||
}, [theme_mode]);
|
||||
|
||||
const msgElement =
|
||||
type === "info" ? (
|
||||
message
|
||||
@@ -46,7 +70,13 @@ const NoticeInner = (props: InnerProps) => {
|
||||
autoHideDuration={duration}
|
||||
onClose={onAutoClose}
|
||||
message={msgElement}
|
||||
sx={{ maxWidth: 360 }}
|
||||
sx={{
|
||||
maxWidth: 360,
|
||||
".MuiSnackbarContent-root": {
|
||||
bgcolor: isDark ? "#50515C" : "#ffffff",
|
||||
color: isDark ? "#ffffff" : "#000000",
|
||||
},
|
||||
}}
|
||||
TransitionComponent={(p) => <Slide {...p} direction="left" />}
|
||||
transitionDuration={200}
|
||||
action={
|
||||
@@ -61,9 +91,9 @@ const NoticeInner = (props: InnerProps) => {
|
||||
interface NoticeInstance {
|
||||
(props: Omit<InnerProps, "onClose">): void;
|
||||
|
||||
info(message: ReactNode, duration?: number): void;
|
||||
error(message: ReactNode, duration?: number): void;
|
||||
success(message: ReactNode, duration?: number): void;
|
||||
info(message: ReactNode, duration?: number, isDark?: boolean): void;
|
||||
error(message: ReactNode, duration?: number, isDark?: boolean): void;
|
||||
success(message: ReactNode, duration?: number, isDark?: boolean): void;
|
||||
}
|
||||
|
||||
let parent: HTMLDivElement = null!;
|
||||
|
||||
@@ -20,8 +20,11 @@ export const BasePage: React.FC<Props> = (props) => {
|
||||
return (
|
||||
<BaseErrorBoundary>
|
||||
<div className="base-page">
|
||||
<header data-windrag style={{ userSelect: "none" }}>
|
||||
<Typography variant="h4" component="h1" data-windrag>
|
||||
<header data-tauri-drag-region="true" style={{ userSelect: "none" }}>
|
||||
<Typography
|
||||
sx={{ fontSize: "20px", fontWeight: "700 " }}
|
||||
data-tauri-drag-region="true"
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
|
||||
@@ -30,13 +33,11 @@ export const BasePage: React.FC<Props> = (props) => {
|
||||
|
||||
<div
|
||||
className={full ? "base-container no-padding" : "base-container"}
|
||||
style={{ backgroundColor: isDark ? "#090909" : "#ffffff" }}
|
||||
style={{ backgroundColor: isDark ? "#1e1f27" : "#ffffff" }}
|
||||
>
|
||||
<section
|
||||
style={{
|
||||
backgroundColor: isDark
|
||||
? alpha(theme.palette.primary.main, 0.1)
|
||||
: "",
|
||||
backgroundColor: isDark ? "#1e1f27" : "var(--background-color)",
|
||||
}}
|
||||
>
|
||||
<div className="base-content" style={contentStyle}>
|
||||
|
||||
57
src/components/base/base-switch.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import { styled } from "@mui/material/styles";
|
||||
import { default as MuiSwitch, SwitchProps } from "@mui/material/Switch";
|
||||
|
||||
export const Switch = styled((props: SwitchProps) => (
|
||||
<MuiSwitch
|
||||
focusVisibleClassName=".Mui-focusVisible"
|
||||
disableRipple
|
||||
{...props}
|
||||
/>
|
||||
))(({ theme }) => ({
|
||||
width: 42,
|
||||
height: 26,
|
||||
padding: 0,
|
||||
"& .MuiSwitch-switchBase": {
|
||||
padding: 0,
|
||||
margin: 2,
|
||||
transitionDuration: "300ms",
|
||||
"&.Mui-checked": {
|
||||
transform: "translateX(16px)",
|
||||
color: "#fff",
|
||||
"& + .MuiSwitch-track": {
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
opacity: 1,
|
||||
border: 0,
|
||||
},
|
||||
"&.Mui-disabled + .MuiSwitch-track": {
|
||||
opacity: 0.5,
|
||||
},
|
||||
},
|
||||
"&.Mui-focusVisible .MuiSwitch-thumb": {
|
||||
color: "#33cf4d",
|
||||
border: "6px solid #fff",
|
||||
},
|
||||
"&.Mui-disabled .MuiSwitch-thumb": {
|
||||
color:
|
||||
theme.palette.mode === "light"
|
||||
? theme.palette.grey[100]
|
||||
: theme.palette.grey[600],
|
||||
},
|
||||
"&.Mui-disabled + .MuiSwitch-track": {
|
||||
opacity: theme.palette.mode === "light" ? 0.7 : 0.3,
|
||||
},
|
||||
},
|
||||
"& .MuiSwitch-thumb": {
|
||||
boxSizing: "border-box",
|
||||
width: 22,
|
||||
height: 22,
|
||||
},
|
||||
"& .MuiSwitch-track": {
|
||||
borderRadius: 26 / 2,
|
||||
backgroundColor: theme.palette.mode === "light" ? "#E9E9EA" : "#39393D",
|
||||
opacity: 1,
|
||||
transition: theme.transitions.create(["background-color"], {
|
||||
duration: 500,
|
||||
}),
|
||||
},
|
||||
}));
|
||||
@@ -4,3 +4,4 @@ export { BaseEmpty } from "./base-empty";
|
||||
export { BaseLoading } from "./base-loading";
|
||||
export { BaseErrorBoundary } from "./base-error-boundary";
|
||||
export { Notice } from "./base-notice";
|
||||
export { Switch } from "./base-switch";
|
||||
|
||||
@@ -38,6 +38,7 @@ export const ConnectionItem = (props: Props) => {
|
||||
return (
|
||||
<ListItem
|
||||
dense
|
||||
sx={{ borderBottom: "1px solid var(--divider-color)" }}
|
||||
secondaryAction={
|
||||
<IconButton edge="end" color="inherit" onClick={onDelete}>
|
||||
<CloseRounded />
|
||||
@@ -58,7 +59,9 @@ export const ConnectionItem = (props: Props) => {
|
||||
|
||||
{!!metadata.process && <Tag>{metadata.process}</Tag>}
|
||||
|
||||
{chains?.length > 0 && <Tag>{chains[value.chains.length - 1]}</Tag>}
|
||||
{chains?.length > 0 && (
|
||||
<Tag>{[...chains].reverse().join(" / ")}</Tag>
|
||||
)}
|
||||
|
||||
<Tag>{dayjs(start).fromNow()}</Tag>
|
||||
|
||||
|
||||
@@ -1,32 +1,47 @@
|
||||
import { alpha, ListItem, ListItemButton, ListItemText } from "@mui/material";
|
||||
import {
|
||||
alpha,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemText,
|
||||
ListItemIcon,
|
||||
} from "@mui/material";
|
||||
import { useMatch, useResolvedPath, useNavigate } from "react-router-dom";
|
||||
import type { LinkProps } from "react-router-dom";
|
||||
|
||||
export const LayoutItem = (props: LinkProps) => {
|
||||
const { to, children } = props;
|
||||
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
interface Props {
|
||||
to: string;
|
||||
children: string;
|
||||
icon: React.ReactNode[];
|
||||
}
|
||||
export const LayoutItem = (props: Props) => {
|
||||
const { to, children, icon } = props;
|
||||
const { verge } = useVerge();
|
||||
const { menu_icon } = verge ?? {};
|
||||
const resolved = useResolvedPath(to);
|
||||
const match = useMatch({ path: resolved.pathname, end: true });
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<ListItem sx={{ py: 0.5, maxWidth: 250, mx: "auto", padding: "1px 0px" }}>
|
||||
<ListItem sx={{ py: 0.5, maxWidth: 250, mx: "auto", padding: "4px 0px" }}>
|
||||
<ListItemButton
|
||||
selected={!!match}
|
||||
sx={[
|
||||
{
|
||||
borderRadius: 3,
|
||||
marginLeft: 1,
|
||||
marginRight: 1,
|
||||
textAlign: "center",
|
||||
"& .MuiListItemText-primary": { color: "text.secondary" },
|
||||
borderRadius: 2,
|
||||
marginLeft: 1.25,
|
||||
paddingLeft: 1,
|
||||
paddingRight: 1,
|
||||
marginRight: 1.25,
|
||||
"& .MuiListItemText-primary": {
|
||||
color: "text.primary",
|
||||
fontWeight: "700",
|
||||
},
|
||||
},
|
||||
({ palette: { mode, primary } }) => {
|
||||
const bgcolor =
|
||||
mode === "light"
|
||||
? alpha(primary.main, 0.15)
|
||||
: alpha(primary.main, 0.35);
|
||||
const color = mode === "light" ? primary.main : primary.light;
|
||||
const color = mode === "light" ? "#1f1f1f" : "#ffffff";
|
||||
|
||||
return {
|
||||
"&.Mui-selected": { bgcolor },
|
||||
@@ -37,7 +52,19 @@ export const LayoutItem = (props: LinkProps) => {
|
||||
]}
|
||||
onClick={() => navigate(to)}
|
||||
>
|
||||
<ListItemText primary={children} />
|
||||
{(menu_icon === "monochrome" || !menu_icon) && (
|
||||
<ListItemIcon sx={{ color: "text.primary", marginLeft: "6px" }}>
|
||||
{icon[0]}
|
||||
</ListItemIcon>
|
||||
)}
|
||||
{menu_icon === "colorful" && <ListItemIcon>{icon[1]}</ListItemIcon>}
|
||||
<ListItemText
|
||||
sx={{
|
||||
textAlign: "center",
|
||||
marginLeft: menu_icon === "disable" ? "" : "-35px",
|
||||
}}
|
||||
primary={children}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
);
|
||||
|
||||
@@ -75,7 +75,7 @@ export const LayoutTraffic = () => {
|
||||
};
|
||||
const valStyle: any = {
|
||||
component: "span",
|
||||
color: "primary",
|
||||
// color: "primary",
|
||||
textAlign: "center",
|
||||
sx: { flex: "1 1 56px", userSelect: "none" },
|
||||
};
|
||||
@@ -88,11 +88,7 @@ export const LayoutTraffic = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
width="110px"
|
||||
position="relative"
|
||||
onClick={trafficRef.current?.toggleStyle}
|
||||
>
|
||||
<Box position="relative" onClick={trafficRef.current?.toggleStyle}>
|
||||
{trafficGraph && pageVisible && (
|
||||
<div style={{ width: "100%", height: 60, marginBottom: 6 }}>
|
||||
<TrafficGraph ref={trafficRef} />
|
||||
@@ -103,9 +99,11 @@ export const LayoutTraffic = () => {
|
||||
<Box display="flex" alignItems="center" whiteSpace="nowrap">
|
||||
<ArrowUpward
|
||||
{...iconStyle}
|
||||
color={+up > 0 ? "primary" : "disabled"}
|
||||
color={+up > 0 ? "secondary" : "disabled"}
|
||||
/>
|
||||
<Typography {...valStyle}>{up}</Typography>
|
||||
<Typography {...valStyle} color="secondary">
|
||||
{up}
|
||||
</Typography>
|
||||
<Typography {...unitStyle}>{upUnit}/s</Typography>
|
||||
</Box>
|
||||
|
||||
@@ -114,7 +112,9 @@ export const LayoutTraffic = () => {
|
||||
{...iconStyle}
|
||||
color={+down > 0 ? "primary" : "disabled"}
|
||||
/>
|
||||
<Typography {...valStyle}>{down}</Typography>
|
||||
<Typography {...valStyle} color="primary">
|
||||
{down}
|
||||
</Typography>
|
||||
<Typography {...unitStyle}>{downUnit}/s</Typography>
|
||||
</Box>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Button } from "@mui/material";
|
||||
import { checkUpdate } from "@tauri-apps/api/updater";
|
||||
import { UpdateViewer } from "../setting/mods/update-viewer";
|
||||
import { DialogRef } from "../base";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@@ -11,14 +12,20 @@ interface Props {
|
||||
|
||||
export const UpdateButton = (props: Props) => {
|
||||
const { className } = props;
|
||||
const { verge } = useVerge();
|
||||
const { auto_check_update } = verge || {};
|
||||
|
||||
const viewerRef = useRef<DialogRef>(null);
|
||||
|
||||
const { data: updateInfo } = useSWR("checkUpdate", checkUpdate, {
|
||||
errorRetryCount: 2,
|
||||
revalidateIfStale: false,
|
||||
focusThrottleInterval: 36e5, // 1 hour
|
||||
});
|
||||
const { data: updateInfo } = useSWR(
|
||||
auto_check_update || auto_check_update === null ? "checkUpdate" : null,
|
||||
checkUpdate,
|
||||
{
|
||||
errorRetryCount: 2,
|
||||
revalidateIfStale: false,
|
||||
focusThrottleInterval: 36e5, // 1 hour
|
||||
}
|
||||
);
|
||||
|
||||
if (!updateInfo?.shouldUpdate) return null;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { alpha, createTheme, Theme } from "@mui/material";
|
||||
import { alpha, createTheme, Shadows, Theme } from "@mui/material";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
import { defaultTheme, defaultDarkTheme } from "@/pages/_theme";
|
||||
@@ -59,6 +59,7 @@ export const useCustomTheme = () => {
|
||||
paper: dt.background_color,
|
||||
},
|
||||
},
|
||||
shadows: Array(25).fill("none") as Shadows,
|
||||
typography: {
|
||||
// todo
|
||||
fontFamily: setting.font_family
|
||||
@@ -87,11 +88,14 @@ export const useCustomTheme = () => {
|
||||
}
|
||||
|
||||
// css
|
||||
const backgroundColor = mode === "light" ? "#ffffff" : "#0B121C";
|
||||
const backgroundColor = mode === "light" ? "#f0f0f0" : "#2e303d";
|
||||
const selectColor = mode === "light" ? "#f5f5f5" : "#d5d5d5";
|
||||
const scrollColor = mode === "light" ? "#90939980" : "#54545480";
|
||||
const dividerColor =
|
||||
mode === "light" ? "rgba(0, 0, 0, 0.06)" : "rgba(255, 255, 255, 0.06)";
|
||||
|
||||
const rootEle = document.documentElement;
|
||||
rootEle.style.setProperty("--divider-color", dividerColor);
|
||||
rootEle.style.setProperty("--background-color", backgroundColor);
|
||||
rootEle.style.setProperty("--selection-color", selectColor);
|
||||
rootEle.style.setProperty("--scroller-color", scrollColor);
|
||||
|
||||
@@ -2,41 +2,54 @@ import { alpha, Box, styled } from "@mui/material";
|
||||
|
||||
export const ProfileBox = styled(Box)(
|
||||
({ theme, "aria-selected": selected }) => {
|
||||
const { mode, primary, text, grey, background } = theme.palette;
|
||||
const { mode, primary, text } = theme.palette;
|
||||
const key = `${mode}-${!!selected}`;
|
||||
|
||||
const backgroundColor = {
|
||||
"light-true": alpha(primary.main, 0.2),
|
||||
"light-false": alpha(background.paper, 0.75),
|
||||
"dark-true": alpha(primary.main, 0.45),
|
||||
"dark-false": alpha(grey[700], 0.45),
|
||||
}[key]!;
|
||||
const backgroundColor = mode === "light" ? "#ffffff" : "#282A36";
|
||||
|
||||
const color = {
|
||||
"light-true": text.secondary,
|
||||
"light-false": text.secondary,
|
||||
"dark-true": alpha(text.secondary, 0.85),
|
||||
"dark-true": alpha(text.secondary, 0.65),
|
||||
"dark-false": alpha(text.secondary, 0.65),
|
||||
}[key]!;
|
||||
|
||||
const h2color = {
|
||||
"light-true": primary.main,
|
||||
"light-false": text.primary,
|
||||
"dark-true": primary.light,
|
||||
"dark-true": primary.main,
|
||||
"dark-false": text.primary,
|
||||
}[key]!;
|
||||
|
||||
const borderSelect = {
|
||||
"light-true": {
|
||||
borderLeft: `3px solid ${primary.main}`,
|
||||
width: `calc(100% + 3px)`,
|
||||
marginLeft: `-3px`,
|
||||
},
|
||||
"light-false": {
|
||||
width: "100%",
|
||||
},
|
||||
"dark-true": {
|
||||
borderLeft: `3px solid ${primary.main}`,
|
||||
width: `calc(100% + 3px)`,
|
||||
marginLeft: `-3px`,
|
||||
},
|
||||
"dark-false": {
|
||||
width: "100%",
|
||||
},
|
||||
}[key];
|
||||
|
||||
return {
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
display: "block",
|
||||
cursor: "pointer",
|
||||
textAlign: "left",
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxShadow: theme.shadows[2],
|
||||
padding: "8px 16px",
|
||||
boxSizing: "border-box",
|
||||
backgroundColor,
|
||||
...borderSelect,
|
||||
borderRadius: "8px",
|
||||
color,
|
||||
"& h2": { color: h2color },
|
||||
};
|
||||
|
||||
@@ -57,6 +57,7 @@ export const ProfileItem = (props: Props) => {
|
||||
|
||||
const { upload = 0, download = 0, total = 0 } = extra ?? {};
|
||||
const from = parseUrl(itemData.url);
|
||||
const description = itemData.desc;
|
||||
const expire = parseExpire(extra?.expire);
|
||||
const progress = Math.round(((download + upload) * 100) / (total + 0.1));
|
||||
|
||||
@@ -230,11 +231,19 @@ export const ProfileItem = (props: Props) => {
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
>
|
||||
<DragIndicator sx={{ cursor: "move", marginLeft: "-6px" }} />
|
||||
<DragIndicator
|
||||
sx={[
|
||||
{ cursor: "move", marginLeft: "-6px" },
|
||||
({ palette: { text } }) => {
|
||||
return { color: text.primary };
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Typography
|
||||
width="calc(100% - 36px)"
|
||||
sx={{ fontSize: "18px", fontWeight: "600", lineHeight: "26px" }}
|
||||
variant="h6"
|
||||
component="h2"
|
||||
noWrap
|
||||
@@ -268,27 +277,36 @@ export const ProfileItem = (props: Props) => {
|
||||
</Box>
|
||||
{/* the second line show url's info or description */}
|
||||
<Box sx={boxStyle}>
|
||||
{hasUrl ? (
|
||||
{
|
||||
<>
|
||||
<Typography noWrap title={`From: ${from}`}>
|
||||
{from}
|
||||
</Typography>
|
||||
|
||||
<Typography
|
||||
noWrap
|
||||
flex="1 0 auto"
|
||||
fontSize={14}
|
||||
textAlign="right"
|
||||
title={`Updated Time: ${parseExpire(updated)}`}
|
||||
>
|
||||
{updated > 0 ? dayjs(updated * 1000).fromNow() : ""}
|
||||
</Typography>
|
||||
{description ? (
|
||||
<Typography
|
||||
noWrap
|
||||
title={description}
|
||||
sx={{ fontSize: "14px" }}
|
||||
>
|
||||
{description}
|
||||
</Typography>
|
||||
) : (
|
||||
hasUrl && (
|
||||
<Typography noWrap title={`From ${from}`}>
|
||||
{from}
|
||||
</Typography>
|
||||
)
|
||||
)}
|
||||
{hasUrl && (
|
||||
<Typography
|
||||
noWrap
|
||||
flex="1 0 auto"
|
||||
fontSize={14}
|
||||
textAlign="right"
|
||||
title={`Updated Time: ${parseExpire(updated)}`}
|
||||
>
|
||||
{updated > 0 ? dayjs(updated * 1000).fromNow() : ""}
|
||||
</Typography>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Typography noWrap title={itemData.desc}>
|
||||
{itemData.desc}
|
||||
</Typography>
|
||||
)}
|
||||
}
|
||||
</Box>
|
||||
{/* the third line show extra info or last updated time */}
|
||||
{hasExtra ? (
|
||||
@@ -299,15 +317,11 @@ export const ProfileItem = (props: Props) => {
|
||||
<span title="Expire Time">{expire}</span>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ ...boxStyle, fontSize: 14, justifyContent: "flex-end" }}>
|
||||
<Box sx={{ ...boxStyle, fontSize: 12, justifyContent: "flex-end" }}>
|
||||
<span title="Updated Time">{parseExpire(updated)}</span>
|
||||
</Box>
|
||||
)}
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={progress}
|
||||
color="inherit"
|
||||
/>
|
||||
<LinearProgress variant="determinate" value={progress} />
|
||||
</ProfileBox>
|
||||
|
||||
<Menu
|
||||
|
||||
@@ -178,17 +178,6 @@ export const ProfileMore = (props: Props) => {
|
||||
{itemData.desc}
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
<Typography
|
||||
noWrap
|
||||
component="span"
|
||||
title={`Updated Time: ${parseExpire(itemData.updated)}`}
|
||||
style={{ fontSize: 14 }}
|
||||
>
|
||||
{!!itemData.updated
|
||||
? dayjs(itemData.updated! * 1000).fromNow()
|
||||
: ""}
|
||||
</Typography>
|
||||
</Box>
|
||||
</ProfileBox>
|
||||
|
||||
|
||||
@@ -15,12 +15,11 @@ import {
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
Switch,
|
||||
styled,
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import { createProfile, patchProfile } from "@/services/cmds";
|
||||
import { BaseDialog, Notice } from "@/components/base";
|
||||
import { BaseDialog, Notice, Switch } from "@/components/base";
|
||||
import { version } from "@root/package.json";
|
||||
import { FileInput } from "./file-input";
|
||||
|
||||
@@ -48,7 +47,7 @@ export const ProfileViewer = forwardRef<ProfileViewerRef, Props>(
|
||||
const { control, watch, register, ...formIns } = useForm<IProfileItem>({
|
||||
defaultValues: {
|
||||
type: "remote",
|
||||
name: "Remote File",
|
||||
name: "",
|
||||
desc: "",
|
||||
url: "",
|
||||
option: {
|
||||
@@ -269,6 +268,17 @@ export const ProfileViewer = forwardRef<ProfileViewerRef, Props>(
|
||||
</StyledBox>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="option.danger_accept_invalid_certs"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<StyledBox>
|
||||
<InputLabel>{t("Accept Invalid Certs (Danger)")}</InputLabel>
|
||||
<Switch checked={field.value} {...field} color="primary" />
|
||||
</StyledBox>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</BaseDialog>
|
||||
|
||||
@@ -13,14 +13,19 @@ import {
|
||||
Typography,
|
||||
Divider,
|
||||
LinearProgress,
|
||||
keyframes,
|
||||
} from "@mui/material";
|
||||
import { RefreshRounded } from "@mui/icons-material";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { getProxyProviders, proxyProviderUpdate } from "@/services/api";
|
||||
import { BaseDialog } from "../base";
|
||||
import parseTraffic from "@/utils/parse-traffic";
|
||||
|
||||
const round = keyframes`
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
`;
|
||||
|
||||
export const ProviderButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const { data } = useSWR("getProxyProviders", getProxyProviders);
|
||||
@@ -28,12 +33,31 @@ export const ProviderButton = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const hasProvider = Object.keys(data || {}).length > 0;
|
||||
const [updating, setUpdating] = useState(
|
||||
Object.keys(data || {}).map(() => false)
|
||||
);
|
||||
|
||||
const handleUpdate = useLockFn(async (key: string) => {
|
||||
await proxyProviderUpdate(key);
|
||||
await mutate("getProxies");
|
||||
await mutate("getProxyProviders");
|
||||
});
|
||||
const setUpdatingAt = (status: boolean, index: number) => {
|
||||
setUpdating((prev) => {
|
||||
const next = [...prev];
|
||||
next[index] = status;
|
||||
return next;
|
||||
});
|
||||
};
|
||||
const handleUpdate = async (key: string, index: number) => {
|
||||
setUpdatingAt(true, index);
|
||||
proxyProviderUpdate(key)
|
||||
.then(async () => {
|
||||
setUpdatingAt(false, index);
|
||||
await mutate("getProxies");
|
||||
await mutate("getProxyProviders");
|
||||
})
|
||||
.catch(async () => {
|
||||
setUpdatingAt(false, index);
|
||||
await mutate("getProxies");
|
||||
await mutate("getProxyProviders");
|
||||
});
|
||||
};
|
||||
|
||||
if (!hasProvider) return null;
|
||||
|
||||
@@ -55,12 +79,13 @@ export const ProviderButton = () => {
|
||||
<Typography variant="h6">{t("Proxy Provider")}</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
onClick={async () => {
|
||||
Object.entries(data || {}).forEach(async ([key, item]) => {
|
||||
await proxyProviderUpdate(key);
|
||||
await mutate("getProxies");
|
||||
await mutate("getProxyProviders");
|
||||
});
|
||||
Object.entries(data || {}).forEach(
|
||||
async ([key, item], index) => {
|
||||
await handleUpdate(key, index);
|
||||
}
|
||||
);
|
||||
}}
|
||||
>
|
||||
{t("Update All")}
|
||||
@@ -74,7 +99,7 @@ export const ProviderButton = () => {
|
||||
onCancel={() => setOpen(false)}
|
||||
>
|
||||
<List sx={{ py: 0, minHeight: 250 }}>
|
||||
{Object.entries(data || {}).map(([key, item]) => {
|
||||
{Object.entries(data || {}).map(([key, item], index) => {
|
||||
const time = dayjs(item.updatedAt);
|
||||
const sub = item.subscriptionInfo;
|
||||
const hasSubInfo = !!sub;
|
||||
@@ -88,12 +113,12 @@ export const ProviderButton = () => {
|
||||
return (
|
||||
<>
|
||||
<ListItem
|
||||
sx={(theme) => ({
|
||||
sx={{
|
||||
p: 0,
|
||||
borderRadius: "10px",
|
||||
boxShadow: theme.shadows[2],
|
||||
border: "solid 2px var(--divider-color)",
|
||||
mb: 1,
|
||||
})}
|
||||
}}
|
||||
key={key}
|
||||
>
|
||||
<ListItemText
|
||||
@@ -136,7 +161,6 @@ export const ProviderButton = () => {
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={progress}
|
||||
color="inherit"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@@ -148,7 +172,12 @@ export const ProviderButton = () => {
|
||||
size="small"
|
||||
color="inherit"
|
||||
title="Update Provider"
|
||||
onClick={() => handleUpdate(key)}
|
||||
onClick={() => handleUpdate(key, index)}
|
||||
sx={{
|
||||
animation: updating[index]
|
||||
? `1s linear infinite ${round}`
|
||||
: "none",
|
||||
}}
|
||||
>
|
||||
<RefreshRounded />
|
||||
</IconButton>
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
updateProxy,
|
||||
deleteConnection,
|
||||
} from "@/services/api";
|
||||
import { Box } from "@mui/material";
|
||||
import { useProfiles } from "@/hooks/use-profiles";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { BaseEmpty } from "../base";
|
||||
@@ -117,7 +118,7 @@ export const ProxyGroups = (props: Props) => {
|
||||
return (
|
||||
<Virtuoso
|
||||
ref={virtuosoRef}
|
||||
style={{ height: "100%" }}
|
||||
style={{ height: "calc(100% - 12px)" }}
|
||||
totalCount={renderList.length}
|
||||
increaseViewportBy={256}
|
||||
itemContent={(index) => (
|
||||
|
||||
@@ -50,30 +50,31 @@ export const ProxyItemMini = (props: Props) => {
|
||||
sx={[
|
||||
{
|
||||
height: 56,
|
||||
borderRadius: 1,
|
||||
borderRadius: 1.5,
|
||||
pl: 1.5,
|
||||
pr: 1,
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
},
|
||||
({ palette: { mode, primary } }) => {
|
||||
const bgcolor =
|
||||
mode === "light"
|
||||
? alpha(primary.main, 0.15)
|
||||
: alpha(primary.main, 0.35);
|
||||
const color = mode === "light" ? primary.main : primary.light;
|
||||
const bgcolor = mode === "light" ? "#ffffff" : "#24252f";
|
||||
const showDelay = delay > 0;
|
||||
|
||||
const shadowColor =
|
||||
mode === "light" ? "rgba(0,0,0,0.04)" : "rgba(255,255,255,0.08)";
|
||||
const selectColor = mode === "light" ? primary.main : primary.light;
|
||||
|
||||
return {
|
||||
"&:hover .the-check": { display: !showDelay ? "block" : "none" },
|
||||
"&:hover .the-delay": { display: showDelay ? "block" : "none" },
|
||||
"&:hover .the-icon": { display: "none" },
|
||||
"&.Mui-selected": { bgcolor, boxShadow: `0 0 0 1px ${bgcolor}` },
|
||||
"&.Mui-selected .MuiListItemText-secondary": { color },
|
||||
boxShadow: `0 0 0 1px ${shadowColor}`,
|
||||
"&.Mui-selected": {
|
||||
width: `calc(100% + 3px)`,
|
||||
marginLeft: `-3px`,
|
||||
borderLeft: `3px solid ${selectColor}`,
|
||||
bgcolor:
|
||||
mode === "light"
|
||||
? alpha(primary.main, 0.15)
|
||||
: alpha(primary.main, 0.35),
|
||||
},
|
||||
backgroundColor: bgcolor,
|
||||
};
|
||||
},
|
||||
]}
|
||||
@@ -82,7 +83,7 @@ export const ProxyItemMini = (props: Props) => {
|
||||
<Typography
|
||||
variant="body2"
|
||||
component="div"
|
||||
color="text.secondary"
|
||||
color="text.primary"
|
||||
sx={{
|
||||
display: "block",
|
||||
textOverflow: "ellipsis",
|
||||
@@ -95,14 +96,54 @@ export const ProxyItemMini = (props: Props) => {
|
||||
</Typography>
|
||||
|
||||
{showType && (
|
||||
<Box sx={{ display: "flex", flexWrap: "nowrap", flex: "none" }}>
|
||||
{!!proxy.provider && (
|
||||
<TypeBox component="span">{proxy.provider}</TypeBox>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexWrap: "nowrap",
|
||||
flex: "none",
|
||||
marginTop: "4px",
|
||||
}}
|
||||
>
|
||||
{proxy.now && (
|
||||
<Typography
|
||||
variant="body2"
|
||||
component="div"
|
||||
color="text.secondary"
|
||||
sx={{
|
||||
display: "block",
|
||||
textOverflow: "ellipsis",
|
||||
wordBreak: "break-all",
|
||||
overflow: "hidden",
|
||||
whiteSpace: "nowrap",
|
||||
marginRight: "8px",
|
||||
}}
|
||||
>
|
||||
{proxy.now}
|
||||
</Typography>
|
||||
)}
|
||||
{!!proxy.provider && (
|
||||
<TypeBox color="text.secondary" component="span">
|
||||
{proxy.provider}
|
||||
</TypeBox>
|
||||
)}
|
||||
<TypeBox color="text.secondary" component="span">
|
||||
{proxy.type}
|
||||
</TypeBox>
|
||||
{proxy.udp && (
|
||||
<TypeBox color="text.secondary" component="span">
|
||||
UDP
|
||||
</TypeBox>
|
||||
)}
|
||||
{proxy.xudp && (
|
||||
<TypeBox color="text.secondary" component="span">
|
||||
XUDP
|
||||
</TypeBox>
|
||||
)}
|
||||
{proxy.tfo && (
|
||||
<TypeBox color="text.secondary" component="span">
|
||||
TFO
|
||||
</TypeBox>
|
||||
)}
|
||||
<TypeBox component="span">{proxy.type}</TypeBox>
|
||||
{proxy.udp && <TypeBox component="span">UDP</TypeBox>}
|
||||
{proxy.xudp && <TypeBox component="span">XUDP</TypeBox>}
|
||||
{proxy.tfo && <TypeBox component="span">TFO</TypeBox>}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
@@ -166,7 +207,7 @@ export const ProxyItemMini = (props: Props) => {
|
||||
};
|
||||
|
||||
const Widget = styled(Box)(({ theme: { typography } }) => ({
|
||||
padding: "3px 6px",
|
||||
padding: "2px 4px",
|
||||
fontSize: 14,
|
||||
fontFamily: typography.fontFamily,
|
||||
borderRadius: "4px",
|
||||
@@ -175,12 +216,13 @@ const Widget = styled(Box)(({ theme: { typography } }) => ({
|
||||
const TypeBox = styled(Box)(({ theme: { palette, typography } }) => ({
|
||||
display: "inline-block",
|
||||
border: "1px solid #ccc",
|
||||
borderColor: alpha(palette.text.secondary, 0.36),
|
||||
color: alpha(palette.text.secondary, 0.42),
|
||||
borderColor: "text.secondary",
|
||||
color: "text.secondary",
|
||||
borderRadius: 4,
|
||||
fontSize: 10,
|
||||
fontFamily: typography.fontFamily,
|
||||
marginRight: "4px",
|
||||
padding: "0 2px",
|
||||
lineHeight: 1.25,
|
||||
marginTop: "auto",
|
||||
padding: "0 4px",
|
||||
lineHeight: 1.5,
|
||||
}));
|
||||
|
||||
@@ -78,19 +78,26 @@ export const ProxyItem = (props: Props) => {
|
||||
sx={[
|
||||
{ borderRadius: 1 },
|
||||
({ palette: { mode, primary } }) => {
|
||||
const bgcolor =
|
||||
mode === "light"
|
||||
? alpha(primary.main, 0.15)
|
||||
: alpha(primary.main, 0.35);
|
||||
const color = mode === "light" ? primary.main : primary.light;
|
||||
const bgcolor = mode === "light" ? "#ffffff" : "#24252f";
|
||||
const selectColor = mode === "light" ? primary.main : primary.light;
|
||||
const showDelay = delay > 0;
|
||||
|
||||
return {
|
||||
"&:hover .the-check": { display: !showDelay ? "block" : "none" },
|
||||
"&:hover .the-delay": { display: showDelay ? "block" : "none" },
|
||||
"&:hover .the-icon": { display: "none" },
|
||||
"&.Mui-selected": { bgcolor },
|
||||
"&.Mui-selected .MuiListItemText-secondary": { color },
|
||||
"&.Mui-selected": {
|
||||
width: `calc(100% + 3px)`,
|
||||
marginLeft: `-3px`,
|
||||
borderLeft: `3px solid ${selectColor}`,
|
||||
bgcolor:
|
||||
mode === "light"
|
||||
? alpha(primary.main, 0.15)
|
||||
: alpha(primary.main, 0.35),
|
||||
},
|
||||
backgroundColor: bgcolor,
|
||||
marginBottom: "8px",
|
||||
height: "40px",
|
||||
};
|
||||
},
|
||||
]}
|
||||
@@ -99,8 +106,17 @@ export const ProxyItem = (props: Props) => {
|
||||
title={proxy.name}
|
||||
secondary={
|
||||
<>
|
||||
<span style={{ marginRight: 4 }}>{proxy.name}</span>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "inline-block",
|
||||
marginRight: "8px",
|
||||
fontSize: "14px",
|
||||
color: "text.primary",
|
||||
}}
|
||||
>
|
||||
{proxy.name}
|
||||
{showType && proxy.now && ` - ${proxy.now}`}
|
||||
</Box>
|
||||
{showType && !!proxy.provider && (
|
||||
<TypeBox component="span">{proxy.provider}</TypeBox>
|
||||
)}
|
||||
|
||||
@@ -16,6 +16,9 @@ import { ProxyHead } from "./proxy-head";
|
||||
import { ProxyItem } from "./proxy-item";
|
||||
import { ProxyItemMini } from "./proxy-item-mini";
|
||||
import type { IRenderItem } from "./use-render-list";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
|
||||
interface RenderProps {
|
||||
item: IRenderItem;
|
||||
@@ -30,27 +33,52 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
const { indent, item, onLocation, onCheckAll, onHeadState, onChangeProxy } =
|
||||
props;
|
||||
const { type, group, headState, proxy, proxyCol } = item;
|
||||
const { verge } = useVerge();
|
||||
const enable_group_icon = verge?.enable_group_icon ?? true;
|
||||
const [mode] = useRecoilState(atomThemeMode);
|
||||
const isDark = mode === "light" ? false : true;
|
||||
const itembackgroundcolor = isDark ? "#282A36" : "#ffffff";
|
||||
|
||||
if (type === 0 && !group.hidden) {
|
||||
return (
|
||||
<ListItemButton
|
||||
dense
|
||||
style={{
|
||||
background: itembackgroundcolor,
|
||||
height: "100%",
|
||||
margin: "8px 8px",
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
onClick={() => onHeadState(group.name, { open: !headState?.open })}
|
||||
>
|
||||
{group.icon && group.icon.trim().startsWith("http") && (
|
||||
<img src={group.icon} height="40px" style={{ marginRight: "8px" }} />
|
||||
)}
|
||||
{group.icon && group.icon.trim().startsWith("data") && (
|
||||
<img src={group.icon} height="40px" style={{ marginRight: "8px" }} />
|
||||
)}
|
||||
{group.icon && group.icon.trim().startsWith("<svg") && (
|
||||
<img
|
||||
src={`data:image/svg+xml;base64,${btoa(group.icon)}`}
|
||||
height="40px"
|
||||
/>
|
||||
)}
|
||||
{enable_group_icon &&
|
||||
group.icon &&
|
||||
group.icon.trim().startsWith("http") && (
|
||||
<img
|
||||
src={group.icon}
|
||||
height="32px"
|
||||
style={{ marginRight: "12px", borderRadius: "6px" }}
|
||||
/>
|
||||
)}
|
||||
{enable_group_icon &&
|
||||
group.icon &&
|
||||
group.icon.trim().startsWith("data") && (
|
||||
<img
|
||||
src={group.icon}
|
||||
height="32px"
|
||||
style={{ marginRight: "12px", borderRadius: "6px" }}
|
||||
/>
|
||||
)}
|
||||
{enable_group_icon &&
|
||||
group.icon &&
|
||||
group.icon.trim().startsWith("<svg") && (
|
||||
<img
|
||||
src={`data:image/svg+xml;base64,${btoa(group.icon)}`}
|
||||
height="32px"
|
||||
/>
|
||||
)}
|
||||
<ListItemText
|
||||
primary={group.name}
|
||||
primary={<StyledPrimary>{group.name}</StyledPrimary>}
|
||||
secondary={
|
||||
<ListItemTextChild
|
||||
sx={{
|
||||
@@ -60,12 +88,16 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
pt: "2px",
|
||||
}}
|
||||
>
|
||||
<StyledTypeBox>{group.type}</StyledTypeBox>
|
||||
<StyledSubtitle>{group.now}</StyledSubtitle>
|
||||
<Box sx={{ marginTop: "2px" }}>
|
||||
<StyledTypeBox>{group.type}</StyledTypeBox>
|
||||
<StyledSubtitle sx={{ color: "text.secondary" }}>
|
||||
{group.now}
|
||||
</StyledSubtitle>
|
||||
</Box>
|
||||
</ListItemTextChild>
|
||||
}
|
||||
secondaryTypographyProps={{
|
||||
sx: { display: "flex", alignItems: "center" },
|
||||
sx: { display: "flex", alignItems: "center", color: "#ccc" },
|
||||
}}
|
||||
/>
|
||||
{headState?.open ? <ExpandLessRounded /> : <ExpandMoreRounded />}
|
||||
@@ -76,7 +108,7 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
if (type === 1 && !group.hidden) {
|
||||
return (
|
||||
<ProxyHead
|
||||
sx={{ pl: indent ? 4.5 : 2.5, pr: 3, mt: indent ? 1 : 0.5, mb: 1 }}
|
||||
sx={{ pl: 2, pr: 3, mt: indent ? 1 : 0.5, mb: 1 }}
|
||||
groupName={group.name}
|
||||
headState={headState!}
|
||||
onLocation={() => onLocation(group)}
|
||||
@@ -93,7 +125,7 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
proxy={proxy!}
|
||||
selected={group.now === proxy?.name}
|
||||
showType={headState?.showType}
|
||||
sx={{ py: 0, pl: indent ? 4 : 2 }}
|
||||
sx={{ py: 0, pl: 2 }}
|
||||
onClick={() => onChangeProxy(group, proxy!)}
|
||||
/>
|
||||
);
|
||||
@@ -104,7 +136,7 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
<Box
|
||||
sx={{
|
||||
py: 2,
|
||||
pl: indent ? 4.5 : 0,
|
||||
pl: 0,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
@@ -124,7 +156,7 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
height: 56,
|
||||
display: "grid",
|
||||
gap: 1,
|
||||
pl: indent ? 4 : 2,
|
||||
pl: 2,
|
||||
pr: 2,
|
||||
pb: 1,
|
||||
gridTemplateColumns: `repeat(${item.col! || 2}, 1fr)`,
|
||||
@@ -147,12 +179,21 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
const StyledSubtitle = styled("span")`
|
||||
font-size: 0.8rem;
|
||||
const StyledPrimary = styled("span")`
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
line-height: 1.5;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
`;
|
||||
const StyledSubtitle = styled("span")`
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
color: text.secondary;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
const ListItemTextChild = styled("span")`
|
||||
display: block;
|
||||
@@ -165,7 +206,7 @@ const StyledTypeBox = styled(ListItemTextChild)(({ theme }) => ({
|
||||
color: alpha(theme.palette.primary.main, 0.8),
|
||||
borderRadius: 4,
|
||||
fontSize: 10,
|
||||
padding: "0 2px",
|
||||
lineHeight: 1.25,
|
||||
marginRight: "4px",
|
||||
padding: "0 4px",
|
||||
lineHeight: 1.5,
|
||||
marginRight: "8px",
|
||||
}));
|
||||
|
||||
@@ -12,13 +12,18 @@ import {
|
||||
Box,
|
||||
alpha,
|
||||
Divider,
|
||||
keyframes,
|
||||
} from "@mui/material";
|
||||
import { RefreshRounded } from "@mui/icons-material";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { getRuleProviders, ruleProviderUpdate } from "@/services/api";
|
||||
import { BaseDialog } from "../base";
|
||||
|
||||
const round = keyframes`
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
`;
|
||||
|
||||
export const ProviderButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const { data } = useSWR("getRuleProviders", getRuleProviders);
|
||||
@@ -26,12 +31,31 @@ export const ProviderButton = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const hasProvider = Object.keys(data || {}).length > 0;
|
||||
const [updating, setUpdating] = useState(
|
||||
Object.keys(data || {}).map(() => false)
|
||||
);
|
||||
|
||||
const handleUpdate = useLockFn(async (key: string) => {
|
||||
await ruleProviderUpdate(key);
|
||||
await mutate("getRules");
|
||||
await mutate("getRuleProviders");
|
||||
});
|
||||
const setUpdatingAt = (status: boolean, index: number) => {
|
||||
setUpdating((prev) => {
|
||||
const next = [...prev];
|
||||
next[index] = status;
|
||||
return next;
|
||||
});
|
||||
};
|
||||
const handleUpdate = async (key: string, index: number) => {
|
||||
setUpdatingAt(true, index);
|
||||
ruleProviderUpdate(key)
|
||||
.then(async () => {
|
||||
setUpdatingAt(false, index);
|
||||
await mutate("getRules");
|
||||
await mutate("getRuleProviders");
|
||||
})
|
||||
.catch(async () => {
|
||||
setUpdatingAt(false, index);
|
||||
await mutate("getRules");
|
||||
await mutate("getRuleProviders");
|
||||
});
|
||||
};
|
||||
|
||||
if (!hasProvider) return null;
|
||||
|
||||
@@ -53,12 +77,13 @@ export const ProviderButton = () => {
|
||||
<Typography variant="h6">{t("Rule Provider")}</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
onClick={async () => {
|
||||
Object.entries(data || {}).forEach(async ([key, item]) => {
|
||||
await ruleProviderUpdate(key);
|
||||
await mutate("getRules");
|
||||
await mutate("getRuleProviders");
|
||||
});
|
||||
Object.entries(data || {}).forEach(
|
||||
async ([key, item], index) => {
|
||||
await handleUpdate(key, index);
|
||||
}
|
||||
);
|
||||
}}
|
||||
>
|
||||
{t("Update All")}
|
||||
@@ -72,17 +97,17 @@ export const ProviderButton = () => {
|
||||
onCancel={() => setOpen(false)}
|
||||
>
|
||||
<List sx={{ py: 0, minHeight: 250 }}>
|
||||
{Object.entries(data || {}).map(([key, item]) => {
|
||||
{Object.entries(data || {}).map(([key, item], index) => {
|
||||
const time = dayjs(item.updatedAt);
|
||||
return (
|
||||
<>
|
||||
<ListItem
|
||||
sx={(theme) => ({
|
||||
sx={{
|
||||
p: 0,
|
||||
borderRadius: "10px",
|
||||
boxShadow: theme.shadows[2],
|
||||
border: "solid 2px var(--divider-color)",
|
||||
mb: 1,
|
||||
})}
|
||||
}}
|
||||
key={key}
|
||||
>
|
||||
<ListItemText
|
||||
@@ -121,7 +146,12 @@ export const ProviderButton = () => {
|
||||
size="small"
|
||||
color="inherit"
|
||||
title="Update Provider"
|
||||
onClick={() => handleUpdate(key)}
|
||||
onClick={() => handleUpdate(key, index)}
|
||||
sx={{
|
||||
animation: updating[index]
|
||||
? `1s linear infinite ${round}`
|
||||
: "none",
|
||||
}}
|
||||
>
|
||||
<RefreshRounded />
|
||||
</IconButton>
|
||||
|
||||
@@ -34,7 +34,7 @@ const RuleItem = (props: Props) => {
|
||||
const { index, value } = props;
|
||||
|
||||
return (
|
||||
<Item>
|
||||
<Item sx={{ borderBottom: "1px solid var(--divider-color)" }}>
|
||||
<Typography
|
||||
color="text.secondary"
|
||||
variant="body2"
|
||||
|
||||
@@ -36,7 +36,7 @@ export const ControllerViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
return (
|
||||
<BaseDialog
|
||||
open={open}
|
||||
title={t("Clash Port")}
|
||||
title={t("External Controller")}
|
||||
contentSx={{ width: 400 }}
|
||||
okBtn={t("Save")}
|
||||
cancelBtn={t("Cancel")}
|
||||
|
||||
@@ -14,17 +14,12 @@ const ItemWrapper = styled("div")`
|
||||
`;
|
||||
|
||||
const HOTKEY_FUNC = [
|
||||
"open_dashboard",
|
||||
"open_or_close_dashboard",
|
||||
"clash_mode_rule",
|
||||
"clash_mode_global",
|
||||
"clash_mode_direct",
|
||||
"clash_mode_script",
|
||||
"toggle_system_proxy",
|
||||
"enable_system_proxy",
|
||||
"disable_system_proxy",
|
||||
"toggle_tun_mode",
|
||||
"enable_tun_mode",
|
||||
"disable_tun_mode",
|
||||
];
|
||||
|
||||
export const HotkeyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
|
||||
@@ -1,16 +1,39 @@
|
||||
import { forwardRef, useImperativeHandle, useState } from "react";
|
||||
import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { List, Switch } from "@mui/material";
|
||||
import { List, Button, Select, MenuItem } from "@mui/material";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { BaseDialog, DialogRef, Notice } from "@/components/base";
|
||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||
import { SettingItem } from "./setting-comp";
|
||||
import { GuardState } from "./guard-state";
|
||||
import { open as openDialog } from "@tauri-apps/api/dialog";
|
||||
import { convertFileSrc } from "@tauri-apps/api/tauri";
|
||||
import { copyIconFile, getAppDir } from "@/services/cmds";
|
||||
import { join } from "@tauri-apps/api/path";
|
||||
|
||||
export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
const { t } = useTranslation();
|
||||
const { verge, patchVerge, mutateVerge } = useVerge();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [commonIcon, setCommonIcon] = useState("");
|
||||
const [sysproxyIcon, setSysproxyIcon] = useState("");
|
||||
const [tunIcon, setTunIcon] = useState("");
|
||||
|
||||
// const { menu_icon } = verge ?? {};
|
||||
useEffect(() => {
|
||||
initIconPath();
|
||||
}, []);
|
||||
|
||||
async function initIconPath() {
|
||||
const appDir = await getAppDir();
|
||||
const icon_dir = await join(appDir, "icons");
|
||||
const common_icon = await join(icon_dir, "common.png");
|
||||
const sysproxy_icon = await join(icon_dir, "sysproxy.png");
|
||||
const tun_icon = await join(icon_dir, "tun.png");
|
||||
setCommonIcon(common_icon);
|
||||
setSysproxyIcon(sysproxy_icon);
|
||||
setTunIcon(tun_icon);
|
||||
}
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
open: () => setOpen(true),
|
||||
@@ -61,6 +84,165 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
<Switch edge="end" />
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem label={t("Proxy Group Icon")}>
|
||||
<GuardState
|
||||
value={verge?.enable_group_icon ?? true}
|
||||
valueProps="checked"
|
||||
onCatch={onError}
|
||||
onFormat={onSwitchFormat}
|
||||
onChange={(e) => onChangeData({ enable_group_icon: e })}
|
||||
onGuard={(e) => patchVerge({ enable_group_icon: e })}
|
||||
>
|
||||
<Switch edge="end" />
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem label={t("Menu Icon")}>
|
||||
<GuardState
|
||||
value={verge?.menu_icon ?? "monochrome"}
|
||||
onCatch={onError}
|
||||
onFormat={(e: any) => e.target.value}
|
||||
onChange={(e) => onChangeData({ menu_icon: e })}
|
||||
onGuard={(e) => patchVerge({ menu_icon: e })}
|
||||
>
|
||||
<Select size="small" sx={{ width: 140, "> div": { py: "7.5px" } }}>
|
||||
<MenuItem value="monochrome">{t("Monochrome")}</MenuItem>
|
||||
<MenuItem value="colorful">{t("Colorful")}</MenuItem>
|
||||
<MenuItem value="disable">{t("Disable")}</MenuItem>
|
||||
</Select>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem label={t("Common Tray Icon")}>
|
||||
<GuardState
|
||||
value={verge?.common_tray_icon}
|
||||
onCatch={onError}
|
||||
onChange={(e) => onChangeData({ common_tray_icon: e })}
|
||||
onGuard={(e) => patchVerge({ common_tray_icon: e })}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="small"
|
||||
startIcon={
|
||||
verge?.common_tray_icon &&
|
||||
commonIcon && (
|
||||
<img height="20px" src={convertFileSrc(commonIcon)} />
|
||||
)
|
||||
}
|
||||
onClick={async () => {
|
||||
if (verge?.common_tray_icon) {
|
||||
onChangeData({ common_tray_icon: false });
|
||||
patchVerge({ common_tray_icon: false });
|
||||
} else {
|
||||
const path = await openDialog({
|
||||
directory: false,
|
||||
multiple: false,
|
||||
filters: [
|
||||
{
|
||||
name: "Tray Icon Image",
|
||||
extensions: ["png"],
|
||||
},
|
||||
],
|
||||
});
|
||||
if (path?.length) {
|
||||
await copyIconFile(`${path}`, "common.png");
|
||||
onChangeData({ common_tray_icon: true });
|
||||
patchVerge({ common_tray_icon: true });
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
{verge?.common_tray_icon ? t("Clear") : t("Browse")}
|
||||
</Button>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem label={t("System Proxy Tray Icon")}>
|
||||
<GuardState
|
||||
value={verge?.sysproxy_tray_icon}
|
||||
onCatch={onError}
|
||||
onChange={(e) => onChangeData({ sysproxy_tray_icon: e })}
|
||||
onGuard={(e) => patchVerge({ sysproxy_tray_icon: e })}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="small"
|
||||
startIcon={
|
||||
verge?.sysproxy_tray_icon &&
|
||||
sysproxyIcon && (
|
||||
<img height="20px" src={convertFileSrc(sysproxyIcon)} />
|
||||
)
|
||||
}
|
||||
onClick={async () => {
|
||||
if (verge?.sysproxy_tray_icon) {
|
||||
onChangeData({ sysproxy_tray_icon: false });
|
||||
patchVerge({ sysproxy_tray_icon: false });
|
||||
} else {
|
||||
const path = await openDialog({
|
||||
directory: false,
|
||||
multiple: false,
|
||||
filters: [
|
||||
{
|
||||
name: "Tray Icon Image",
|
||||
extensions: ["png"],
|
||||
},
|
||||
],
|
||||
});
|
||||
if (path?.length) {
|
||||
await copyIconFile(`${path}`, "sysproxy.png");
|
||||
onChangeData({ sysproxy_tray_icon: true });
|
||||
patchVerge({ sysproxy_tray_icon: true });
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
{verge?.sysproxy_tray_icon ? t("Clear") : t("Browse")}
|
||||
</Button>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem label={t("Tun Tray Icon")}>
|
||||
<GuardState
|
||||
value={verge?.tun_tray_icon}
|
||||
onCatch={onError}
|
||||
onChange={(e) => onChangeData({ tun_tray_icon: e })}
|
||||
onGuard={(e) => patchVerge({ tun_tray_icon: e })}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="small"
|
||||
startIcon={
|
||||
verge?.tun_tray_icon &&
|
||||
tunIcon && <img height="20px" src={convertFileSrc(tunIcon)} />
|
||||
}
|
||||
onClick={async () => {
|
||||
if (verge?.tun_tray_icon) {
|
||||
onChangeData({ tun_tray_icon: false });
|
||||
patchVerge({ tun_tray_icon: false });
|
||||
} else {
|
||||
const path = await openDialog({
|
||||
directory: false,
|
||||
multiple: false,
|
||||
filters: [
|
||||
{
|
||||
name: "Tray Icon Image",
|
||||
extensions: ["png"],
|
||||
},
|
||||
],
|
||||
});
|
||||
if (path?.length) {
|
||||
await copyIconFile(`${path}`, "tun.png");
|
||||
onChangeData({ tun_tray_icon: true });
|
||||
patchVerge({ tun_tray_icon: true });
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
{verge?.tun_tray_icon ? t("Clear") : t("Browse")}
|
||||
</Button>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</List>
|
||||
</BaseDialog>
|
||||
);
|
||||
|
||||
@@ -7,11 +7,10 @@ import {
|
||||
ListItemText,
|
||||
MenuItem,
|
||||
Select,
|
||||
Switch,
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { BaseDialog, DialogRef, Notice } from "@/components/base";
|
||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||
|
||||
export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -21,6 +20,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
const [values, setValues] = useState({
|
||||
appLogLevel: "info",
|
||||
autoCloseConnection: true,
|
||||
autoCheckUpdate: true,
|
||||
enableBuiltinEnhanced: true,
|
||||
proxyLayoutColumn: 6,
|
||||
defaultLatencyTest: "",
|
||||
@@ -34,6 +34,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
setValues({
|
||||
appLogLevel: verge?.app_log_level ?? "info",
|
||||
autoCloseConnection: verge?.auto_close_connection ?? true,
|
||||
autoCheckUpdate: verge?.auto_check_update ?? true,
|
||||
enableBuiltinEnhanced: verge?.enable_builtin_enhanced ?? true,
|
||||
proxyLayoutColumn: verge?.proxy_layout_column || 6,
|
||||
defaultLatencyTest: verge?.default_latency_test || "",
|
||||
@@ -49,6 +50,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
await patchVerge({
|
||||
app_log_level: values.appLogLevel,
|
||||
auto_close_connection: values.autoCloseConnection,
|
||||
auto_check_update: values.autoCheckUpdate,
|
||||
enable_builtin_enhanced: values.enableBuiltinEnhanced,
|
||||
proxy_layout_column: values.proxyLayoutColumn,
|
||||
default_latency_test: values.defaultLatencyTest,
|
||||
@@ -105,6 +107,17 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem sx={{ padding: "5px 2px" }}>
|
||||
<ListItemText primary={t("Auto Check Update")} />
|
||||
<Switch
|
||||
edge="end"
|
||||
checked={values.autoCheckUpdate}
|
||||
onChange={(_, c) =>
|
||||
setValues((v) => ({ ...v, autoCheckUpdate: c }))
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem sx={{ padding: "5px 2px" }}>
|
||||
<ListItemText primary={t("Enable Builtin Enhanced")} />
|
||||
<Switch
|
||||
@@ -194,7 +207,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
spellCheck="false"
|
||||
sx={{ width: 250 }}
|
||||
value={values.defaultLatencyTimeout}
|
||||
placeholder="http://1.1.1.1"
|
||||
placeholder="10000"
|
||||
onChange={(e) =>
|
||||
setValues((v) => ({
|
||||
...v,
|
||||
|
||||
@@ -18,9 +18,11 @@ export const SettingItem: React.FC<ItemProps> = (props) => {
|
||||
const { label, extra, children, secondary } = props;
|
||||
|
||||
const primary = !extra ? (
|
||||
label
|
||||
<Box sx={{ display: "flex", alignItems: "center", fontSize: "14px" }}>
|
||||
<span>{label}</span>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", fontSize: "14px" }}>
|
||||
<span>{label}</span>
|
||||
{extra}
|
||||
</Box>
|
||||
@@ -39,7 +41,17 @@ export const SettingList: React.FC<{
|
||||
children: ReactNode;
|
||||
}> = (props) => (
|
||||
<List>
|
||||
<ListSubheader sx={{ background: "transparent" }} disableSticky>
|
||||
<ListSubheader
|
||||
sx={[
|
||||
{ background: "transparent", fontSize: "16px", fontWeight: "700" },
|
||||
({ palette }) => {
|
||||
return {
|
||||
color: palette.text.primary,
|
||||
};
|
||||
},
|
||||
]}
|
||||
disableSticky
|
||||
>
|
||||
{props.title}
|
||||
</ListSubheader>
|
||||
|
||||
|
||||
71
src/components/setting/mods/stack-mode-switch.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button, ButtonGroup, Tooltip } from "@mui/material";
|
||||
import { checkService } from "@/services/cmds";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import getSystem from "@/utils/get-system";
|
||||
import useSWR from "swr";
|
||||
|
||||
const isWIN = getSystem() === "windows";
|
||||
|
||||
interface Props {
|
||||
value?: string;
|
||||
onChange?: (value: string) => void;
|
||||
}
|
||||
|
||||
export const StackModeSwitch = (props: Props) => {
|
||||
const { value, onChange } = props;
|
||||
const { verge } = useVerge();
|
||||
const { enable_service_mode } = verge ?? {};
|
||||
// service mode
|
||||
const { data: serviceStatus } = useSWR(
|
||||
isWIN ? "checkService" : null,
|
||||
checkService,
|
||||
{
|
||||
revalidateIfStale: false,
|
||||
shouldRetryOnError: false,
|
||||
}
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
title={
|
||||
isWIN && (serviceStatus !== "active" || !enable_service_mode)
|
||||
? t("System and Mixed Can Only be Used in Service Mode")
|
||||
: ""
|
||||
}
|
||||
>
|
||||
<ButtonGroup size="small" sx={{ my: "4px" }}>
|
||||
<Button
|
||||
variant={value?.toLowerCase() === "system" ? "contained" : "outlined"}
|
||||
onClick={() => onChange?.("system")}
|
||||
disabled={
|
||||
isWIN && (serviceStatus !== "active" || !enable_service_mode)
|
||||
}
|
||||
sx={{ textTransform: "capitalize" }}
|
||||
>
|
||||
System
|
||||
</Button>
|
||||
<Button
|
||||
variant={value?.toLowerCase() === "gvisor" ? "contained" : "outlined"}
|
||||
onClick={() => onChange?.("gvisor")}
|
||||
sx={{ textTransform: "capitalize" }}
|
||||
>
|
||||
gVisor
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant={value?.toLowerCase() === "mixed" ? "contained" : "outlined"}
|
||||
onClick={() => onChange?.("mixed")}
|
||||
disabled={
|
||||
isWIN && (serviceStatus !== "active" || !enable_service_mode)
|
||||
}
|
||||
sx={{ textTransform: "capitalize" }}
|
||||
>
|
||||
Mixed
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
@@ -8,13 +8,12 @@ import {
|
||||
ListItem,
|
||||
ListItemText,
|
||||
styled,
|
||||
Switch,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { getSystemProxy } from "@/services/cmds";
|
||||
import { BaseDialog, DialogRef, Notice } from "@/components/base";
|
||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||
|
||||
export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -5,13 +5,14 @@ import {
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
MenuItem,
|
||||
Select,
|
||||
Switch,
|
||||
Box,
|
||||
Typography,
|
||||
Button,
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import { useClash } from "@/hooks/use-clash";
|
||||
import { BaseDialog, DialogRef, Notice } from "@/components/base";
|
||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||
import { StackModeSwitch } from "./stack-mode-switch";
|
||||
|
||||
export const TunViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -20,12 +21,12 @@ export const TunViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [values, setValues] = useState({
|
||||
stack: "gVisor",
|
||||
device: "Mihomo",
|
||||
stack: "gvisor",
|
||||
device: "Meta",
|
||||
autoRoute: true,
|
||||
autoDetectInterface: true,
|
||||
dnsHijack: ["any:53", "tcp://any:53"],
|
||||
strictRoute: true,
|
||||
dnsHijack: ["any:53"],
|
||||
strictRoute: false,
|
||||
mtu: 9000,
|
||||
});
|
||||
|
||||
@@ -33,12 +34,12 @@ export const TunViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
open: () => {
|
||||
setOpen(true);
|
||||
setValues({
|
||||
stack: clash?.tun.stack ?? "gVisor",
|
||||
device: clash?.tun.device ?? "Mihomo",
|
||||
stack: clash?.tun.stack ?? "gvisor",
|
||||
device: clash?.tun.device ?? "Meta",
|
||||
autoRoute: clash?.tun["auto-route"] ?? true,
|
||||
autoDetectInterface: clash?.tun["auto-detect-interface"] ?? true,
|
||||
dnsHijack: clash?.tun["dns-hijack"] ?? ["any:53", "tcp://any:53"],
|
||||
strictRoute: clash?.tun["strict-route"] ?? true,
|
||||
dnsHijack: clash?.tun["dns-hijack"] ?? ["any:53"],
|
||||
strictRoute: clash?.tun["strict-route"] ?? false,
|
||||
mtu: clash?.tun.mtu ?? 9000,
|
||||
});
|
||||
},
|
||||
@@ -73,7 +74,45 @@ export const TunViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
return (
|
||||
<BaseDialog
|
||||
open={open}
|
||||
title={t("Tun Mode")}
|
||||
title={
|
||||
<Box display="flex" justifyContent="space-between" gap={1}>
|
||||
<Typography variant="h6">{t("Tun Mode")}</Typography>
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="small"
|
||||
onClick={async () => {
|
||||
let tun = {
|
||||
stack: "gvisor",
|
||||
device: "Meta",
|
||||
"auto-route": true,
|
||||
"auto-detect-interface": true,
|
||||
"dns-hijack": ["any:53"],
|
||||
"strict-route": false,
|
||||
mtu: 9000,
|
||||
};
|
||||
setValues({
|
||||
stack: "gvisor",
|
||||
device: "Meta",
|
||||
autoRoute: true,
|
||||
autoDetectInterface: true,
|
||||
dnsHijack: ["any:53"],
|
||||
strictRoute: false,
|
||||
mtu: 9000,
|
||||
});
|
||||
await patchClash({ tun });
|
||||
await mutateClash(
|
||||
(old) => ({
|
||||
...(old! || {}),
|
||||
tun,
|
||||
}),
|
||||
false
|
||||
);
|
||||
}}
|
||||
>
|
||||
{t("Reset to Default")}
|
||||
</Button>
|
||||
</Box>
|
||||
}
|
||||
contentSx={{ width: 450 }}
|
||||
okBtn={t("Save")}
|
||||
cancelBtn={t("Cancel")}
|
||||
@@ -84,23 +123,15 @@ export const TunViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
<List>
|
||||
<ListItem sx={{ padding: "5px 2px" }}>
|
||||
<ListItemText primary={t("Stack")} />
|
||||
<Select
|
||||
size="small"
|
||||
sx={{ width: 100, "> div": { py: "7.5px" } }}
|
||||
<StackModeSwitch
|
||||
value={values.stack}
|
||||
onChange={(e) => {
|
||||
onChange={(value) => {
|
||||
setValues((v) => ({
|
||||
...v,
|
||||
stack: e.target.value as string,
|
||||
stack: value,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
{["System", "gVisor", "Mixed"].map((i) => (
|
||||
<MenuItem value={i} key={i}>
|
||||
{i}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem sx={{ padding: "5px 2px" }}>
|
||||
@@ -113,7 +144,7 @@ export const TunViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
spellCheck="false"
|
||||
sx={{ width: 250 }}
|
||||
value={values.device}
|
||||
placeholder="Mihomo"
|
||||
placeholder="Meta"
|
||||
onChange={(e) =>
|
||||
setValues((v) => ({ ...v, device: e.target.value }))
|
||||
}
|
||||
|
||||
@@ -22,10 +22,13 @@ export const WebUIViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
close: () => setOpen(false),
|
||||
}));
|
||||
|
||||
const webUIList = verge?.web_ui_list || [];
|
||||
const webUIList = verge?.web_ui_list || [
|
||||
"https://d.metacubex.one/#?hostname=%host&port=%port&secret=%secret",
|
||||
"https://yacd.metacubex.one/?host=%host&port=%port&secret=%secret",
|
||||
];
|
||||
|
||||
const handleAdd = useLockFn(async (value: string) => {
|
||||
const newList = [value, ...webUIList];
|
||||
const newList = [...webUIList, value];
|
||||
mutateVerge((old) => (old ? { ...old, web_ui_list: newList } : old), false);
|
||||
await patchVerge({ web_ui_list: newList });
|
||||
});
|
||||
@@ -100,18 +103,6 @@ export const WebUIViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
onClose={() => setOpen(false)}
|
||||
onCancel={() => setOpen(false)}
|
||||
>
|
||||
{editing && (
|
||||
<WebUIItem
|
||||
value=""
|
||||
onlyEdit
|
||||
onChange={(v) => {
|
||||
setEditing(false);
|
||||
handleAdd(v || "");
|
||||
}}
|
||||
onCancel={() => setEditing(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!editing && webUIList.length === 0 && (
|
||||
<BaseEmpty
|
||||
text="Empty List"
|
||||
@@ -132,6 +123,17 @@ export const WebUIViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
onOpenUrl={handleOpenUrl}
|
||||
/>
|
||||
))}
|
||||
{editing && (
|
||||
<WebUIItem
|
||||
value=""
|
||||
onlyEdit
|
||||
onChange={(v) => {
|
||||
setEditing(false);
|
||||
handleAdd(v || "");
|
||||
}}
|
||||
onCancel={() => setEditing(false)}
|
||||
/>
|
||||
)}
|
||||
</BaseDialog>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -3,7 +3,6 @@ import { useTranslation } from "react-i18next";
|
||||
import { useLockFn } from "ahooks";
|
||||
import {
|
||||
TextField,
|
||||
Switch,
|
||||
Select,
|
||||
MenuItem,
|
||||
Typography,
|
||||
@@ -11,7 +10,7 @@ import {
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import { ArrowForward, Settings, Shuffle } from "@mui/icons-material";
|
||||
import { DialogRef, Notice } from "@/components/base";
|
||||
import { DialogRef, Notice, Switch } from "@/components/base";
|
||||
import { useClash } from "@/hooks/use-clash";
|
||||
import { GuardState } from "./mods/guard-state";
|
||||
import { WebUIViewer } from "./mods/web-ui-viewer";
|
||||
@@ -118,7 +117,7 @@ const SettingClash = ({ onError }: Props) => {
|
||||
extra={
|
||||
<Tooltip title={t("Random Port")}>
|
||||
<IconButton
|
||||
color={enable_random_port ? "success" : "inherit"}
|
||||
color={enable_random_port ? "primary" : "inherit"}
|
||||
size="small"
|
||||
onClick={() => {
|
||||
Notice.success(t("After restart to take effect"), 1000);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import useSWR from "swr";
|
||||
import { useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { IconButton, Switch, Tooltip } from "@mui/material";
|
||||
import { IconButton, Tooltip } from "@mui/material";
|
||||
import { PrivacyTipRounded, Settings, InfoRounded } from "@mui/icons-material";
|
||||
import { checkService } from "@/services/cmds";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { DialogRef } from "@/components/base";
|
||||
import { DialogRef, Switch } from "@/components/base";
|
||||
import { SettingList, SettingItem } from "./mods/setting-comp";
|
||||
import { GuardState } from "./mods/guard-state";
|
||||
import { ServiceViewer } from "./mods/service-viewer";
|
||||
|
||||
@@ -10,7 +10,13 @@ import {
|
||||
Input,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { exitApp, openAppDir, openCoreDir, openLogsDir } from "@/services/cmds";
|
||||
import {
|
||||
exitApp,
|
||||
openAppDir,
|
||||
openCoreDir,
|
||||
openLogsDir,
|
||||
openDevTools,
|
||||
} from "@/services/cmds";
|
||||
import { ArrowForward } from "@mui/icons-material";
|
||||
import { checkUpdate } from "@tauri-apps/api/updater";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
@@ -27,6 +33,7 @@ import { LayoutViewer } from "./mods/layout-viewer";
|
||||
import { UpdateViewer } from "./mods/update-viewer";
|
||||
import getSystem from "@/utils/get-system";
|
||||
import { routers } from "@/pages/_routers";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
interface Props {
|
||||
onError?: (err: Error) => void;
|
||||
}
|
||||
@@ -167,6 +174,7 @@ const SettingVerge = ({ onError }: Props) => {
|
||||
<Input
|
||||
value={startup_script}
|
||||
disabled
|
||||
sx={{ width: 230 }}
|
||||
endAdornment={
|
||||
<>
|
||||
<Button
|
||||
@@ -303,6 +311,17 @@ const SettingVerge = ({ onError }: Props) => {
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem label={t("Open Dev Tools")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={openDevTools}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem label={t("Exit")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
import { alpha, Box, styled } from "@mui/material";
|
||||
|
||||
export const TestBox = styled(Box)(({ theme, "aria-selected": selected }) => {
|
||||
const { mode, primary, text, grey, background } = theme.palette;
|
||||
const { mode, primary, text } = theme.palette;
|
||||
const key = `${mode}-${!!selected}`;
|
||||
|
||||
const backgroundColor = {
|
||||
"light-true": alpha(primary.main, 0.2),
|
||||
"light-false": alpha(background.paper, 0.75),
|
||||
"dark-true": alpha(primary.main, 0.45),
|
||||
"dark-false": alpha(grey[700], 0.45),
|
||||
}[key]!;
|
||||
const backgroundColor = mode === "light" ? "#ffffff" : "#282A36";
|
||||
|
||||
const color = {
|
||||
"light-true": text.secondary,
|
||||
"light-false": text.secondary,
|
||||
"dark-true": alpha(text.secondary, 0.85),
|
||||
"dark-true": alpha(text.secondary, 0.65),
|
||||
"dark-false": alpha(text.secondary, 0.65),
|
||||
}[key]!;
|
||||
|
||||
const h2color = {
|
||||
"light-true": primary.main,
|
||||
"light-false": text.primary,
|
||||
"dark-true": primary.light,
|
||||
"dark-true": primary.main,
|
||||
"dark-false": text.primary,
|
||||
}[key]!;
|
||||
|
||||
@@ -31,7 +26,7 @@ export const TestBox = styled(Box)(({ theme, "aria-selected": selected }) => {
|
||||
display: "block",
|
||||
cursor: "pointer",
|
||||
textAlign: "left",
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
borderRadius: 8,
|
||||
boxShadow: theme.shadows[2],
|
||||
padding: "8px 16px",
|
||||
boxSizing: "border-box",
|
||||
|
||||
@@ -104,10 +104,10 @@ export const TestItem = (props: Props) => {
|
||||
{icon && icon.trim() !== "" ? (
|
||||
<Box sx={{ display: "flex", justifyContent: "center" }}>
|
||||
{icon.trim().startsWith("http") && (
|
||||
<img src={icon} height="40px" style={{ marginRight: "8px" }} />
|
||||
<img src={icon} height="40px" />
|
||||
)}
|
||||
{icon.trim().startsWith("data") && (
|
||||
<img src={icon} height="40px" style={{ marginRight: "8px" }} />
|
||||
<img src={icon} height="40px" />
|
||||
)}
|
||||
{icon.trim().startsWith("<svg") && (
|
||||
<img
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import useSWR, { mutate } from "swr";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { getAxios, getVersion, updateConfigs } from "@/services/api";
|
||||
import {
|
||||
getAxios,
|
||||
getClashConfig,
|
||||
getVersion,
|
||||
updateConfigs,
|
||||
} from "@/services/api";
|
||||
import { getClashInfo, patchClashConfig } from "@/services/cmds";
|
||||
getClashInfo,
|
||||
patchClashConfig,
|
||||
getRuntimeConfig,
|
||||
} from "@/services/cmds";
|
||||
|
||||
export const useClash = () => {
|
||||
const { data: clash, mutate: mutateClash } = useSWR(
|
||||
"getClashConfig",
|
||||
getClashConfig
|
||||
"getRuntimeConfig",
|
||||
getRuntimeConfig
|
||||
);
|
||||
|
||||
const { data: versionData, mutate: mutateVersion } = useSWR(
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
"Update Interval": "Update Interval",
|
||||
"Use System Proxy": "Use System Proxy",
|
||||
"Use Clash Proxy": "Use Clash Proxy",
|
||||
"Accept Invalid Certs (Danger)": "Allows Invalid Certificates (Danger)",
|
||||
|
||||
"Settings": "Settings",
|
||||
"Clash Setting": "Clash Setting",
|
||||
@@ -110,6 +111,10 @@
|
||||
"Hotkey Setting": "Hotkey Setting",
|
||||
"Traffic Graph": "Traffic Graph",
|
||||
"Memory Usage": "Memory Usage",
|
||||
"Proxy Group Icon": "Proxy Group Icon",
|
||||
"Common Tray Icon": "Common Tray Icon",
|
||||
"System Proxy Tray Icon": "System Proxy Tray Icon",
|
||||
"Tun Tray Icon": "Tun Tray Icon",
|
||||
"Language": "Language",
|
||||
"Open App Dir": "Open App Dir",
|
||||
"Open Core Dir": "Open Core Dir",
|
||||
@@ -134,17 +139,12 @@
|
||||
"Download Speed": "Download Speed",
|
||||
"Upload Speed": "Upload Speed",
|
||||
|
||||
"open_dashboard": "Open Dashboard",
|
||||
"open_or_close_dashboard": "Open/Close Dashboard",
|
||||
"clash_mode_rule": "Rule Mode",
|
||||
"clash_mode_global": "Global Mode",
|
||||
"clash_mode_direct": "Direct Mode",
|
||||
"clash_mode_script": "Script Mode",
|
||||
"toggle_system_proxy": "Toggle System Proxy",
|
||||
"enable_system_proxy": "Enable System Proxy",
|
||||
"disable_system_proxy": "Disable System Proxy",
|
||||
"toggle_tun_mode": "Toggle Tun Mode",
|
||||
"enable_tun_mode": "Enable Tun Mode",
|
||||
"disable_tun_mode": "Disable Tun Mode",
|
||||
"toggle_system_proxy": "Enable/Disable System Proxy",
|
||||
"toggle_tun_mode": "Enable/Disable Tun Mode",
|
||||
|
||||
"App Log Level": "App Log Level",
|
||||
"Auto Close Connections": "Auto Close Connections",
|
||||
@@ -160,7 +160,16 @@
|
||||
"Retain 30 Days": "Retain 30 Days",
|
||||
"Retain 90 Days": "Retain 90 Days",
|
||||
|
||||
"Stack": "Tun Stack",
|
||||
"Device": "Device Name",
|
||||
"Auto Route": "Auto Route",
|
||||
"Strict Route": "Strict Route",
|
||||
"Auto Detect Interface": "Auto Detect Interface",
|
||||
"DNS Hijack": "DNS Hijack",
|
||||
"MTU": "Max Transmission Unit",
|
||||
|
||||
"Portable Updater Error": "The portable version does not support in-app updates. Please manually download and replace it",
|
||||
"Tun Mode Info Windows": "The Tun mode requires granting core-related permissions. Please enable service mode before using it",
|
||||
"Tun Mode Info Unix": "The Tun mode requires granting core-related permissions. Before using it, please authorize the core in the core settings"
|
||||
"Tun Mode Info Unix": "The Tun mode requires granting core-related permissions. Before using it, please authorize the core in the core settings",
|
||||
"System and Mixed Can Only be Used in Service Mode": "System and Mixed Can Only be Used in Service Mode"
|
||||
}
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
"Descriptions": "Описания",
|
||||
"Subscription URL": "URL подписки",
|
||||
"Update Interval": "Интервал обновления",
|
||||
"Use System Proxy": "Использовать системный прокси для обновления",
|
||||
"Use Clash Proxy": "Использовать прокси Clash для обновления",
|
||||
"Accept Invalid Certs (Danger)": "Принимать недействительные сертификаты (Опасно)",
|
||||
|
||||
"Settings": "Настройки",
|
||||
"Clash Setting": "Настройки Clash",
|
||||
@@ -118,17 +121,12 @@
|
||||
"Cancel": "Отмена",
|
||||
"Exit": "Выход",
|
||||
|
||||
"open_dashboard": "Open Dashboard",
|
||||
"open_or_close_dashboard": "Open/Close Dashboard",
|
||||
"clash_mode_rule": "Режим правил",
|
||||
"clash_mode_global": "Глобальный режим",
|
||||
"clash_mode_direct": "Прямой режим",
|
||||
"clash_mode_script": "Скриптовый режим",
|
||||
"toggle_system_proxy": "Переключить режим системного прокси",
|
||||
"enable_system_proxy": "Включить системный прокси",
|
||||
"disable_system_proxy": "Отключить системный прокси",
|
||||
"toggle_tun_mode": "Переключить режим туннеля",
|
||||
"enable_tun_mode": "Включить режим туннеля",
|
||||
"disable_tun_mode": "Отключить режим туннеля",
|
||||
"toggle_system_proxy": "Включить/Отключить системный прокси",
|
||||
"toggle_tun_mode": "Включить/Отключить режим туннеля",
|
||||
|
||||
"Portable Updater Error": "Портативная версия не поддерживает обновление внутри приложения, пожалуйста, скачайте и замените вручную"
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
"Update Interval": "更新间隔",
|
||||
"Use System Proxy": "使用系统代理更新",
|
||||
"Use Clash Proxy": "使用Clash代理更新",
|
||||
"Accept Invalid Certs (Danger)": "允许无效证书 (危险)",
|
||||
|
||||
"Settings": "设置",
|
||||
"Clash Setting": "Clash 设置",
|
||||
@@ -110,11 +111,19 @@
|
||||
"Hotkey Setting": "热键设置",
|
||||
"Traffic Graph": "流量图显",
|
||||
"Memory Usage": "内存使用",
|
||||
"Proxy Group Icon": "代理组图标",
|
||||
"Menu Icon": "菜单图标",
|
||||
"Monochrome": "单色图标",
|
||||
"Colorful": "彩色图标",
|
||||
"Common Tray Icon": "常规托盘图标",
|
||||
"System Proxy Tray Icon": "系统代理托盘图标",
|
||||
"Tun Tray Icon": "Tun模式托盘图标",
|
||||
"Language": "语言设置",
|
||||
"Open App Dir": "应用目录",
|
||||
"Open Core Dir": "内核目录",
|
||||
"Open Logs Dir": "日志目录",
|
||||
"Check for Updates": "检查更新",
|
||||
"Open Dev Tools": "打开开发者工具",
|
||||
"Verge Version": "Verge 版本",
|
||||
"theme.light": "浅色",
|
||||
"theme.dark": "深色",
|
||||
@@ -134,21 +143,16 @@
|
||||
"Download Speed": "下载速度",
|
||||
"Upload Speed": "上传速度",
|
||||
|
||||
"open_dashboard": "打开面板",
|
||||
"open_or_close_dashboard": "打开/关闭面板",
|
||||
"clash_mode_rule": "规则模式",
|
||||
"clash_mode_global": "全局模式",
|
||||
"clash_mode_direct": "直连模式",
|
||||
"clash_mode_script": "脚本模式",
|
||||
"toggle_system_proxy": "切换系统代理",
|
||||
"enable_system_proxy": "开启系统代理",
|
||||
"disable_system_proxy": "关闭系统代理",
|
||||
"toggle_tun_mode": "切换Tun模式",
|
||||
"enable_tun_mode": "开启Tun模式",
|
||||
"disable_tun_mode": "关闭Tun模式",
|
||||
"toggle_system_proxy": "打开/关闭系统代理",
|
||||
"toggle_tun_mode": "打开/关闭Tun模式",
|
||||
|
||||
"App Log Level": "App日志等级",
|
||||
"Auto Close Connections": "自动关闭连接",
|
||||
"Enable Clash Fields Filter": "开启Clash字段过滤",
|
||||
"Auto Check Update": "自动检查更新",
|
||||
"Enable Builtin Enhanced": "开启内建增强功能",
|
||||
"Proxy Layout Column": "代理页布局列数",
|
||||
"Default Latency Test": "默认测试链接",
|
||||
@@ -160,7 +164,17 @@
|
||||
"Retain 30 Days": "保留30天",
|
||||
"Retain 90 Days": "保留90天",
|
||||
|
||||
"Stack": "Tun 模式堆栈",
|
||||
"Device": "Tun 网卡名称",
|
||||
"Auto Route": "自动设置全局路由",
|
||||
"Strict Route": "严格路由",
|
||||
"Auto Detect Interface": "自动选择流量出口接口",
|
||||
"DNS Hijack": "DNS 劫持",
|
||||
"MTU": "最大传输单元",
|
||||
"Reset to Default": "重置为默认值",
|
||||
|
||||
"Portable Updater Error": "便携版不支持应用内更新,请手动下载替换",
|
||||
"Tun Mode Info Windows": "Tun模式需要授予内核相关权限,使用前请先开启服务模式",
|
||||
"Tun Mode Info Unix": "Tun模式需要授予内核相关权限,使用前请先在内核设置中给内核授权"
|
||||
"Tun Mode Info Unix": "Tun模式需要授予内核相关权限,使用前请先在内核设置中给内核授权",
|
||||
"System and Mixed Can Only be Used in Service Mode": "System和Mixed只能在服务模式下使用"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ import { routers } from "./_routers";
|
||||
import { getAxios } from "@/services/api";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import LogoSvg from "@/assets/image/logo.svg?react";
|
||||
import LogoSvg_dark from "@/assets/image/logo_dark.svg?react";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { BaseErrorBoundary, Notice } from "@/components/base";
|
||||
import { LayoutItem } from "@/components/layout/layout-item";
|
||||
import { LayoutControl } from "@/components/layout/layout-control";
|
||||
@@ -31,8 +34,9 @@ dayjs.extend(relativeTime);
|
||||
const OS = getSystem();
|
||||
|
||||
const Layout = () => {
|
||||
const [mode] = useRecoilState(atomThemeMode);
|
||||
const isDark = mode === "light" ? false : true;
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { theme } = useCustomTheme();
|
||||
|
||||
const { verge } = useVerge();
|
||||
@@ -100,9 +104,6 @@ const Layout = () => {
|
||||
square
|
||||
elevation={0}
|
||||
className={`${OS} layout`}
|
||||
onPointerDown={(e: any) => {
|
||||
if (e.target?.dataset?.windrag) appWindow.startDragging();
|
||||
}}
|
||||
onContextMenu={(e) => {
|
||||
// only prevent it on Windows
|
||||
const validList = ["input", "textarea"];
|
||||
@@ -121,34 +122,45 @@ const Layout = () => {
|
||||
({ palette }) => ({
|
||||
bgcolor: palette.background.paper,
|
||||
}),
|
||||
OS === "linux"
|
||||
? {
|
||||
borderRadius: "8px",
|
||||
border: "2px solid var(--divider-color)",
|
||||
width: "calc(100vw - 4px)",
|
||||
height: "calc(100vh - 4px)",
|
||||
}
|
||||
: {},
|
||||
]}
|
||||
>
|
||||
<div className="layout__left" data-windrag>
|
||||
<div className="the-logo" data-windrag>
|
||||
<LogoSvg />
|
||||
|
||||
{!portableFlag && <UpdateButton className="the-newbtn" />}
|
||||
<div className="layout__left" data-tauri-drag-region="true">
|
||||
<div className="the-logo" data-tauri-drag-region="true">
|
||||
{!isDark ? <LogoSvg /> : <LogoSvg_dark />}
|
||||
{<UpdateButton className="the-newbtn" />}
|
||||
</div>
|
||||
|
||||
<List className="the-menu">
|
||||
{routers.map((router) => (
|
||||
<LayoutItem key={router.label} to={router.link}>
|
||||
<LayoutItem
|
||||
key={router.label}
|
||||
to={router.link}
|
||||
icon={router.icon}
|
||||
>
|
||||
{t(router.label)}
|
||||
</LayoutItem>
|
||||
))}
|
||||
</List>
|
||||
|
||||
<div className="the-traffic" data-windrag>
|
||||
<div className="the-traffic">
|
||||
<LayoutTraffic />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="layout__right" data-windrag>
|
||||
{OS === "windows" && (
|
||||
<div className="the-bar">
|
||||
<LayoutControl />
|
||||
<div className="layout__right">
|
||||
{
|
||||
<div className="the-bar" data-tauri-drag-region="true">
|
||||
{OS !== "macos" && <LayoutControl />}
|
||||
</div>
|
||||
)}
|
||||
}
|
||||
|
||||
<TransitionGroup className="the-content">
|
||||
<CSSTransition
|
||||
|
||||
@@ -6,40 +6,63 @@ import SettingsPage from "./settings";
|
||||
import ConnectionsPage from "./connections";
|
||||
import RulesPage from "./rules";
|
||||
|
||||
import ProxiesSvg from "@/assets/image/itemicon/proxies.svg?react";
|
||||
import ProfilesSvg from "@/assets/image/itemicon/profiles.svg?react";
|
||||
import ConnectionsSvg from "@/assets/image/itemicon/connections.svg?react";
|
||||
import RulesSvg from "@/assets/image/itemicon/rules.svg?react";
|
||||
import LogsSvg from "@/assets/image/itemicon/logs.svg?react";
|
||||
import TestSvg from "@/assets/image/itemicon/test.svg?react";
|
||||
import SettingsSvg from "@/assets/image/itemicon/settings.svg?react";
|
||||
|
||||
import WifiRoundedIcon from "@mui/icons-material/WifiRounded";
|
||||
import DnsRoundedIcon from "@mui/icons-material/DnsRounded";
|
||||
import LanguageRoundedIcon from "@mui/icons-material/LanguageRounded";
|
||||
import ForkRightRoundedIcon from "@mui/icons-material/ForkRightRounded";
|
||||
import SubjectRoundedIcon from "@mui/icons-material/SubjectRounded";
|
||||
import WifiTetheringRoundedIcon from "@mui/icons-material/WifiTetheringRounded";
|
||||
import SettingsRoundedIcon from "@mui/icons-material/SettingsRounded";
|
||||
|
||||
export const routers = [
|
||||
{
|
||||
label: "Label-Proxies",
|
||||
link: "/",
|
||||
icon: [<WifiRoundedIcon />, <ProxiesSvg />],
|
||||
ele: ProxiesPage,
|
||||
},
|
||||
{
|
||||
label: "Label-Profiles",
|
||||
link: "/profile",
|
||||
icon: [<DnsRoundedIcon />, <ProfilesSvg />],
|
||||
ele: ProfilesPage,
|
||||
},
|
||||
{
|
||||
label: "Label-Connections",
|
||||
link: "/connections",
|
||||
icon: [<LanguageRoundedIcon />, <ConnectionsSvg />],
|
||||
ele: ConnectionsPage,
|
||||
},
|
||||
{
|
||||
label: "Label-Rules",
|
||||
link: "/rules",
|
||||
icon: [<ForkRightRoundedIcon />, <RulesSvg />],
|
||||
ele: RulesPage,
|
||||
},
|
||||
{
|
||||
label: "Label-Logs",
|
||||
link: "/logs",
|
||||
icon: [<SubjectRoundedIcon />, <LogsSvg />],
|
||||
ele: LogsPage,
|
||||
},
|
||||
{
|
||||
label: "Label-Test",
|
||||
link: "/test",
|
||||
icon: [<WifiTetheringRoundedIcon />, <TestSvg />],
|
||||
ele: TestPage,
|
||||
},
|
||||
{
|
||||
label: "Label-Settings",
|
||||
link: "/settings",
|
||||
icon: [<SettingsRoundedIcon />, <SettingsSvg />],
|
||||
ele: SettingsPage,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -3,16 +3,16 @@ const OS = getSystem();
|
||||
|
||||
// default theme setting
|
||||
export const defaultTheme = {
|
||||
primary_color: "#1867c0",
|
||||
secondary_color: "#3a88bb",
|
||||
primary_text: "#1d1d1f",
|
||||
secondary_text: "#424245",
|
||||
info_color: "#0288d1",
|
||||
error_color: "#d32f2f",
|
||||
warning_color: "#ed6c02",
|
||||
success_color: "#2e7d32",
|
||||
background_color: "#ffffff",
|
||||
font_family: `"Roboto", "Helvetica", "Arial", sans-serif, ${
|
||||
primary_color: "#007AFF",
|
||||
secondary_color: "#fc9b76",
|
||||
primary_text: "#000000",
|
||||
secondary_text: "#3c3c4399",
|
||||
info_color: "#007AFF",
|
||||
error_color: "#FF3B30",
|
||||
warning_color: "#FF9500",
|
||||
success_color: "#06943D",
|
||||
background_color: "#f5f5f5",
|
||||
font_family: `-apple-system, BlinkMacSystemFont,"Microsoft YaHei UI", "Microsoft YaHei", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", ${
|
||||
OS === "windows" ? "twemoji mozilla" : ""
|
||||
}`,
|
||||
};
|
||||
@@ -20,7 +20,13 @@ export const defaultTheme = {
|
||||
// dark mode
|
||||
export const defaultDarkTheme = {
|
||||
...defaultTheme,
|
||||
primary_text: "#E8E8ED",
|
||||
background_color: "#181818",
|
||||
secondary_text: "#bbbbbb",
|
||||
primary_color: "#0A84FF",
|
||||
secondary_color: "#FF9F0A",
|
||||
primary_text: "#ffffff",
|
||||
background_color: "#2e303d",
|
||||
secondary_text: "#ebebf599",
|
||||
info_color: "#0A84FF",
|
||||
error_color: "#FF453A",
|
||||
warning_color: "#FF9F0A",
|
||||
success_color: "#30D158",
|
||||
};
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
ConnectionDetailRef,
|
||||
} from "@/components/connection/connection-detail";
|
||||
import parseTraffic from "@/utils/parse-traffic";
|
||||
import { useCustomTheme } from "@/components/layout/use-custom-theme";
|
||||
|
||||
const initConn = { uploadTotal: 0, downloadTotal: 0, connections: [] };
|
||||
|
||||
@@ -33,7 +34,8 @@ type OrderFunc = (list: IConnectionsItem[]) => IConnectionsItem[];
|
||||
const ConnectionsPage = () => {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { clashInfo } = useClashInfo();
|
||||
|
||||
const { theme } = useCustomTheme();
|
||||
const isDark = theme.palette.mode === "dark";
|
||||
const [filterText, setFilterText] = useState("");
|
||||
const [curOrderOpt, setOrderOpt] = useState("Default");
|
||||
const [connData, setConnData] = useState<IConnections>(initConn);
|
||||
@@ -106,7 +108,6 @@ const ConnectionsPage = () => {
|
||||
|
||||
useEffect(() => {
|
||||
if (!clashInfo) return;
|
||||
|
||||
const { server = "", secret = "" } = clashInfo;
|
||||
connect(`ws://${server}/connections?token=${encodeURIComponent(secret)}`);
|
||||
|
||||
@@ -125,7 +126,7 @@ const ConnectionsPage = () => {
|
||||
title={t("Connections")}
|
||||
contentStyle={{ height: "100%" }}
|
||||
header={
|
||||
<Box sx={{ mt: 1, display: "flex", alignItems: "center", gap: 2 }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
|
||||
<Box sx={{ mx: 1 }}>Download: {parseTraffic(download)}</Box>
|
||||
<Box sx={{ mx: 1 }}>Upload: {parseTraffic(upload)}</Box>
|
||||
<IconButton
|
||||
@@ -198,7 +199,15 @@ const ConnectionsPage = () => {
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box height="calc(100% - 50px)" sx={{ userSelect: "text" }}>
|
||||
<Box
|
||||
height="calc(100% - 65px)"
|
||||
sx={{
|
||||
userSelect: "text",
|
||||
margin: "10px",
|
||||
borderRadius: "8px",
|
||||
bgcolor: isDark ? "#282a36" : "#ffffff",
|
||||
}}
|
||||
>
|
||||
{filterConn.length === 0 ? (
|
||||
<BaseEmpty text="No Connections" />
|
||||
) : isTableLayout ? (
|
||||
|
||||
@@ -18,12 +18,14 @@ import {
|
||||
import { atomEnableLog, atomLogData } from "@/services/states";
|
||||
import { BaseEmpty, BasePage } from "@/components/base";
|
||||
import LogItem from "@/components/log/log-item";
|
||||
import { useCustomTheme } from "@/components/layout/use-custom-theme";
|
||||
|
||||
const LogPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const [logData, setLogData] = useRecoilState(atomLogData);
|
||||
const [enableLog, setEnableLog] = useRecoilState(atomEnableLog);
|
||||
|
||||
const { theme } = useCustomTheme();
|
||||
const isDark = theme.palette.mode === "dark";
|
||||
const [logState, setLogState] = useState("all");
|
||||
const [filterText, setFilterText] = useState("");
|
||||
|
||||
@@ -42,7 +44,7 @@ const LogPage = () => {
|
||||
title={t("Logs")}
|
||||
contentStyle={{ height: "100%" }}
|
||||
header={
|
||||
<Box sx={{ mt: 1, display: "flex", alignItems: "center", gap: 2 }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
|
||||
<IconButton
|
||||
size="small"
|
||||
color="inherit"
|
||||
@@ -107,7 +109,14 @@ const LogPage = () => {
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box height="calc(100% - 50px)">
|
||||
<Box
|
||||
height="calc(100% - 65px)"
|
||||
sx={{
|
||||
margin: "10px",
|
||||
borderRadius: "8px",
|
||||
bgcolor: isDark ? "#282a36" : "#ffffff",
|
||||
}}
|
||||
>
|
||||
{filterLogs.length > 0 ? (
|
||||
<Virtuoso
|
||||
initialTopMostItemIndex={999}
|
||||
|
||||
@@ -2,7 +2,15 @@ import useSWR, { mutate } from "swr";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useSetRecoilState } from "recoil";
|
||||
import { Box, Button, Grid, IconButton, Stack, TextField } from "@mui/material";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Grid,
|
||||
IconButton,
|
||||
Stack,
|
||||
TextField,
|
||||
Divider,
|
||||
} from "@mui/material";
|
||||
import {
|
||||
DndContext,
|
||||
closestCenter,
|
||||
@@ -19,7 +27,7 @@ import {
|
||||
import { LoadingButton } from "@mui/lab";
|
||||
import {
|
||||
ClearRounded,
|
||||
ContentCopyRounded,
|
||||
ContentPasteRounded,
|
||||
LocalFireDepartmentRounded,
|
||||
RefreshRounded,
|
||||
TextSnippetOutlined,
|
||||
@@ -46,6 +54,8 @@ import { ProfileMore } from "@/components/profile/profile-more";
|
||||
import { useProfiles } from "@/hooks/use-profiles";
|
||||
import { ConfigViewer } from "@/components/setting/mods/config-viewer";
|
||||
import { throttle } from "lodash-es";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
|
||||
const ProfilePage = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -235,12 +245,19 @@ const ProfilePage = () => {
|
||||
const text = await navigator.clipboard.readText();
|
||||
if (text) setUrl(text);
|
||||
};
|
||||
const [mode] = useRecoilState(atomThemeMode);
|
||||
const islight = mode === "light" ? true : false;
|
||||
const dividercolor = islight
|
||||
? "rgba(0, 0, 0, 0.06)"
|
||||
: "rgba(255, 255, 255, 0.06)";
|
||||
|
||||
return (
|
||||
<BasePage
|
||||
full
|
||||
title={t("Profiles")}
|
||||
contentStyle={{ height: "100%" }}
|
||||
header={
|
||||
<Box sx={{ mt: 1, display: "flex", alignItems: "center", gap: 1 }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
|
||||
<IconButton
|
||||
size="small"
|
||||
color="inherit"
|
||||
@@ -270,7 +287,18 @@ const ProfilePage = () => {
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Stack direction="row" spacing={1} sx={{ mb: 2 }}>
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={1}
|
||||
sx={{
|
||||
pt: 1,
|
||||
mb: 0.5,
|
||||
mx: "10px",
|
||||
height: "36px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<TextField
|
||||
hiddenLabel
|
||||
fullWidth
|
||||
@@ -291,7 +319,7 @@ const ProfilePage = () => {
|
||||
title={t("Paste")}
|
||||
onClick={onCopyLink}
|
||||
>
|
||||
<ContentCopyRounded fontSize="inherit" />
|
||||
<ContentPasteRounded fontSize="inherit" />
|
||||
</IconButton>
|
||||
) : (
|
||||
<IconButton
|
||||
@@ -310,6 +338,7 @@ const ProfilePage = () => {
|
||||
loading={loading}
|
||||
variant="contained"
|
||||
size="small"
|
||||
sx={{ borderRadius: "6px" }}
|
||||
onClick={onImport}
|
||||
>
|
||||
{t("Import")}
|
||||
@@ -317,60 +346,82 @@ const ProfilePage = () => {
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
sx={{ borderRadius: "6px" }}
|
||||
onClick={() => viewerRef.current?.create()}
|
||||
>
|
||||
{t("New")}
|
||||
</Button>
|
||||
</Stack>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragEnd={onDragEnd}
|
||||
<Box
|
||||
sx={{
|
||||
pt: 1,
|
||||
mb: 0.5,
|
||||
pl: "10px",
|
||||
mr: "10px",
|
||||
height: "calc(100% - 68px)",
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ mb: 4.5 }}>
|
||||
<Grid container spacing={{ xs: 1, lg: 1 }}>
|
||||
<SortableContext
|
||||
items={regularItems.map((x) => {
|
||||
return x.uid;
|
||||
})}
|
||||
>
|
||||
{regularItems.map((item) => (
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragEnd={onDragEnd}
|
||||
>
|
||||
<Box sx={{ mb: 1.5 }}>
|
||||
<Grid container spacing={{ xs: 1, lg: 1 }}>
|
||||
<SortableContext
|
||||
items={regularItems.map((x) => {
|
||||
return x.uid;
|
||||
})}
|
||||
>
|
||||
{regularItems.map((item) => (
|
||||
<Grid item xs={12} sm={6} md={4} lg={3} key={item.file}>
|
||||
<ProfileItem
|
||||
id={item.uid}
|
||||
selected={profiles.current === item.uid}
|
||||
activating={activating === item.uid}
|
||||
itemData={item}
|
||||
onSelect={(f) => onSelect(item.uid, f)}
|
||||
onEdit={() => viewerRef.current?.edit(item)}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</SortableContext>
|
||||
</Grid>
|
||||
</Box>
|
||||
</DndContext>
|
||||
|
||||
{enhanceItems.length > 0 && (
|
||||
<Divider
|
||||
variant="middle"
|
||||
flexItem
|
||||
sx={{ width: `calc(100% - 32px)`, borderColor: dividercolor }}
|
||||
></Divider>
|
||||
)}
|
||||
|
||||
{enhanceItems.length > 0 && (
|
||||
<Box sx={{ mt: 1.5 }}>
|
||||
<Grid container spacing={{ xs: 1, lg: 1 }}>
|
||||
{enhanceItems.map((item) => (
|
||||
<Grid item xs={12} sm={6} md={4} lg={3} key={item.file}>
|
||||
<ProfileItem
|
||||
id={item.uid}
|
||||
selected={profiles.current === item.uid}
|
||||
activating={activating === item.uid}
|
||||
<ProfileMore
|
||||
selected={!!chain.includes(item.uid)}
|
||||
itemData={item}
|
||||
onSelect={(f) => onSelect(item.uid, f)}
|
||||
enableNum={chain.length || 0}
|
||||
logInfo={chainLogs[item.uid]}
|
||||
onEnable={() => onEnable(item.uid)}
|
||||
onDisable={() => onDisable(item.uid)}
|
||||
onDelete={() => onDelete(item.uid)}
|
||||
onMoveTop={() => onMoveTop(item.uid)}
|
||||
onMoveEnd={() => onMoveEnd(item.uid)}
|
||||
onEdit={() => viewerRef.current?.edit(item)}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</SortableContext>
|
||||
</Grid>
|
||||
</Box>
|
||||
</DndContext>
|
||||
|
||||
{enhanceItems.length > 0 && (
|
||||
<Grid container spacing={{ xs: 2, lg: 2 }}>
|
||||
{enhanceItems.map((item) => (
|
||||
<Grid item xs={12} sm={6} md={4} lg={3} key={item.file}>
|
||||
<ProfileMore
|
||||
selected={!!chain.includes(item.uid)}
|
||||
itemData={item}
|
||||
enableNum={chain.length || 0}
|
||||
logInfo={chainLogs[item.uid]}
|
||||
onEnable={() => onEnable(item.uid)}
|
||||
onDisable={() => onDisable(item.uid)}
|
||||
onDelete={() => onDelete(item.uid)}
|
||||
onMoveTop={() => onMoveTop(item.uid)}
|
||||
onMoveEnd={() => onMoveEnd(item.uid)}
|
||||
onEdit={() => viewerRef.current?.edit(item)}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<ProfileViewer ref={viewerRef} onChange={() => mutateProfiles()} />
|
||||
<ConfigViewer ref={configRef} />
|
||||
</BasePage>
|
||||
|
||||
@@ -7,11 +7,13 @@ import { getRules } from "@/services/api";
|
||||
import { BaseEmpty, BasePage } from "@/components/base";
|
||||
import RuleItem from "@/components/rule/rule-item";
|
||||
import { ProviderButton } from "@/components/rule/provider-button";
|
||||
import { useCustomTheme } from "@/components/layout/use-custom-theme";
|
||||
|
||||
const RulesPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const { data = [] } = useSWR("getRules", getRules);
|
||||
|
||||
const { theme } = useCustomTheme();
|
||||
const isDark = theme.palette.mode === "dark";
|
||||
const [filterText, setFilterText] = useState("");
|
||||
|
||||
const rules = useMemo(() => {
|
||||
@@ -53,7 +55,14 @@ const RulesPage = () => {
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box height="calc(100% - 50px)">
|
||||
<Box
|
||||
height="calc(100% - 65px)"
|
||||
sx={{
|
||||
margin: "10px",
|
||||
borderRadius: "8px",
|
||||
bgcolor: isDark ? "#282a36" : "#ffffff",
|
||||
}}
|
||||
>
|
||||
{rules.length > 0 ? (
|
||||
<Virtuoso
|
||||
data={rules}
|
||||
|
||||
@@ -7,6 +7,9 @@ import { openWebUrl } from "@/services/cmds";
|
||||
import SettingVerge from "@/components/setting/setting-verge";
|
||||
import SettingClash from "@/components/setting/setting-clash";
|
||||
import SettingSystem from "@/components/setting/setting-system";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { useCustomTheme } from "@/components/layout/use-custom-theme";
|
||||
|
||||
const SettingPage = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -19,12 +22,16 @@ const SettingPage = () => {
|
||||
return openWebUrl("https://github.com/clash-verge-rev/clash-verge-rev");
|
||||
});
|
||||
|
||||
const [mode] = useRecoilState(atomThemeMode);
|
||||
const isDark = mode === "light" ? false : true;
|
||||
const { theme } = useCustomTheme();
|
||||
|
||||
return (
|
||||
<BasePage
|
||||
title={t("Settings")}
|
||||
header={
|
||||
<IconButton
|
||||
size="small"
|
||||
size="medium"
|
||||
color="inherit"
|
||||
title="@clash-verge-rev/clash-verge-rev"
|
||||
onClick={toGithubRepo}
|
||||
@@ -33,17 +40,33 @@ const SettingPage = () => {
|
||||
</IconButton>
|
||||
}
|
||||
>
|
||||
<Grid container spacing={{ xs: 1, lg: 1 }}>
|
||||
<Grid container spacing={{ xs: 1.5, lg: 1.5 }}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Box sx={{ borderRadius: 1, boxShadow: 2, marginBottom: 1 }}>
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: 2,
|
||||
marginBottom: 1.5,
|
||||
backgroundColor: isDark ? "#282a36" : "#ffffff",
|
||||
}}
|
||||
>
|
||||
<SettingSystem onError={onError} />
|
||||
</Box>
|
||||
<Box sx={{ borderRadius: 1, boxShadow: 2 }}>
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: 2,
|
||||
backgroundColor: isDark ? "#282a36" : "#ffffff",
|
||||
}}
|
||||
>
|
||||
<SettingClash onError={onError} />
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Box sx={{ borderRadius: 1, boxShadow: 2 }}>
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: 2,
|
||||
backgroundColor: isDark ? "#282a36" : "#ffffff",
|
||||
}}
|
||||
>
|
||||
<SettingVerge onError={onError} />
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
@@ -111,9 +111,10 @@ const TestPage = () => {
|
||||
|
||||
return (
|
||||
<BasePage
|
||||
full
|
||||
title={t("Test")}
|
||||
header={
|
||||
<Box sx={{ mt: 1, display: "flex", alignItems: "center", gap: 1 }}>
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
@@ -131,32 +132,40 @@ const TestPage = () => {
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragEnd={onDragEnd}
|
||||
<Box
|
||||
sx={{
|
||||
pt: 1.25,
|
||||
mb: 0.5,
|
||||
px: "10px",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ mb: 4.5 }}>
|
||||
<Grid container spacing={{ xs: 1, lg: 1 }}>
|
||||
<SortableContext
|
||||
items={testList.map((x) => {
|
||||
return x.uid;
|
||||
})}
|
||||
>
|
||||
{testList.map((item) => (
|
||||
<Grid item xs={6} sm={4} md={3} lg={2} key={item.uid}>
|
||||
<TestItem
|
||||
id={item.uid}
|
||||
itemData={item}
|
||||
onEdit={() => viewerRef.current?.edit(item)}
|
||||
onDelete={onDeleteTestListItem}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</SortableContext>
|
||||
</Grid>
|
||||
</Box>
|
||||
</DndContext>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragEnd={onDragEnd}
|
||||
>
|
||||
<Box sx={{ mb: 4.5 }}>
|
||||
<Grid container spacing={{ xs: 1, lg: 1 }}>
|
||||
<SortableContext
|
||||
items={testList.map((x) => {
|
||||
return x.uid;
|
||||
})}
|
||||
>
|
||||
{testList.map((item) => (
|
||||
<Grid item xs={6} sm={4} md={3} lg={2} key={item.uid}>
|
||||
<TestItem
|
||||
id={item.uid}
|
||||
itemData={item}
|
||||
onEdit={() => viewerRef.current?.edit(item)}
|
||||
onDelete={onDeleteTestListItem}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</SortableContext>
|
||||
</Grid>
|
||||
</Box>
|
||||
</DndContext>
|
||||
</Box>
|
||||
<TestViewer ref={viewerRef} onChange={onTestListItemChange} />
|
||||
</BasePage>
|
||||
);
|
||||
|
||||
@@ -90,8 +90,9 @@ export async function getClashInfo() {
|
||||
return invoke<IClashInfo | null>("get_clash_info");
|
||||
}
|
||||
|
||||
// Get runtime config which controlled by verge
|
||||
export async function getRuntimeConfig() {
|
||||
return invoke<any | null>("get_runtime_config");
|
||||
return invoke<IConfigData | null>("get_runtime_config");
|
||||
}
|
||||
|
||||
export async function getRuntimeYaml() {
|
||||
@@ -138,6 +139,10 @@ export async function grantPermission(core: string) {
|
||||
return invoke<void>("grant_permission", { core });
|
||||
}
|
||||
|
||||
export async function getAppDir() {
|
||||
return invoke<string>("get_app_dir");
|
||||
}
|
||||
|
||||
export async function openAppDir() {
|
||||
return invoke<void>("open_app_dir").catch((err) =>
|
||||
Notice.error(err?.message || err.toString(), 1500)
|
||||
@@ -208,6 +213,17 @@ export async function getPortableFlag() {
|
||||
return invoke<boolean>("get_portable_flag");
|
||||
}
|
||||
|
||||
export async function openDevTools() {
|
||||
return invoke("open_devtools");
|
||||
}
|
||||
|
||||
export async function exitApp() {
|
||||
return invoke("exit_app");
|
||||
}
|
||||
|
||||
export async function copyIconFile(
|
||||
path: string,
|
||||
name: "common.png" | "sysproxy.png" | "tun.png"
|
||||
) {
|
||||
return invoke<void>("copy_icon_file", { path, name });
|
||||
}
|
||||
|
||||
7
src/services/types.d.ts
vendored
@@ -173,6 +173,7 @@ interface IProfileOption {
|
||||
with_proxy?: boolean;
|
||||
self_proxy?: boolean;
|
||||
update_interval?: number;
|
||||
danger_accept_invalid_certs?: boolean;
|
||||
}
|
||||
|
||||
interface IProfilesConfig {
|
||||
@@ -200,6 +201,11 @@ interface IVergeConfig {
|
||||
theme_mode?: "light" | "dark" | "system";
|
||||
traffic_graph?: boolean;
|
||||
enable_memory_usage?: boolean;
|
||||
enable_group_icon?: boolean;
|
||||
menu_icon?: "monochrome" | "colorful" | "disable";
|
||||
common_tray_icon?: boolean;
|
||||
sysproxy_tray_icon?: boolean;
|
||||
tun_tray_icon?: boolean;
|
||||
enable_tun_mode?: boolean;
|
||||
enable_auto_launch?: boolean;
|
||||
enable_service_mode?: boolean;
|
||||
@@ -227,6 +233,7 @@ interface IVergeConfig {
|
||||
css_injection?: string;
|
||||
};
|
||||
auto_close_connection?: boolean;
|
||||
auto_check_update?: boolean;
|
||||
default_latency_test?: string;
|
||||
default_latency_timeout?: number;
|
||||
enable_builtin_enhanced?: boolean;
|
||||
|
||||