feat: refactor commands and support update profile
This commit is contained in:
parent
c1bcfc6785
commit
98378e6261
@ -1,215 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
config::{read_profiles, save_profiles, ProfileItem, ProfilesConfig},
|
|
||||||
events::{
|
|
||||||
emit::ClashInfoPayload,
|
|
||||||
state::{ClashInfoState, ProfileLock},
|
|
||||||
},
|
|
||||||
utils::{
|
|
||||||
app_home_dir,
|
|
||||||
clash::{self, put_clash_profile},
|
|
||||||
fetch::fetch_profile,
|
|
||||||
sysopt::{set_proxy_config, SysProxyConfig},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Write;
|
|
||||||
use tauri::{api::process::kill_children, AppHandle, State};
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn restart_sidebar(app_handle: AppHandle, clash_info: State<'_, ClashInfoState>) {
|
|
||||||
kill_children();
|
|
||||||
let payload = clash::run_clash_bin(&app_handle);
|
|
||||||
|
|
||||||
if let Ok(mut arc) = clash_info.0.lock() {
|
|
||||||
*arc = payload;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn get_clash_info(clash_info: State<'_, ClashInfoState>) -> Option<ClashInfoPayload> {
|
|
||||||
match clash_info.0.lock() {
|
|
||||||
Ok(arc) => Some(arc.clone()),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Import the Profile from url and
|
|
||||||
/// save to the `profiles.yaml` file
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn import_profile(url: String, lock: State<'_, ProfileLock>) -> Result<String, String> {
|
|
||||||
let result = match fetch_profile(&url).await {
|
|
||||||
Some(r) => r,
|
|
||||||
None => {
|
|
||||||
log::error!("failed to fetch profile from `{}`", url);
|
|
||||||
return Err(format!("failed"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let path = app_home_dir().join("profiles").join(&result.file);
|
|
||||||
File::create(path)
|
|
||||||
.unwrap()
|
|
||||||
.write(result.data.as_bytes())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// get lock
|
|
||||||
match lock.0.lock() {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(_) => return Err(format!("can not get file locked")),
|
|
||||||
};
|
|
||||||
|
|
||||||
// update profiles.yaml
|
|
||||||
let mut profiles = read_profiles();
|
|
||||||
let mut items = match profiles.items {
|
|
||||||
Some(p) => p,
|
|
||||||
None => vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
let profile = ProfileItem {
|
|
||||||
name: Some(result.name),
|
|
||||||
file: Some(result.file),
|
|
||||||
mode: Some(format!("rule")),
|
|
||||||
url: Some(url),
|
|
||||||
selected: Some(vec![]), // Todo: parse the selected list
|
|
||||||
extra: Some(result.extra),
|
|
||||||
};
|
|
||||||
|
|
||||||
items.push(profile);
|
|
||||||
profiles.items = Some(items);
|
|
||||||
save_profiles(&profiles);
|
|
||||||
|
|
||||||
Ok(format!("success"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub fn get_profiles(lock: State<'_, ProfileLock>) -> Option<ProfilesConfig> {
|
|
||||||
match lock.0.lock() {
|
|
||||||
Ok(_) => Some(read_profiles()),
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
/// update the profile config
|
|
||||||
pub fn set_profiles(
|
|
||||||
current: usize,
|
|
||||||
profile: ProfileItem,
|
|
||||||
lock: State<'_, ProfileLock>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
match lock.0.lock() {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(_) => return Err(format!("can not get file locked")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut profiles = read_profiles();
|
|
||||||
let mut items = match profiles.items {
|
|
||||||
Some(p) => p,
|
|
||||||
None => vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
if current >= items.len() {
|
|
||||||
return Err(format!("out of profiles bound"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut origin = items[current].clone();
|
|
||||||
|
|
||||||
if profile.name.is_some() {
|
|
||||||
origin.name = profile.name;
|
|
||||||
}
|
|
||||||
if profile.file.is_some() {
|
|
||||||
origin.file = profile.file;
|
|
||||||
}
|
|
||||||
if profile.mode.is_some() {
|
|
||||||
origin.mode = profile.mode;
|
|
||||||
}
|
|
||||||
if profile.url.is_some() {
|
|
||||||
origin.url = profile.url;
|
|
||||||
}
|
|
||||||
if profile.selected.is_some() {
|
|
||||||
origin.selected = profile.selected;
|
|
||||||
}
|
|
||||||
if profile.extra.is_some() {
|
|
||||||
origin.extra = profile.extra;
|
|
||||||
}
|
|
||||||
|
|
||||||
items[current] = origin;
|
|
||||||
profiles.items = Some(items);
|
|
||||||
save_profiles(&profiles);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
/// change to target profile
|
|
||||||
pub async fn put_profiles(
|
|
||||||
current: usize,
|
|
||||||
lock: State<'_, ProfileLock>,
|
|
||||||
clash_info: State<'_, ClashInfoState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
match lock.0.lock() {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(_) => return Err(format!("can not get file locked")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let clash_info = match clash_info.0.lock() {
|
|
||||||
Ok(arc) => arc.clone(),
|
|
||||||
_ => return Err(format!("can not get clash info")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut profiles = read_profiles();
|
|
||||||
let items_len = match &profiles.items {
|
|
||||||
Some(p) => p.len(),
|
|
||||||
None => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if current >= items_len {
|
|
||||||
return Err(format!(
|
|
||||||
"failed to change profile to the index `{}`",
|
|
||||||
current
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
profiles.current = Some(current as u32);
|
|
||||||
save_profiles(&profiles);
|
|
||||||
put_clash_profile(&clash_info).await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
/// set system proxy
|
|
||||||
pub fn set_sys_proxy(enable: bool, clash_info: State<'_, ClashInfoState>) -> Result<(), String> {
|
|
||||||
let clash_info = match clash_info.0.lock() {
|
|
||||||
Ok(arc) => arc.clone(),
|
|
||||||
_ => return Err(format!("can not get clash info")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let port = match clash_info.controller {
|
|
||||||
Some(ctrl) => ctrl.port,
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if port.is_none() {
|
|
||||||
return Err(format!("can not get clash core's port"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let config = if enable {
|
|
||||||
let server = format!("127.0.0.1:{}", port.unwrap());
|
|
||||||
// todo
|
|
||||||
let bypass = String::from("localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*");
|
|
||||||
|
|
||||||
SysProxyConfig {
|
|
||||||
enable,
|
|
||||||
server,
|
|
||||||
bypass,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SysProxyConfig {
|
|
||||||
enable,
|
|
||||||
server: String::from(""),
|
|
||||||
bypass: String::from(""),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match set_proxy_config(&config) {
|
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(_) => Err(format!("can not set proxy")),
|
|
||||||
}
|
|
||||||
}
|
|
2
src-tauri/src/cmds/mod.rs
Normal file
2
src-tauri/src/cmds/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod profile;
|
||||||
|
pub mod some;
|
172
src-tauri/src/cmds/profile.rs
Normal file
172
src-tauri/src/cmds/profile.rs
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
use crate::{
|
||||||
|
config::{read_profiles, save_profiles, ProfileItem, ProfilesConfig},
|
||||||
|
events::state::{ClashInfoState, ProfileLock},
|
||||||
|
utils::{app_home_dir, clash::put_clash_profile, fetch::fetch_profile},
|
||||||
|
};
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
use tauri::State;
|
||||||
|
|
||||||
|
/// Import the profile from url
|
||||||
|
/// and save to `profiles.yaml`
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn import_profile(url: String, lock: State<'_, ProfileLock>) -> Result<(), String> {
|
||||||
|
let result = match fetch_profile(&url).await {
|
||||||
|
Some(r) => r,
|
||||||
|
None => {
|
||||||
|
log::error!("failed to fetch profile from `{}`", url);
|
||||||
|
return Err(format!("failed to fetch profile from `{}`", url));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// get lock
|
||||||
|
if lock.0.lock().is_err() {
|
||||||
|
return Err(format!("can not get file lock"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the profile file
|
||||||
|
let path = app_home_dir().join("profiles").join(&result.file);
|
||||||
|
let file_data = result.data.as_bytes();
|
||||||
|
File::create(path).unwrap().write(file_data).unwrap();
|
||||||
|
|
||||||
|
// update `profiles.yaml`
|
||||||
|
let mut profiles = read_profiles();
|
||||||
|
let mut items = profiles.items.unwrap_or(vec![]);
|
||||||
|
|
||||||
|
items.push(ProfileItem {
|
||||||
|
name: Some(result.name),
|
||||||
|
file: Some(result.file),
|
||||||
|
mode: Some(format!("rule")),
|
||||||
|
url: Some(url),
|
||||||
|
selected: Some(vec![]),
|
||||||
|
extra: Some(result.extra),
|
||||||
|
});
|
||||||
|
profiles.items = Some(items);
|
||||||
|
save_profiles(&profiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the profile
|
||||||
|
/// and save to `profiles.yaml`
|
||||||
|
/// http request firstly
|
||||||
|
/// then acquire the lock of `profiles.yaml`
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn update_profile(index: usize, lock: State<'_, ProfileLock>) -> Result<(), String> {
|
||||||
|
// get lock
|
||||||
|
if lock.0.lock().is_err() {
|
||||||
|
return Err(format!("can not get file lock"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// update `profiles.yaml`
|
||||||
|
let mut profiles = read_profiles();
|
||||||
|
let mut items = profiles.items.unwrap_or(vec![]);
|
||||||
|
|
||||||
|
if index >= items.len() {
|
||||||
|
return Err(format!("the index out of bound"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let url = match &items[index].url {
|
||||||
|
Some(u) => u,
|
||||||
|
None => return Err(format!("invalid url")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = match fetch_profile(&url).await {
|
||||||
|
Some(r) => r,
|
||||||
|
None => {
|
||||||
|
log::error!("failed to fetch profile from `{}`", url);
|
||||||
|
return Err(format!("failed to fetch profile from `{}`", url));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// update file
|
||||||
|
let file_path = &items[index].file.as_ref().unwrap();
|
||||||
|
let file_path = app_home_dir().join("profiles").join(file_path);
|
||||||
|
let file_data = result.data.as_bytes();
|
||||||
|
File::create(file_path).unwrap().write(file_data).unwrap();
|
||||||
|
|
||||||
|
items[index].name = Some(result.name);
|
||||||
|
items[index].extra = Some(result.extra);
|
||||||
|
profiles.items = Some(items);
|
||||||
|
save_profiles(&profiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get all profiles from `profiles.yaml`
|
||||||
|
/// do not acquire the lock of ProfileLock
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn get_profiles() -> Result<ProfilesConfig, String> {
|
||||||
|
Ok(read_profiles())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// patch the profile config
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn set_profiles(
|
||||||
|
index: usize,
|
||||||
|
profile: ProfileItem,
|
||||||
|
lock: State<'_, ProfileLock>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
// get lock
|
||||||
|
if lock.0.lock().is_err() {
|
||||||
|
return Err(format!("can not get file lock"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut profiles = read_profiles();
|
||||||
|
let mut items = profiles.items.unwrap_or(vec![]);
|
||||||
|
|
||||||
|
if index >= items.len() {
|
||||||
|
return Err(format!("the index out of bound"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if profile.name.is_some() {
|
||||||
|
items[index].name = profile.name;
|
||||||
|
}
|
||||||
|
if profile.file.is_some() {
|
||||||
|
items[index].file = profile.file;
|
||||||
|
}
|
||||||
|
if profile.mode.is_some() {
|
||||||
|
items[index].mode = profile.mode;
|
||||||
|
}
|
||||||
|
if profile.url.is_some() {
|
||||||
|
items[index].url = profile.url;
|
||||||
|
}
|
||||||
|
if profile.selected.is_some() {
|
||||||
|
items[index].selected = profile.selected;
|
||||||
|
}
|
||||||
|
if profile.extra.is_some() {
|
||||||
|
items[index].extra = profile.extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
profiles.items = Some(items);
|
||||||
|
save_profiles(&profiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// change the current profile
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn put_profiles(
|
||||||
|
current: usize,
|
||||||
|
lock: State<'_, ProfileLock>,
|
||||||
|
clash_info: State<'_, ClashInfoState>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
if lock.0.lock().is_err() {
|
||||||
|
return Err(format!("can not get file lock"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let clash_info = match clash_info.0.lock() {
|
||||||
|
Ok(arc) => arc.clone(),
|
||||||
|
_ => return Err(format!("can not get clash info")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut profiles = read_profiles();
|
||||||
|
let items_len = match &profiles.items {
|
||||||
|
Some(list) => list.len(),
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
if current >= items_len {
|
||||||
|
return Err(format!("the index out of bound"));
|
||||||
|
}
|
||||||
|
|
||||||
|
profiles.current = Some(current as u32);
|
||||||
|
match save_profiles(&profiles) {
|
||||||
|
Ok(_) => put_clash_profile(&clash_info).await,
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
|
}
|
70
src-tauri/src/cmds/some.rs
Normal file
70
src-tauri/src/cmds/some.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use crate::{
|
||||||
|
events::{emit::ClashInfoPayload, state::ClashInfoState},
|
||||||
|
utils::{
|
||||||
|
clash::run_clash_bin,
|
||||||
|
sysopt::{set_proxy_config, SysProxyConfig},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use tauri::{api::process::kill_children, AppHandle, State};
|
||||||
|
|
||||||
|
/// restart the sidecar
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn restart_sidecar(app_handle: AppHandle, clash_info: State<'_, ClashInfoState>) {
|
||||||
|
kill_children();
|
||||||
|
let payload = run_clash_bin(&app_handle);
|
||||||
|
|
||||||
|
if let Ok(mut arc) = clash_info.0.lock() {
|
||||||
|
*arc = payload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get the clash core info from the state
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn get_clash_info(clash_info: State<'_, ClashInfoState>) -> Result<ClashInfoPayload, String> {
|
||||||
|
match clash_info.0.lock() {
|
||||||
|
Ok(arc) => Ok(arc.clone()),
|
||||||
|
Err(_) => Err(format!("can not get clash info")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set the system proxy
|
||||||
|
/// Tips: only support windows now
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn set_sys_proxy(enable: bool, clash_info: State<'_, ClashInfoState>) -> Result<(), String> {
|
||||||
|
let clash_info = match clash_info.0.lock() {
|
||||||
|
Ok(arc) => arc.clone(),
|
||||||
|
_ => return Err(format!("can not get clash info")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let port = match clash_info.controller {
|
||||||
|
Some(ctrl) => ctrl.port,
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if port.is_none() {
|
||||||
|
return Err(format!("can not get clash core's port"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = if enable {
|
||||||
|
let server = format!("127.0.0.1:{}", port.unwrap());
|
||||||
|
// todo
|
||||||
|
let bypass = String::from("localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*");
|
||||||
|
|
||||||
|
SysProxyConfig {
|
||||||
|
enable,
|
||||||
|
server,
|
||||||
|
bypass,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SysProxyConfig {
|
||||||
|
enable,
|
||||||
|
server: String::from(""),
|
||||||
|
bypass: String::from(""),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match set_proxy_config(&config) {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(_) => Err(format!("can not set proxy")),
|
||||||
|
}
|
||||||
|
}
|
@ -99,13 +99,12 @@ pub fn read_profiles() -> ProfilesConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Save Verge App Config
|
/// Save Verge App Config
|
||||||
pub fn save_profiles(profiles: &ProfilesConfig) {
|
pub fn save_profiles(profiles: &ProfilesConfig) -> Result<(), String> {
|
||||||
save_yaml(
|
save_yaml(
|
||||||
app_home_dir().join("profiles.yaml"),
|
app_home_dir().join("profiles.yaml"),
|
||||||
profiles,
|
profiles,
|
||||||
Some("# Profiles Config for Clash Verge\n\n"),
|
Some("# Profiles Config for Clash Verge\n\n"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
extern crate tauri;
|
extern crate tauri;
|
||||||
|
|
||||||
mod cmd;
|
mod cmds;
|
||||||
mod config;
|
mod config;
|
||||||
mod events;
|
mod events;
|
||||||
mod utils;
|
mod utils;
|
||||||
@ -57,13 +57,14 @@ fn main() -> std::io::Result<()> {
|
|||||||
_ => {}
|
_ => {}
|
||||||
})
|
})
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
cmd::restart_sidebar,
|
cmds::some::restart_sidecar,
|
||||||
cmd::get_clash_info,
|
cmds::some::get_clash_info,
|
||||||
cmd::import_profile,
|
cmds::some::set_sys_proxy,
|
||||||
cmd::get_profiles,
|
cmds::profile::import_profile,
|
||||||
cmd::set_profiles,
|
cmds::profile::update_profile,
|
||||||
cmd::put_profiles,
|
cmds::profile::get_profiles,
|
||||||
cmd::set_sys_proxy,
|
cmds::profile::set_profiles,
|
||||||
|
cmds::profile::put_profiles,
|
||||||
])
|
])
|
||||||
.build(tauri::generate_context!())
|
.build(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
@ -28,10 +28,11 @@ interface Props {
|
|||||||
selected: boolean;
|
selected: boolean;
|
||||||
itemData: ProfileItem;
|
itemData: ProfileItem;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
|
onUpdate: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProfileItemComp: React.FC<Props> = (props) => {
|
const ProfileItemComp: React.FC<Props> = (props) => {
|
||||||
const { selected, itemData, onClick } = props;
|
const { selected, itemData, onClick, onUpdate } = props;
|
||||||
|
|
||||||
const { name = "Profile", extra } = itemData;
|
const { name = "Profile", extra } = itemData;
|
||||||
const { upload = 0, download = 0, total = 0 } = extra ?? {};
|
const { upload = 0, download = 0, total = 0 } = extra ?? {};
|
||||||
@ -87,6 +88,7 @@ const ProfileItemComp: React.FC<Props> = (props) => {
|
|||||||
color="inherit"
|
color="inherit"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
onUpdate();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuRounded />
|
<MenuRounded />
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import useSWR, { useSWRConfig } from "swr";
|
import useSWR, { useSWRConfig } from "swr";
|
||||||
import { Box, Button, Grid, TextField, Typography } from "@mui/material";
|
import { Box, Button, Grid, TextField, Typography } from "@mui/material";
|
||||||
import { getProfiles, importProfile, putProfiles } from "../services/command";
|
import {
|
||||||
|
getProfiles,
|
||||||
|
importProfile,
|
||||||
|
putProfiles,
|
||||||
|
updateProfile,
|
||||||
|
} from "../services/command";
|
||||||
import ProfileItemComp from "../components/profile-item";
|
import ProfileItemComp from "../components/profile-item";
|
||||||
import useNotice from "../utils/use-notice";
|
import useNotice from "../utils/use-notice";
|
||||||
|
|
||||||
@ -33,6 +38,16 @@ const RulesPage = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onUpdateProfile = (index: number) => {
|
||||||
|
updateProfile(index)
|
||||||
|
.then(() => {
|
||||||
|
mutate("getProfiles");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: 0.9, maxWidth: "850px", mx: "auto", mb: 2 }}>
|
<Box sx={{ width: 0.9, maxWidth: "850px", mx: "auto", mb: 2 }}>
|
||||||
<Typography variant="h4" component="h1" sx={{ py: 2, mb: 1 }}>
|
<Typography variant="h4" component="h1" sx={{ py: 2, mb: 1 }}>
|
||||||
@ -66,6 +81,7 @@ const RulesPage = () => {
|
|||||||
selected={profiles.current === idx}
|
selected={profiles.current === idx}
|
||||||
itemData={item}
|
itemData={item}
|
||||||
onClick={() => onProfileChange(idx)}
|
onClick={() => onProfileChange(idx)}
|
||||||
|
onUpdate={() => onUpdateProfile(idx)}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { invoke } from "@tauri-apps/api/tauri";
|
import { invoke } from "@tauri-apps/api/tauri";
|
||||||
|
|
||||||
export async function restartSidecar() {
|
export async function restartSidecar() {
|
||||||
return invoke<void>("restart_sidebar");
|
return invoke<void>("restart_sidecar");
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClashInfo {
|
export interface ClashInfo {
|
||||||
@ -15,7 +15,11 @@ export async function getClashInfo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function importProfile(url: string) {
|
export async function importProfile(url: string) {
|
||||||
return invoke<string>("import_profile", { url });
|
return invoke<void>("import_profile", { url });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateProfile(index: number) {
|
||||||
|
return invoke<void>("update_profile", { index });
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProfileItem {
|
export interface ProfileItem {
|
||||||
|
Loading…
Reference in New Issue
Block a user