mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-15 13:50:47 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91c14211c6 | ||
|
|
1ea07c458b | ||
|
|
591add6e0c | ||
|
|
b99fff66df | ||
|
|
f54ba05b00 | ||
|
|
6596fb00c7 | ||
|
|
df0b5a80dc | ||
|
|
8cdbb31dbe | ||
|
|
0be4b1222d | ||
|
|
18a6bfd73a | ||
|
|
5e2271b237 | ||
|
|
798999d490 | ||
|
|
0e68c5e8bc | ||
|
|
9694af82f4 | ||
|
|
28a4386975 | ||
|
|
a238f7beba | ||
|
|
75ba16281b | ||
|
|
ad65a278d4 | ||
|
|
a2320b3f8d | ||
|
|
ae12853ad0 | ||
|
|
68adf6dc2f | ||
|
|
f88989bd4b |
@@ -61,7 +61,7 @@ jobs:
|
||||
- name: Tauri build
|
||||
uses: tauri-apps/tauri-action@0e558392ccadcb49bcc89e7df15a400e8f0c954d
|
||||
# enable cache even though failed
|
||||
# continue-on-error: true
|
||||
continue-on-error: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
name: Test CI
|
||||
|
||||
on: workflow_dispatch
|
||||
|
||||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
RUST_BACKTRACE: short
|
||||
|
||||
jobs:
|
||||
release:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: startsWith(github.repository, 'zzzgydi')
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 14
|
||||
|
||||
- name: Install Dependencies (ubuntu only)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf
|
||||
|
||||
- name: Get yarn cache dir path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- name: Yarn Cache
|
||||
uses: actions/cache@v2
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Yarn install and check
|
||||
run: |
|
||||
yarn install --network-timeout 1000000
|
||||
yarn run check
|
||||
|
||||
- name: Tauri build
|
||||
uses: tauri-apps/tauri-action@0e558392ccadcb49bcc89e7df15a400e8f0c954d
|
||||
# enable cache even though failed
|
||||
continue-on-error: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
@@ -1,3 +1,19 @@
|
||||
## v1.0.1
|
||||
|
||||
### Features
|
||||
|
||||
- adjust default theme settings
|
||||
- reduce gpu usage of traffic graph when hidden
|
||||
- supports more remote profile response header setting
|
||||
- check remote profile data format when imported
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- service mode install and start issue (Windows)
|
||||
- fix launch panic (Some Windows)
|
||||
|
||||
---
|
||||
|
||||
## v1.0.0
|
||||
|
||||
### Features
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clash-verge",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"license": "GPL-3.0",
|
||||
"scripts": {
|
||||
"dev": "tauri dev",
|
||||
@@ -18,9 +18,9 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.8.2",
|
||||
"@emotion/styled": "^11.8.1",
|
||||
"@mui/icons-material": "^5.6.1",
|
||||
"@mui/material": "^5.6.1",
|
||||
"@tauri-apps/api": "^1.0.0-rc.3",
|
||||
"@mui/icons-material": "^5.6.2",
|
||||
"@mui/material": "^5.6.4",
|
||||
"@tauri-apps/api": "^1.0.0-rc.4",
|
||||
"ahooks": "^3.2.0",
|
||||
"axios": "^0.26.0",
|
||||
"dayjs": "^1.11.0",
|
||||
@@ -37,7 +37,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/github": "^5.0.0",
|
||||
"@tauri-apps/cli": "^1.0.0-rc.8",
|
||||
"@tauri-apps/cli": "^1.0.0-rc.9",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/js-cookie": "^3.0.1",
|
||||
"@types/lodash": "^4.14.180",
|
||||
|
||||
+15
-9
@@ -143,20 +143,26 @@ async function resolveService() {
|
||||
|
||||
if (platform !== "win32") return;
|
||||
|
||||
const url =
|
||||
"https://github.com/zzzgydi/clash-verge-service/releases/download/latest/clash-verge-service.exe";
|
||||
|
||||
const binName = "clash-verge-service.exe";
|
||||
|
||||
const resDir = path.join(cwd, "src-tauri/resources");
|
||||
const targetPath = path.join(resDir, binName);
|
||||
|
||||
if (!FORCE && (await fs.pathExists(targetPath))) return;
|
||||
const repo =
|
||||
"https://github.com/zzzgydi/clash-verge-service/releases/download/latest";
|
||||
|
||||
async function help(bin) {
|
||||
const targetPath = path.join(resDir, bin);
|
||||
|
||||
if (!FORCE && (await fs.pathExists(targetPath))) return;
|
||||
|
||||
const url = `${repo}/${bin}`;
|
||||
await downloadFile(url, targetPath);
|
||||
}
|
||||
|
||||
await fs.mkdirp(resDir);
|
||||
await downloadFile(url, targetPath);
|
||||
await help("clash-verge-service.exe");
|
||||
await help("install-service.exe");
|
||||
await help("uninstall-service.exe");
|
||||
|
||||
console.log(`[INFO]: resolve ${binName} finished`);
|
||||
console.log(`[INFO]: resolve Service finished`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Generated
+286
-330
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1.0.0-rc.5", features = [] }
|
||||
tauri-build = { version = "1.0.0-rc.7", features = [] }
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
@@ -24,7 +24,7 @@ serde_yaml = "0.8"
|
||||
delay_timer = "0.11.1"
|
||||
parking_lot = "0.12.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "1.0.0-rc.6", features = ["process-all", "shell-all", "system-tray", "updater", "window-all"] }
|
||||
tauri = { version = "1.0.0-rc.8", features = ["process-all", "shell-all", "system-tray", "updater", "window-all"] }
|
||||
window-shadows = { git = "https://github.com/tauri-apps/window-shadows" }
|
||||
window-vibrancy = { git = "https://github.com/tauri-apps/window-vibrancy" }
|
||||
|
||||
@@ -40,10 +40,11 @@ port_scanner = "0.1.5"
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
runas = "0.2.1"
|
||||
deelevate = "0.2.0"
|
||||
windows-sys = "0.36"
|
||||
winreg = { version = "0.10", features = ["transactions"] }
|
||||
|
||||
[features]
|
||||
default = ["custom-protocol"]
|
||||
default = ["custom-protocol", "tauri/ayatana-tray"]
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
verge-dev = []
|
||||
debug-yml = []
|
||||
|
||||
@@ -258,20 +258,20 @@ pub mod service {
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn check_service() -> Result<JsonResponse, String> {
|
||||
wrap_err!(crate::core::Service::check_service().await)
|
||||
// no log
|
||||
match crate::core::Service::check_service().await {
|
||||
Ok(res) => Ok(res),
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn install_service() -> Result<(), String> {
|
||||
log_if_err!(crate::core::Service::install_service().await);
|
||||
let ret = wrap_err!(crate::core::Service::start_service().await);
|
||||
log::info!("clash verge service started successfully");
|
||||
ret
|
||||
wrap_err!(crate::core::Service::install_service().await)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn uninstall_service() -> Result<(), String> {
|
||||
log_if_err!(crate::core::Service::stop_service().await);
|
||||
wrap_err!(crate::core::Service::uninstall_service().await)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::utils::{dirs, help, tmpl};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_yaml::Mapping;
|
||||
use std::fs;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
@@ -15,13 +16,13 @@ pub struct PrfItem {
|
||||
/// profile name
|
||||
pub name: Option<String>,
|
||||
|
||||
/// profile file
|
||||
pub file: Option<String>,
|
||||
|
||||
/// profile description
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub desc: Option<String>,
|
||||
|
||||
/// profile file
|
||||
pub file: Option<String>,
|
||||
|
||||
/// source url
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub url: Option<String>,
|
||||
@@ -155,7 +156,7 @@ impl PrfItem {
|
||||
let desc = item.desc.unwrap_or("".into());
|
||||
PrfItem::from_script(name, desc)
|
||||
}
|
||||
typ @ _ => bail!("invalid type \"{typ}\""),
|
||||
typ @ _ => bail!("invalid profile item type \"{typ}\""),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +204,7 @@ impl PrfItem {
|
||||
builder = builder.no_proxy();
|
||||
}
|
||||
|
||||
builder = builder.user_agent(user_agent.unwrap_or("clash-verge/v0.1.0".into()));
|
||||
builder = builder.user_agent(user_agent.unwrap_or("clash-verge/v1.0.0".into()));
|
||||
|
||||
let resp = builder.build()?.get(url).send().await?;
|
||||
let header = resp.headers();
|
||||
@@ -223,11 +224,37 @@ impl PrfItem {
|
||||
None => None,
|
||||
};
|
||||
|
||||
// parse the Content-Disposition
|
||||
let filename = match header.get("Content-Disposition") {
|
||||
Some(value) => {
|
||||
let filename = value.to_str().unwrap_or("");
|
||||
help::parse_str::<String>(filename, "filename=")
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
// parse the profile-update-interval
|
||||
let option = match header.get("profile-update-interval") {
|
||||
Some(value) => match value.to_str().unwrap_or("").parse::<u64>() {
|
||||
Ok(val) => Some(PrfOption {
|
||||
update_interval: Some(val * 60), // hour -> min
|
||||
..PrfOption::default()
|
||||
}),
|
||||
Err(_) => None,
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
let uid = help::get_uid("r");
|
||||
let file = format!("{uid}.yaml");
|
||||
let name = name.unwrap_or(uid.clone());
|
||||
let name = name.unwrap_or(filename.unwrap_or("Remote File".into()));
|
||||
let data = resp.text_with_charset("utf-8").await?;
|
||||
|
||||
// check the data whether the valid yaml format
|
||||
if !serde_yaml::from_str::<Mapping>(&data).is_ok() {
|
||||
bail!("the remote profile data is not valid yaml");
|
||||
}
|
||||
|
||||
Ok(PrfItem {
|
||||
uid: Some(uid),
|
||||
itype: Some("remote".into()),
|
||||
|
||||
@@ -191,8 +191,9 @@ pub mod win_service {
|
||||
use super::*;
|
||||
use anyhow::Context;
|
||||
use deelevate::{PrivilegeLevel, Token};
|
||||
use runas::Command as RunasCommond;
|
||||
use std::{env::current_exe, process::Command as StdCommond};
|
||||
use runas::Command as RunasCommand;
|
||||
use std::os::windows::process::CommandExt;
|
||||
use std::{env::current_exe, process::Command as StdCommand};
|
||||
|
||||
const SERVICE_NAME: &str = "clash_verge_service";
|
||||
|
||||
@@ -217,61 +218,63 @@ pub mod win_service {
|
||||
/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
|
||||
pub async fn install_service() -> Result<()> {
|
||||
let binary_path = dirs::service_path();
|
||||
let arg = format!("binpath={}", binary_path.as_os_str().to_string_lossy());
|
||||
let install_path = binary_path.with_file_name("install-service.exe");
|
||||
|
||||
if !install_path.exists() {
|
||||
bail!("installer exe not found");
|
||||
}
|
||||
|
||||
let token = Token::with_current_process()?;
|
||||
let level = token.privilege_level()?;
|
||||
|
||||
let args = [
|
||||
"create",
|
||||
SERVICE_NAME,
|
||||
arg.as_str(),
|
||||
"type=own",
|
||||
"start=AUTO",
|
||||
"displayname=Clash Verge Service",
|
||||
];
|
||||
|
||||
let status = match level {
|
||||
PrivilegeLevel::NotPrivileged => RunasCommond::new("sc").args(&args).status()?,
|
||||
_ => StdCommond::new("sc").args(&args).status()?,
|
||||
PrivilegeLevel::NotPrivileged => RunasCommand::new(install_path).status()?,
|
||||
_ => StdCommand::new(install_path)
|
||||
.creation_flags(0x08000000)
|
||||
.status()?,
|
||||
};
|
||||
|
||||
if status.success() {
|
||||
return Ok(());
|
||||
if !status.success() {
|
||||
bail!(
|
||||
"failed to install service with status {}",
|
||||
status.code().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
if status.code() == Some(1073i32) {
|
||||
bail!("clash verge service is installed");
|
||||
}
|
||||
|
||||
bail!(
|
||||
"failed to install service with status {}",
|
||||
status.code().unwrap()
|
||||
)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Uninstall the Clash Verge Service
|
||||
/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
|
||||
pub async fn uninstall_service() -> Result<()> {
|
||||
let binary_path = dirs::service_path();
|
||||
let uninstall_path = binary_path.with_file_name("uninstall-service.exe");
|
||||
|
||||
if !uninstall_path.exists() {
|
||||
bail!("uninstaller exe not found");
|
||||
}
|
||||
|
||||
let token = Token::with_current_process()?;
|
||||
let level = token.privilege_level()?;
|
||||
|
||||
let args = ["delete", SERVICE_NAME];
|
||||
|
||||
let status = match level {
|
||||
PrivilegeLevel::NotPrivileged => RunasCommond::new("sc").args(&args).status()?,
|
||||
_ => StdCommond::new("sc").args(&args).status()?,
|
||||
PrivilegeLevel::NotPrivileged => RunasCommand::new(uninstall_path).status()?,
|
||||
_ => StdCommand::new(uninstall_path)
|
||||
.creation_flags(0x08000000)
|
||||
.status()?,
|
||||
};
|
||||
|
||||
match status.success() {
|
||||
true => Ok(()),
|
||||
false => bail!(
|
||||
if !status.success() {
|
||||
bail!(
|
||||
"failed to uninstall service with status {}",
|
||||
status.code().unwrap()
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// [deprecated]
|
||||
/// start service
|
||||
/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
|
||||
pub async fn start_service() -> Result<()> {
|
||||
@@ -281,8 +284,8 @@ pub mod win_service {
|
||||
let args = ["start", SERVICE_NAME];
|
||||
|
||||
let status = match level {
|
||||
PrivilegeLevel::NotPrivileged => RunasCommond::new("sc").args(&args).status()?,
|
||||
_ => StdCommond::new("sc").args(&args).status()?,
|
||||
PrivilegeLevel::NotPrivileged => RunasCommand::new("sc").args(&args).status()?,
|
||||
_ => StdCommand::new("sc").args(&args).status()?,
|
||||
};
|
||||
|
||||
match status.success() {
|
||||
|
||||
@@ -6,3 +6,4 @@ pub mod resolve;
|
||||
pub mod server;
|
||||
pub mod sysopt;
|
||||
pub mod tmpl;
|
||||
mod winhelp;
|
||||
|
||||
@@ -35,27 +35,29 @@ fn resolve_window(app: &App) {
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use crate::utils::winhelp;
|
||||
use window_shadows::set_shadow;
|
||||
use window_vibrancy::apply_blur;
|
||||
|
||||
window.set_decorations(false).unwrap();
|
||||
set_shadow(&window, true).unwrap();
|
||||
apply_blur(&window, None).unwrap();
|
||||
let _ = window.set_decorations(false);
|
||||
let _ = set_shadow(&window, true);
|
||||
|
||||
// todo
|
||||
// win11 disable this feature temporarily due to lag
|
||||
if !winhelp::is_win11() {
|
||||
let _ = apply_blur(&window, None);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use tauri::LogicalSize;
|
||||
use tauri::Size::Logical;
|
||||
window.set_decorations(true).unwrap();
|
||||
window
|
||||
.set_size(Logical(LogicalSize {
|
||||
width: 800.0,
|
||||
height: 610.0,
|
||||
}))
|
||||
.unwrap();
|
||||
// use tauri_plugin_vibrancy::MacOSVibrancy;
|
||||
// #[allow(deprecated)]
|
||||
// window.apply_vibrancy(MacOSVibrancy::AppearanceBased);
|
||||
|
||||
let _ = window.set_decorations(true);
|
||||
let _ = window.set_size(Logical(LogicalSize {
|
||||
width: 800.0,
|
||||
height: 620.0,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#![cfg(target_os = "windows")]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
//!
|
||||
//! From https://github.com/tauri-apps/window-vibrancy/blob/dev/src/windows.rs
|
||||
//!
|
||||
|
||||
use windows_sys::Win32::{
|
||||
Foundation::*,
|
||||
System::{LibraryLoader::*, SystemInformation::*},
|
||||
};
|
||||
|
||||
fn get_function_impl(library: &str, function: &str) -> Option<FARPROC> {
|
||||
assert_eq!(library.chars().last(), Some('\0'));
|
||||
assert_eq!(function.chars().last(), Some('\0'));
|
||||
|
||||
let module = unsafe { LoadLibraryA(library.as_ptr()) };
|
||||
if module == 0 {
|
||||
return None;
|
||||
}
|
||||
Some(unsafe { GetProcAddress(module, function.as_ptr()) })
|
||||
}
|
||||
|
||||
macro_rules! get_function {
|
||||
($lib:expr, $func:ident) => {
|
||||
get_function_impl(concat!($lib, '\0'), concat!(stringify!($func), '\0')).map(|f| unsafe {
|
||||
std::mem::transmute::<::windows_sys::Win32::Foundation::FARPROC, $func>(f)
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns a tuple of (major, minor, buildnumber)
|
||||
fn get_windows_ver() -> Option<(u32, u32, u32)> {
|
||||
type RtlGetVersion = unsafe extern "system" fn(*mut OSVERSIONINFOW) -> i32;
|
||||
let handle = get_function!("ntdll.dll", RtlGetVersion);
|
||||
if let Some(rtl_get_version) = handle {
|
||||
unsafe {
|
||||
let mut vi = OSVERSIONINFOW {
|
||||
dwOSVersionInfoSize: 0,
|
||||
dwMajorVersion: 0,
|
||||
dwMinorVersion: 0,
|
||||
dwBuildNumber: 0,
|
||||
dwPlatformId: 0,
|
||||
szCSDVersion: [0; 128],
|
||||
};
|
||||
|
||||
let status = (rtl_get_version)(&mut vi as _);
|
||||
|
||||
if status >= 0 {
|
||||
Some((vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_win11() -> bool {
|
||||
let v = get_windows_ver().unwrap_or_default();
|
||||
v.2 >= 22000
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_version() {
|
||||
dbg!(get_windows_ver().unwrap_or_default());
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "Clash Verge",
|
||||
"version": "1.0.0"
|
||||
"version": "1.0.1"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
@@ -32,13 +32,11 @@
|
||||
"shortDescription": "A Clash GUI based on tauri.",
|
||||
"longDescription": "A Clash GUI based on tauri.",
|
||||
"deb": {
|
||||
"depends": [],
|
||||
"useBootstrapper": false
|
||||
"depends": []
|
||||
},
|
||||
"macOS": {
|
||||
"frameworks": [],
|
||||
"minimumSystemVersion": "",
|
||||
"useBootstrapper": false,
|
||||
"exceptionDomain": "",
|
||||
"signingIdentity": null,
|
||||
"entitlements": null
|
||||
@@ -73,7 +71,7 @@
|
||||
{
|
||||
"title": "Clash Verge",
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"height": 636,
|
||||
"resizable": true,
|
||||
"fullscreen": false,
|
||||
"decorations": false,
|
||||
|
||||
@@ -11,6 +11,7 @@ body {
|
||||
--primary-main: #5b5c9d;
|
||||
--text-primary: #637381;
|
||||
--selection-color: #f5f5f5;
|
||||
--scroller-color: #90939980;
|
||||
}
|
||||
|
||||
::selection {
|
||||
@@ -25,7 +26,7 @@ body {
|
||||
}
|
||||
*::-webkit-scrollbar-thumb {
|
||||
border-radius: 6px;
|
||||
background-color: rgba(#909399, 0.5);
|
||||
background-color: var(--scroller-color);
|
||||
}
|
||||
|
||||
@import "./layout.scss";
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
height: 100%;
|
||||
max-width: 225px;
|
||||
min-width: 125px;
|
||||
padding: 8px 0;
|
||||
padding: 16px 0 8px;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
@@ -23,14 +23,14 @@
|
||||
max-width: 168px;
|
||||
max-height: 168px;
|
||||
margin: 0 auto;
|
||||
padding: 0 8px;
|
||||
padding: 0 16px;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
img,
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 96%;
|
||||
height: 96%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
}
|
||||
|
||||
.the-menu {
|
||||
flex: 1 1 75%;
|
||||
flex: 1 1 80%;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Box, Typography } from "@mui/material";
|
||||
import { ArrowDownward, ArrowUpward } from "@mui/icons-material";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { ApiType } from "../../services/types";
|
||||
import { getInfomation } from "../../services/api";
|
||||
import { getInformation } from "../../services/api";
|
||||
import { getVergeConfig } from "../../services/cmds";
|
||||
import { atomClashPort } from "../../services/states";
|
||||
import TrafficGraph from "./traffic-graph";
|
||||
@@ -41,7 +41,7 @@ const LayoutTraffic = () => {
|
||||
useEffect(() => {
|
||||
let ws: WebSocket | null = null;
|
||||
|
||||
getInfomation().then((result) => {
|
||||
getInformation().then((result) => {
|
||||
const { server = "", secret = "" } = result;
|
||||
ws = new WebSocket(`ws://${server}/traffic?token=${secret}`);
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useTheme } from "@mui/material";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
|
||||
const maxPoint = 30;
|
||||
|
||||
@@ -70,7 +72,28 @@ const TrafficGraph = (props: Props) => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// reduce the GPU usage when hidden
|
||||
const [enablePaint, setEnablePaint] = useState(true);
|
||||
useEffect(() => {
|
||||
appWindow.isVisible().then(setEnablePaint);
|
||||
|
||||
const unlistenBlur = listen("tauri://blur", async () => {
|
||||
setEnablePaint(await appWindow.isVisible());
|
||||
});
|
||||
|
||||
const unlistenFocus = listen("tauri://focus", async () => {
|
||||
setEnablePaint(await appWindow.isVisible());
|
||||
});
|
||||
|
||||
return () => {
|
||||
unlistenBlur.then((fn) => fn());
|
||||
unlistenFocus.then((fn) => fn());
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enablePaint) return;
|
||||
|
||||
let raf = 0;
|
||||
const canvas = canvasRef.current!;
|
||||
|
||||
@@ -193,7 +216,7 @@ const TrafficGraph = (props: Props) => {
|
||||
return () => {
|
||||
cancelAnimationFrame(raf);
|
||||
};
|
||||
}, [palette]);
|
||||
}, [enablePaint, palette]);
|
||||
|
||||
return <canvas ref={canvasRef} style={{ width: "100%", height: "100%" }} />;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import useSWR from "swr";
|
||||
import { useMemo } from "react";
|
||||
import { createTheme } from "@mui/material";
|
||||
import { getVergeConfig } from "../../services/cmds";
|
||||
import { defaultTheme as dt } from "../../pages/_theme";
|
||||
import { defaultTheme, defaultDarkTheme } from "../../pages/_theme";
|
||||
|
||||
/**
|
||||
* custome theme
|
||||
@@ -13,14 +13,9 @@ export default function useCustomTheme() {
|
||||
|
||||
const theme = useMemo(() => {
|
||||
const mode = theme_mode ?? "light";
|
||||
// const background = mode === "light" ? "#f5f5f5" : "#000";
|
||||
const selectColor = mode === "light" ? "#f5f5f5" : "#d5d5d5";
|
||||
|
||||
const rootEle = document.documentElement;
|
||||
rootEle.style.background = "transparent";
|
||||
rootEle.style.setProperty("--selection-color", selectColor);
|
||||
|
||||
const setting = theme_setting || {};
|
||||
const dt = mode === "light" ? defaultTheme : defaultDarkTheme;
|
||||
|
||||
const theme = createTheme({
|
||||
breakpoints: {
|
||||
@@ -47,6 +42,16 @@ export default function useCustomTheme() {
|
||||
},
|
||||
});
|
||||
|
||||
// css
|
||||
const selectColor = mode === "light" ? "#f5f5f5" : "#d5d5d5";
|
||||
const scrollColor = mode === "light" ? "#90939980" : "#54545480";
|
||||
|
||||
const rootEle = document.documentElement;
|
||||
rootEle.style.background = "transparent";
|
||||
rootEle.style.setProperty("--selection-color", selectColor);
|
||||
rootEle.style.setProperty("--scroller-color", scrollColor);
|
||||
rootEle.style.setProperty("--primary-main", theme.palette.primary.main);
|
||||
|
||||
// inject css
|
||||
let style = document.querySelector("style#verge-theme");
|
||||
if (!style) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useEffect, useState } from "react";
|
||||
import { useSetRecoilState } from "recoil";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { ApiType } from "../../services/types";
|
||||
import { getInfomation } from "../../services/api";
|
||||
import { getInformation } from "../../services/api";
|
||||
import { atomLogData } from "../../services/states";
|
||||
|
||||
const MAX_LOG_NUM = 1000;
|
||||
@@ -25,7 +25,7 @@ export default function useLogSetup() {
|
||||
});
|
||||
};
|
||||
|
||||
getInfomation().then((info) => {
|
||||
getInformation().then((info) => {
|
||||
const { server = "", secret = "" } = info;
|
||||
ws = new WebSocket(`ws://${server}/logs?token=${secret}`);
|
||||
ws.addEventListener("message", handler);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { mutate } from "swr";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useLockFn, useSetState } from "ahooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
@@ -25,6 +26,8 @@ interface Props {
|
||||
// remote / local file / merge / script
|
||||
const ProfileEdit = (props: Props) => {
|
||||
const { open, itemData, onClose } = props;
|
||||
|
||||
const { t } = useTranslation();
|
||||
const [form, setForm] = useSetState({ ...itemData });
|
||||
const [option, setOption] = useSetState(itemData.option ?? {});
|
||||
const [showOpt, setShowOpt] = useState(!!itemData.option);
|
||||
@@ -33,7 +36,10 @@ const ProfileEdit = (props: Props) => {
|
||||
if (itemData) {
|
||||
setForm({ ...itemData });
|
||||
setOption(itemData.option ?? {});
|
||||
setShowOpt(!!itemData.option?.user_agent);
|
||||
setShowOpt(
|
||||
itemData.type === "remote" &&
|
||||
(!!itemData.option?.user_agent || !!itemData.option?.update_interval)
|
||||
);
|
||||
}
|
||||
}, [itemData]);
|
||||
|
||||
@@ -41,7 +47,10 @@ const ProfileEdit = (props: Props) => {
|
||||
try {
|
||||
const { uid } = itemData;
|
||||
const { name, desc, url } = form;
|
||||
const option_ = itemData.type === "remote" ? option : undefined;
|
||||
const option_ =
|
||||
itemData.type === "remote" || itemData.type === "local"
|
||||
? option
|
||||
: undefined;
|
||||
|
||||
if (itemData.type === "remote" && !url) {
|
||||
throw new Error("Remote URL should not be null");
|
||||
@@ -65,11 +74,11 @@ const ProfileEdit = (props: Props) => {
|
||||
|
||||
const type =
|
||||
form.type ||
|
||||
(form.url ? "remote" : form.file?.endsWith("js") ? "script" : "local");
|
||||
(form.url ? "remote" : form.file?.endsWith(".js") ? "script" : "local");
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose}>
|
||||
<DialogTitle sx={{ pb: 0.5 }}>Edit Profile</DialogTitle>
|
||||
<DialogTitle sx={{ pb: 0.5 }}>{t("Edit Info")}</DialogTitle>
|
||||
|
||||
<DialogContent sx={{ width: 336, pb: 1 }}>
|
||||
<TextField
|
||||
@@ -100,7 +109,7 @@ const ProfileEdit = (props: Props) => {
|
||||
{type === "remote" && (
|
||||
<TextField
|
||||
{...textFieldProps}
|
||||
label="Subscription Url"
|
||||
label="Subscription URL"
|
||||
value={form.url}
|
||||
onChange={(e) => setForm({ url: e.target.value })}
|
||||
onKeyDown={(e) => e.key === "Enter" && onUpdate()}
|
||||
@@ -108,26 +117,27 @@ const ProfileEdit = (props: Props) => {
|
||||
)}
|
||||
|
||||
{showOpt && (
|
||||
<>
|
||||
<TextField
|
||||
{...textFieldProps}
|
||||
label="User Agent"
|
||||
value={option.user_agent}
|
||||
onChange={(e) => setOption({ user_agent: e.target.value })}
|
||||
onKeyDown={(e) => e.key === "Enter" && onUpdate()}
|
||||
/>
|
||||
<TextField
|
||||
{...textFieldProps}
|
||||
label="User Agent"
|
||||
value={option.user_agent}
|
||||
placeholder="clash-verge/v1.0.0"
|
||||
onChange={(e) => setOption({ user_agent: e.target.value })}
|
||||
onKeyDown={(e) => e.key === "Enter" && onUpdate()}
|
||||
/>
|
||||
)}
|
||||
|
||||
<TextField
|
||||
{...textFieldProps}
|
||||
label="Update Interval (mins)"
|
||||
value={option.update_interval}
|
||||
onChange={(e) => {
|
||||
const str = e.target.value?.replace(/\D/, "");
|
||||
setOption({ update_interval: str != null ? +str : str });
|
||||
}}
|
||||
onKeyDown={(e) => e.key === "Enter" && onUpdate()}
|
||||
/>
|
||||
</>
|
||||
{((type === "remote" && showOpt) || type === "local") && (
|
||||
<TextField
|
||||
{...textFieldProps}
|
||||
label="Update Interval (mins)"
|
||||
value={option.update_interval}
|
||||
onChange={(e) => {
|
||||
const str = e.target.value?.replace(/\D/, "");
|
||||
setOption({ update_interval: str != null ? +str : str });
|
||||
}}
|
||||
onKeyDown={(e) => e.key === "Enter" && onUpdate()}
|
||||
/>
|
||||
)}
|
||||
</DialogContent>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import dayjs from "dayjs";
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useSWRConfig } from "swr";
|
||||
import { useRecoilState } from "recoil";
|
||||
@@ -59,11 +59,6 @@ const ProfileItem = (props: Props) => {
|
||||
const [loadingCache, setLoadingCache] = useRecoilState(atomLoadingCache);
|
||||
|
||||
const { uid, name = "Profile", extra, updated = 0 } = itemData;
|
||||
const { upload = 0, download = 0, total = 0 } = extra ?? {};
|
||||
const from = parseUrl(itemData.url);
|
||||
const expire = parseExpire(extra?.expire);
|
||||
const progress = Math.round(((download + upload) * 100) / (total + 0.1));
|
||||
const fromnow = updated > 0 ? dayjs(updated * 1000).fromNow() : "";
|
||||
|
||||
// local file mode
|
||||
// remote file mode
|
||||
@@ -71,8 +66,42 @@ const ProfileItem = (props: Props) => {
|
||||
const hasUrl = !!itemData.url;
|
||||
const hasExtra = !!extra; // only subscription url has extra info
|
||||
|
||||
const { upload = 0, download = 0, total = 0 } = extra ?? {};
|
||||
const from = parseUrl(itemData.url);
|
||||
const expire = parseExpire(extra?.expire);
|
||||
const progress = Math.round(((download + upload) * 100) / (total + 0.1));
|
||||
|
||||
const loading = loadingCache[itemData.uid] ?? false;
|
||||
|
||||
// interval update from now field
|
||||
const [, setRefresh] = useState({});
|
||||
useEffect(() => {
|
||||
if (!hasUrl) return;
|
||||
|
||||
let timer: any = null;
|
||||
|
||||
const handler = () => {
|
||||
const now = Date.now();
|
||||
const lastUpdate = updated * 1000;
|
||||
|
||||
// 大于一天的不管
|
||||
if (now - lastUpdate >= 24 * 36e5) return;
|
||||
|
||||
const wait = now - lastUpdate >= 36e5 ? 30e5 : 5e4;
|
||||
|
||||
timer = setTimeout(() => {
|
||||
setRefresh({});
|
||||
handler();
|
||||
}, wait);
|
||||
};
|
||||
|
||||
handler();
|
||||
|
||||
return () => {
|
||||
if (timer) clearTimeout(timer);
|
||||
};
|
||||
}, [hasUrl, updated]);
|
||||
|
||||
const [editOpen, setEditOpen] = useState(false);
|
||||
const [fileOpen, setFileOpen] = useState(false);
|
||||
|
||||
@@ -165,8 +194,8 @@ const ProfileItem = (props: Props) => {
|
||||
const color = {
|
||||
"light-true": text.secondary,
|
||||
"light-false": text.secondary,
|
||||
"dark-true": alpha(text.secondary, 0.6),
|
||||
"dark-false": alpha(text.secondary, 0.6),
|
||||
"dark-true": alpha(text.secondary, 0.75),
|
||||
"dark-false": alpha(text.secondary, 0.75),
|
||||
}[key]!;
|
||||
|
||||
const h2color = {
|
||||
@@ -231,7 +260,7 @@ const ProfileItem = (props: Props) => {
|
||||
textAlign="right"
|
||||
title="updated time"
|
||||
>
|
||||
{fromnow}
|
||||
{updated > 0 ? dayjs(updated * 1000).fromNow() : ""}
|
||||
</Typography>
|
||||
</Box>
|
||||
) : (
|
||||
|
||||
@@ -13,9 +13,10 @@ import {
|
||||
ListItemText,
|
||||
styled,
|
||||
TextField,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { getVergeConfig, patchVergeConfig } from "../../services/cmds";
|
||||
import { defaultTheme } from "../../pages/_theme";
|
||||
import { defaultTheme, defaultDarkTheme } from "../../pages/_theme";
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
@@ -71,15 +72,22 @@ const SettingTheme = (props: Props) => {
|
||||
}
|
||||
});
|
||||
|
||||
const renderItem = (label: string, key: keyof typeof defaultTheme) => {
|
||||
// default theme
|
||||
const { palette } = useTheme();
|
||||
|
||||
const dt = palette.mode === "light" ? defaultTheme : defaultDarkTheme;
|
||||
|
||||
type ThemeKey = keyof typeof theme & keyof typeof defaultTheme;
|
||||
|
||||
const renderItem = (label: string, key: ThemeKey) => {
|
||||
return (
|
||||
<Item>
|
||||
<ListItemText primary={label} />
|
||||
<Round sx={{ background: theme[key] || defaultTheme[key] }} />
|
||||
<Round sx={{ background: theme[key] || dt[key] }} />
|
||||
<TextField
|
||||
{...textProps}
|
||||
value={theme[key] ?? ""}
|
||||
placeholder={defaultTheme[key]}
|
||||
placeholder={dt[key]}
|
||||
onChange={handleChange(key)}
|
||||
onKeyDown={(e) => e.key === "Enter" && onSave()}
|
||||
/>
|
||||
|
||||
@@ -72,7 +72,7 @@ const Layout = () => {
|
||||
}}
|
||||
sx={[
|
||||
({ palette }) => ({
|
||||
bgcolor: alpha(palette.background.paper, theme_blur ? 0.85 : 1),
|
||||
bgcolor: alpha(palette.background.paper, theme_blur ? 0.8 : 1),
|
||||
}),
|
||||
]}
|
||||
>
|
||||
@@ -83,7 +83,7 @@ const Layout = () => {
|
||||
<UpdateButton className="the-newbtn" />
|
||||
</div>
|
||||
|
||||
<List className="the-menu" data-windrag>
|
||||
<List className="the-menu">
|
||||
{routers.map((router) => (
|
||||
<LayoutItem key={router.label} to={router.link}>
|
||||
{t(router.label)}
|
||||
|
||||
@@ -10,3 +10,10 @@ export const defaultTheme = {
|
||||
success_color: "#2e7d32",
|
||||
font_family: `"Roboto", "Helvetica", "Arial", sans-serif`,
|
||||
};
|
||||
|
||||
// dark mode
|
||||
export const defaultDarkTheme = {
|
||||
...defaultTheme,
|
||||
primary_text: "#757575",
|
||||
secondary_text: "#637381",
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Box, Button, Paper, TextField } from "@mui/material";
|
||||
import { Virtuoso } from "react-virtuoso";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ApiType } from "../services/types";
|
||||
import { closeAllConnections, getInfomation } from "../services/api";
|
||||
import { closeAllConnections, getInformation } from "../services/api";
|
||||
import BasePage from "../components/base/base-page";
|
||||
import ConnectionItem from "../components/connection/connection-item";
|
||||
|
||||
@@ -25,7 +25,7 @@ const ConnectionsPage = () => {
|
||||
useEffect(() => {
|
||||
let ws: WebSocket | null = null;
|
||||
|
||||
getInfomation().then((result) => {
|
||||
getInformation().then((result) => {
|
||||
const { server = "", secret = "" } = result;
|
||||
ws = new WebSocket(`ws://${server}/connections?token=${secret}`);
|
||||
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ export async function getAxios(force: boolean = false) {
|
||||
return axiosIns;
|
||||
}
|
||||
|
||||
/// get infomation
|
||||
export async function getInfomation() {
|
||||
/// get information
|
||||
export async function getInformation() {
|
||||
if (server) return { server, secret };
|
||||
const info = await getClashInfo();
|
||||
return info!;
|
||||
|
||||
@@ -386,10 +386,10 @@
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@mui/base@5.0.0-alpha.76":
|
||||
version "5.0.0-alpha.76"
|
||||
resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-alpha.76.tgz#683d68eff6d52e19e9962f608a5d3b8b6fb6ef55"
|
||||
integrity sha512-Pd0l4DvjXiGRyipn/CTDlYB2XrJwhpLktVXvbvcmzL2SMDaNprSarZqBkPHIubkulmRDZEEcnFDrpKgeSJDg4A==
|
||||
"@mui/base@5.0.0-alpha.79":
|
||||
version "5.0.0-alpha.79"
|
||||
resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-alpha.79.tgz#1994a6382a162b52ec93b66f3c74d193820d2365"
|
||||
integrity sha512-/lZLF027BkiEjM8MIYoeS/FEhTKf+41ePU9SOijMGrCin1Y0Igucw+IHa1fF8HXD7wDbFKqHuso3J1jMG8wyNw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.17.2"
|
||||
"@emotion/is-prop-valid" "^1.1.2"
|
||||
@@ -400,21 +400,21 @@
|
||||
prop-types "^15.7.2"
|
||||
react-is "^17.0.2"
|
||||
|
||||
"@mui/icons-material@^5.6.1":
|
||||
version "5.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.6.1.tgz#421e2b73992349abb07f8f03074d7e56e20bf7ba"
|
||||
integrity sha512-I1x8u+FRLOmoJpRJASMx9UG+jZrSkNLyRQmBXivQQwXu3m3iasMoaKYhhI0J18t8+FWktbkNTp63oEUHE9Gw0Q==
|
||||
"@mui/icons-material@^5.6.2":
|
||||
version "5.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.6.2.tgz#239c40fc5841dc7c6af7d00e4e988550de170fcd"
|
||||
integrity sha512-9QdI7axKuBAyaGz4mtdi7Uy1j73/thqFmEuxpJHxNC7O8ADEK1Da3t2veK2tgmsXsUlAHcAG63gg+GvWWeQNqQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.17.2"
|
||||
|
||||
"@mui/material@^5.6.1":
|
||||
version "5.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.6.1.tgz#b74cfbe4666586e054a28cf3df448369892085e1"
|
||||
integrity sha512-xg6pPq+1jxWupwmPpnfmsHNjrsOe2xynUQWrRfcH8WHrrr1sQulq0VF4gORq/l8DD8a/jb4s8SsC20e/e6mHKQ==
|
||||
"@mui/material@^5.6.4":
|
||||
version "5.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.6.4.tgz#5c6d6770acaea84d7b1c6492639627baed62f65b"
|
||||
integrity sha512-7TD+u/SExZK2a55w6reX56oPk37gKr/M/XGt156X+m0d9LhzOsW864nkErIX/H8oSkX/6kCimxu1FDsO+gjiVw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.17.2"
|
||||
"@mui/base" "5.0.0-alpha.76"
|
||||
"@mui/system" "^5.6.1"
|
||||
"@mui/base" "5.0.0-alpha.79"
|
||||
"@mui/system" "^5.6.4"
|
||||
"@mui/types" "^7.1.3"
|
||||
"@mui/utils" "^5.6.1"
|
||||
"@types/react-transition-group" "^4.4.4"
|
||||
@@ -425,10 +425,10 @@
|
||||
react-is "^17.0.2"
|
||||
react-transition-group "^4.4.2"
|
||||
|
||||
"@mui/private-theming@^5.6.1":
|
||||
version "5.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.6.1.tgz#198ccec972375db999c293109b5f26456b9c3a22"
|
||||
integrity sha512-8lgh+tUt/3ftStfvml3dwAzhW3fe/cUFjLcBViOTnWk7UixWR79me4qehsO4NVj0THpu3d2qclrLzdD8qBAWAQ==
|
||||
"@mui/private-theming@^5.6.2":
|
||||
version "5.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.6.2.tgz#c42da32f8b9481ba12885176c0168a355727c189"
|
||||
integrity sha512-IbrSfFXfiZdyhRMC2bgGTFtb16RBQ5mccmjeh3MtAERWuepiCK7gkW5D9WhEsfTu6iez+TEjeUKSgmMHlsM2mg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.17.2"
|
||||
"@mui/utils" "^5.6.1"
|
||||
@@ -443,13 +443,13 @@
|
||||
"@emotion/cache" "^11.7.1"
|
||||
prop-types "^15.7.2"
|
||||
|
||||
"@mui/system@^5.6.1":
|
||||
version "5.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.6.1.tgz#dd47a15b82012f44464a0f25765e3dec6182ba98"
|
||||
integrity sha512-Y5pDvEOK6VOY+0vgNeyDuEEO5QCinhXbZQDyLOlaGLKuAoRGLXO9pcSsjZoGkewYZitXD44EDfgBQ+BqsAfgUA==
|
||||
"@mui/system@^5.6.4":
|
||||
version "5.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.6.4.tgz#b1c615c70b3573d61a8a56dbaee6700bb9a5ca9b"
|
||||
integrity sha512-7rsWED1wMFMePySJobsBerFZNu7ga580QSi3Zd6sJR8nVj12qD3yIdfvxA70/PxJ/805KbIT0GX7edKI+hpyhA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.17.2"
|
||||
"@mui/private-theming" "^5.6.1"
|
||||
"@mui/private-theming" "^5.6.2"
|
||||
"@mui/styled-engine" "^5.6.1"
|
||||
"@mui/types" "^7.1.3"
|
||||
"@mui/utils" "^5.6.1"
|
||||
@@ -653,72 +653,72 @@
|
||||
"@svgr/hast-util-to-babel-ast" "^6.2.1"
|
||||
svg-parser "^2.0.2"
|
||||
|
||||
"@tauri-apps/api@^1.0.0-rc.3":
|
||||
version "1.0.0-rc.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-1.0.0-rc.3.tgz#e80ddbe832bf003537d94801d508a7f7e25ac48b"
|
||||
integrity sha512-/ZbyBjuUoU6mYm8RzibIUvVuJ31ZwYA2+fTRl7FF4LVFhzCVJ1YI1BS5ohGb2GsLNmLpfeo7kDHaIhV2uaOchQ==
|
||||
"@tauri-apps/api@^1.0.0-rc.4":
|
||||
version "1.0.0-rc.4"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-1.0.0-rc.4.tgz#454ef7b15237f3d5752bbfc09c8997a00b1e8a9b"
|
||||
integrity sha512-1HaUsx8+TzFHDoQ+Mmd6RWaMsPyZlurQHgACDt+il5e/ui6pDkumVXaS92SnY5XOcS4gBC0BkgjVfkWgcm/Oww==
|
||||
dependencies:
|
||||
type-fest "2.12.1"
|
||||
type-fest "2.12.2"
|
||||
|
||||
"@tauri-apps/cli-darwin-arm64@1.0.0-rc.8":
|
||||
version "1.0.0-rc.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.0.0-rc.8.tgz#84eac830714d1819c72f4e3d7e334bee3719d673"
|
||||
integrity sha512-sbV4fkd3YBlX0gEBldEVmN/NbBdHzrn8wCRRiFaNBocDWC6Ji6DNvpp1Vy1xgY0RgtGOisGD+3+HelmKP4Mh/A==
|
||||
"@tauri-apps/cli-darwin-arm64@1.0.0-rc.9":
|
||||
version "1.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.0.0-rc.9.tgz#8786ce2eacbad4b69eaa8e4e0b7ae16819923b11"
|
||||
integrity sha512-cpcSRyVOh3n5GsCdKtVQpLJ36yx7h+KY868l7KhPnM5EL1cQbFwYzD/VHlzFvfrpS19YvPBB/AHln4rll5iWvw==
|
||||
|
||||
"@tauri-apps/cli-darwin-x64@1.0.0-rc.8":
|
||||
version "1.0.0-rc.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.0.0-rc.8.tgz#675b8cdbf2a0ade23159e964ac3a1e5dd767ffcf"
|
||||
integrity sha512-VmuYbBZKKal/YxSTbzHTaM04C9zUlTXq7ePoXc1PRAa/Xafo16N37OGzhzBlsKHrvh6BtPp9ZWk5UhHIDiJBsw==
|
||||
"@tauri-apps/cli-darwin-x64@1.0.0-rc.9":
|
||||
version "1.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.0.0-rc.9.tgz#b4aa98ebf26018b3e9013ea4ce16a294f2cb8c4f"
|
||||
integrity sha512-ku8QpMNrfqyCk2adLdVB+zzaCb7T0/RgVvaqEZqK54WW4blUxkeKHbKqZ/SKRdxTkghHbgJIoBtlk1A5GUbAwg==
|
||||
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf@1.0.0-rc.8":
|
||||
version "1.0.0-rc.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.0.0-rc.8.tgz#b7ecece513c7ba828c0e794eca4f3125f83f2cf6"
|
||||
integrity sha512-2VKkS1c2pK56sgtGxtsm9nKKWefG7dgPnynTuCoEngkgQfNIlZ1ns/eAIZpBmwhvOMOw2OesKvK9ZQo0/lE/IA==
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf@1.0.0-rc.9":
|
||||
version "1.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.0.0-rc.9.tgz#d77c329168eaa2a5d66b9648deda8d98783d781d"
|
||||
integrity sha512-Qlwm4eWo0uCeL3kmowfaLghPehYTYvnM4fH6cRZndzs6/abqsFdghmEmhP5mn34/RAnHXAUANItqlgk6L7C4iw==
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-gnu@1.0.0-rc.8":
|
||||
version "1.0.0-rc.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.0.0-rc.8.tgz#6c08741be40d0148da16b26d568c1595e3b99332"
|
||||
integrity sha512-jykbrTJyx0uJhhL/3PPYGx5ETqEzacJ3YChnHzVClSzPkrdoGC61/xY9dMD9ZFJsLMJkV4VJj8sGRd1OPKCa/w==
|
||||
"@tauri-apps/cli-linux-arm64-gnu@1.0.0-rc.9":
|
||||
version "1.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.0.0-rc.9.tgz#ecf229e8176b55046d64c2fab9c831fa0fe39a77"
|
||||
integrity sha512-Rr4S902dYjRnDCu141f5Cz3JxwKxX/ax7LiMhSifQu5o2wSiezmZ20VRHBwW1UuZxvGV+hxTuZVnfD6NKQdWdA==
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-musl@1.0.0-rc.8":
|
||||
version "1.0.0-rc.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.0.0-rc.8.tgz#70fdfbf5e4fe4d42bc5984a7bc8914d08a3dcbf6"
|
||||
integrity sha512-HAIm8BKpLIWkvYgxoRzDIaqWIW3UtH2HO1qDd0aov5FTx/9dtCTtylpvd/6mWs5LGaEmsLoSokfJloI2sMZ/WQ==
|
||||
"@tauri-apps/cli-linux-arm64-musl@1.0.0-rc.9":
|
||||
version "1.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.0.0-rc.9.tgz#10a6052d9a6bd720da5ffb1a98bc862564d7a93f"
|
||||
integrity sha512-MxqjspY2aS/nxtvBMT8TExZfDWDEsUvQRHHY/2KoBYpqpzucW6WXRGmeOvS1GeA3vnub2/Kq5i32jGRDT1tvrA==
|
||||
|
||||
"@tauri-apps/cli-linux-x64-gnu@1.0.0-rc.8":
|
||||
version "1.0.0-rc.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.0.0-rc.8.tgz#bf21f03128e1d6f8ae4d4e043ac2620d8489a69d"
|
||||
integrity sha512-fnPrkX6Uy9Qz2vqnT3D3sgbJzXTR4arNUIQl8HIYi2YCZZVmDWczz4x4++ilZWwk0I3a7d612/WzTeBzQjn3kg==
|
||||
"@tauri-apps/cli-linux-x64-gnu@1.0.0-rc.9":
|
||||
version "1.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.0.0-rc.9.tgz#34891286ffe0eba1c0602baaa5c3f198f5247a0a"
|
||||
integrity sha512-LD7KnJuH1mYFwQfcALPttBnaSG6pgO87Z6nY3xXJjo+A4ttPHcmIBaNdXCTjAmib/umD0nD8k95Hw9iJFYTuiA==
|
||||
|
||||
"@tauri-apps/cli-linux-x64-musl@1.0.0-rc.8":
|
||||
version "1.0.0-rc.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.0.0-rc.8.tgz#647286cb6826d0ff1503a9d6d88959ab8f5de4fb"
|
||||
integrity sha512-kHrpBsJFRAwqFL7xnsrKdNxnYjzI/J9/Dr7T3rl+IIPbi1sIojh6DydxFOYepnuoINA6zWYQJpo0FQeASJsXrw==
|
||||
"@tauri-apps/cli-linux-x64-musl@1.0.0-rc.9":
|
||||
version "1.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.0.0-rc.9.tgz#32e6550964e559b158d4b9c83b3a7e3c3d58abee"
|
||||
integrity sha512-ifocAxBYhk7qrO5x1mizxx/yABvkmyia0kw9eXUn7d5a30HoBcl/A9t+w+7c4B/n/D+gxEMSr6CPaIZv7KnTog==
|
||||
|
||||
"@tauri-apps/cli-win32-ia32-msvc@1.0.0-rc.8":
|
||||
version "1.0.0-rc.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.0.0-rc.8.tgz#69fff6f746631345649d2abf788e9f0954eb7ce8"
|
||||
integrity sha512-y8uT7AaIZVdLAWL4pxj/GXitwWn828er23yniOvTo1mJMCZsSFdwiOGiRSXI6OZsVCOPiJmvqq7eWaskQKYA0A==
|
||||
"@tauri-apps/cli-win32-ia32-msvc@1.0.0-rc.9":
|
||||
version "1.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.0.0-rc.9.tgz#01f5c7f1f9a359ea7f6d203dd03d8b98cf8bdcb6"
|
||||
integrity sha512-ClDYF4CstoccPMVkIHyvy1jzlWXIYZX2mjKB6z18MdJ0O7Je8TC115K30lqXtSdPuKX35xWDcWU2b/gllcUUzA==
|
||||
|
||||
"@tauri-apps/cli-win32-x64-msvc@1.0.0-rc.8":
|
||||
version "1.0.0-rc.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.0.0-rc.8.tgz#bf58e24c42fccf098f78dc51e43f5cd7b7ff6842"
|
||||
integrity sha512-PiDr/iAKoL9nQSiWHkUSjRVHbvCJaa7Xj3P9UnGkjJQ9LGTr7AYZdLk4zISegF+/fZnOmaqUdZW9yWPPyJAzPw==
|
||||
"@tauri-apps/cli-win32-x64-msvc@1.0.0-rc.9":
|
||||
version "1.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.0.0-rc.9.tgz#4136d9837efb3c1bf56340d3b5abf56c10b8c7a5"
|
||||
integrity sha512-hJjnpl864OhpIp2lTMTW4ad2Aia5/Tbf7k8GJILzUY/XkBhZjNIgZORa8bDcnZRCTU+RDgMFc+AoKtDIircjnA==
|
||||
|
||||
"@tauri-apps/cli@^1.0.0-rc.8":
|
||||
version "1.0.0-rc.8"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-1.0.0-rc.8.tgz#ee8c9a587739853bd5f8a46a456a43ae594610f6"
|
||||
integrity sha512-FWpNwbgGMPgDb41oO7wdBhBsBE6FMG9yHKbtbrkJ/8d/hWcT6e3UUTfFL9cR2VGdp1pdWlul5+BKH0PTf8rB9w==
|
||||
"@tauri-apps/cli@^1.0.0-rc.9":
|
||||
version "1.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-1.0.0-rc.9.tgz#727159fa07bb2829b27abc3540324adfcff59f7a"
|
||||
integrity sha512-j+HZ65wdfFrMwisYeQpdZnldONevBPHjAo9v9Impf0irUU2UR5nwyvyArHTaWCvNeqEs+YV4XXHsfm2xVpnaug==
|
||||
optionalDependencies:
|
||||
"@tauri-apps/cli-darwin-arm64" "1.0.0-rc.8"
|
||||
"@tauri-apps/cli-darwin-x64" "1.0.0-rc.8"
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf" "1.0.0-rc.8"
|
||||
"@tauri-apps/cli-linux-arm64-gnu" "1.0.0-rc.8"
|
||||
"@tauri-apps/cli-linux-arm64-musl" "1.0.0-rc.8"
|
||||
"@tauri-apps/cli-linux-x64-gnu" "1.0.0-rc.8"
|
||||
"@tauri-apps/cli-linux-x64-musl" "1.0.0-rc.8"
|
||||
"@tauri-apps/cli-win32-ia32-msvc" "1.0.0-rc.8"
|
||||
"@tauri-apps/cli-win32-x64-msvc" "1.0.0-rc.8"
|
||||
"@tauri-apps/cli-darwin-arm64" "1.0.0-rc.9"
|
||||
"@tauri-apps/cli-darwin-x64" "1.0.0-rc.9"
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf" "1.0.0-rc.9"
|
||||
"@tauri-apps/cli-linux-arm64-gnu" "1.0.0-rc.9"
|
||||
"@tauri-apps/cli-linux-arm64-musl" "1.0.0-rc.9"
|
||||
"@tauri-apps/cli-linux-x64-gnu" "1.0.0-rc.9"
|
||||
"@tauri-apps/cli-linux-x64-musl" "1.0.0-rc.9"
|
||||
"@tauri-apps/cli-win32-ia32-msvc" "1.0.0-rc.9"
|
||||
"@tauri-apps/cli-win32-x64-msvc" "1.0.0-rc.9"
|
||||
|
||||
"@types/fs-extra@^9.0.13":
|
||||
version "9.0.13"
|
||||
@@ -2033,10 +2033,10 @@ tunnel@0.0.6:
|
||||
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
|
||||
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
|
||||
|
||||
type-fest@2.12.1:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.1.tgz#d2be8f50bf5f8f0a5fd916d29bf3e98c17e960be"
|
||||
integrity sha512-AiknQSEqKVGDDjtZqeKrUoTlcj7FKhupmnVUgz6KoOKtvMwRGE6hUNJ/nVear+h7fnUPO1q/htSkYKb1pyntkQ==
|
||||
type-fest@2.12.2:
|
||||
version "2.12.2"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.2.tgz#80a53614e6b9b475eb9077472fb7498dc7aa51d0"
|
||||
integrity sha512-qt6ylCGpLjZ7AaODxbpyBZSs9fCI9SkL3Z9q2oxMBQhs/uyY+VD8jHA8ULCGmWQJlBgqvO3EJeAngOHD8zQCrQ==
|
||||
|
||||
typescript@^4.5.5:
|
||||
version "4.6.3"
|
||||
|
||||
Reference in New Issue
Block a user