feat: runtime config viewer
This commit is contained in:
parent
7633f9f88b
commit
a9bf32919e
@ -174,6 +174,13 @@ pub fn get_clash_info(core: State<'_, Core>) -> CmdResult<ClashInfo> {
|
|||||||
Ok(clash.info.clone())
|
Ok(clash.info.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get the running clash config string
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn get_running_config(core: State<'_, Core>) -> CmdResult<Option<String>> {
|
||||||
|
let clash = core.clash.lock();
|
||||||
|
Ok(clash.running_config.clone())
|
||||||
|
}
|
||||||
|
|
||||||
/// update the clash core config
|
/// update the clash core config
|
||||||
/// after putting the change to the clash core
|
/// after putting the change to the clash core
|
||||||
/// then we should save the latest config
|
/// then we should save the latest config
|
||||||
|
@ -87,6 +87,9 @@ pub struct Clash {
|
|||||||
|
|
||||||
/// some info
|
/// some info
|
||||||
pub info: ClashInfo,
|
pub info: ClashInfo,
|
||||||
|
|
||||||
|
/// save the running config
|
||||||
|
pub running_config: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clash {
|
impl Clash {
|
||||||
@ -94,7 +97,11 @@ impl Clash {
|
|||||||
let config = Clash::read_config();
|
let config = Clash::read_config();
|
||||||
let info = ClashInfo::from(&config);
|
let info = ClashInfo::from(&config);
|
||||||
|
|
||||||
Clash { config, info }
|
Clash {
|
||||||
|
config,
|
||||||
|
info,
|
||||||
|
running_config: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get clash config
|
/// get clash config
|
||||||
@ -111,6 +118,14 @@ impl Clash {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// save running config
|
||||||
|
pub fn set_running_config(&mut self, config: &Mapping) {
|
||||||
|
self.running_config = match serde_yaml::to_string(config) {
|
||||||
|
Ok(config_str) => Some(config_str),
|
||||||
|
Err(_) => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// patch update the clash config
|
/// patch update the clash config
|
||||||
/// if the port is changed then return true
|
/// if the port is changed then return true
|
||||||
pub fn patch_config(&mut self, patch: Mapping) -> Result<(bool, bool)> {
|
pub fn patch_config(&mut self, patch: Mapping) -> Result<(bool, bool)> {
|
||||||
|
@ -347,12 +347,10 @@ impl Core {
|
|||||||
Clash::strict_filter(data)
|
Clash::strict_filter(data)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mut config, info) = {
|
let mut clash = self.clash.lock();
|
||||||
let clash = self.clash.lock();
|
|
||||||
let config = clash.config.clone();
|
let mut config = clash.config.clone();
|
||||||
let info = clash.info.clone();
|
let info = clash.info.clone();
|
||||||
(config, info)
|
|
||||||
};
|
|
||||||
|
|
||||||
for (key, value) in data.into_iter() {
|
for (key, value) in data.into_iter() {
|
||||||
config.insert(key, value);
|
config.insert(key, value);
|
||||||
@ -369,6 +367,9 @@ impl Core {
|
|||||||
Notice::from(window.clone())
|
Notice::from(window.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clash.set_running_config(&config);
|
||||||
|
drop(clash);
|
||||||
|
|
||||||
let service = self.service.lock();
|
let service = self.service.lock();
|
||||||
service.set_config(info, config, notice)
|
service.set_config(info, config, notice)
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
cmds::get_clash_info,
|
cmds::get_clash_info,
|
||||||
cmds::patch_clash_config,
|
cmds::patch_clash_config,
|
||||||
cmds::change_clash_core,
|
cmds::change_clash_core,
|
||||||
|
cmds::get_running_config,
|
||||||
// verge
|
// verge
|
||||||
cmds::get_verge_config,
|
cmds::get_verge_config,
|
||||||
cmds::patch_verge_config,
|
cmds::patch_verge_config,
|
||||||
|
75
src/components/setting/config-viewer.tsx
Normal file
75
src/components/setting/config-viewer.tsx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useRecoilValue } from "recoil";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Chip,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { InfoRounded } from "@mui/icons-material";
|
||||||
|
import { atomThemeMode } from "../../services/states";
|
||||||
|
import { getRunningConfig } from "../../services/cmds";
|
||||||
|
|
||||||
|
import "monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js";
|
||||||
|
import "monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution.js";
|
||||||
|
import "monaco-editor/esm/vs/editor/contrib/folding/browser/folding.js";
|
||||||
|
import { editor } from "monaco-editor/esm/vs/editor/editor.api";
|
||||||
|
|
||||||
|
const ConfigViewer = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const editorRef = useRef<any>();
|
||||||
|
const instanceRef = useRef<editor.IStandaloneCodeEditor | null>(null);
|
||||||
|
const themeMode = useRecoilValue(atomThemeMode);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) return;
|
||||||
|
|
||||||
|
getRunningConfig().then((data) => {
|
||||||
|
const dom = editorRef.current;
|
||||||
|
|
||||||
|
if (!dom) return;
|
||||||
|
if (instanceRef.current) instanceRef.current.dispose();
|
||||||
|
|
||||||
|
instanceRef.current = editor.create(editorRef.current, {
|
||||||
|
value: data ?? "# Error\n",
|
||||||
|
language: "yaml",
|
||||||
|
theme: themeMode === "light" ? "vs" : "vs-dark",
|
||||||
|
minimap: { enabled: false },
|
||||||
|
readOnly: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (instanceRef.current) {
|
||||||
|
instanceRef.current.dispose();
|
||||||
|
instanceRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dialog open={open} onClose={() => setOpen(false)}>
|
||||||
|
<DialogTitle>
|
||||||
|
{t("Running Config")} <Chip label="ReadOnly" size="small" />
|
||||||
|
</DialogTitle>
|
||||||
|
|
||||||
|
<DialogContent sx={{ width: 520, pb: 1 }}>
|
||||||
|
<div style={{ width: "100%", height: "420px" }} ref={editorRef} />
|
||||||
|
</DialogContent>
|
||||||
|
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={() => setOpen(false)}>{t("Back")}</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<InfoRounded fontSize="small" onClick={() => setOpen(true)} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default ConfigViewer;
|
@ -18,6 +18,7 @@ import { SettingList, SettingItem } from "./setting";
|
|||||||
import { CmdType } from "../../services/types";
|
import { CmdType } from "../../services/types";
|
||||||
import GuardState from "./guard-state";
|
import GuardState from "./guard-state";
|
||||||
import ServiceMode from "./service-mode";
|
import ServiceMode from "./service-mode";
|
||||||
|
import ConfigViewer from "./config-viewer";
|
||||||
import SysproxyTooltip from "./sysproxy-tooltip";
|
import SysproxyTooltip from "./sysproxy-tooltip";
|
||||||
import getSystem from "../../utils/get-system";
|
import getSystem from "../../utils/get-system";
|
||||||
|
|
||||||
@ -58,7 +59,14 @@ const SettingSystem = ({ onError }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<SettingList title={t("System Setting")}>
|
<SettingList title={t("System Setting")}>
|
||||||
<SettingItem>
|
<SettingItem>
|
||||||
<ListItemText primary={t("Tun Mode")} />
|
<ListItemText
|
||||||
|
primary={
|
||||||
|
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||||
|
<span style={{ marginRight: 4 }}>{t("Tun Mode")}</span>
|
||||||
|
<ConfigViewer />
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<GuardState
|
<GuardState
|
||||||
value={enable_tun_mode ?? false}
|
value={enable_tun_mode ?? false}
|
||||||
valueProps="checked"
|
valueProps="checked"
|
||||||
|
@ -70,6 +70,10 @@ export async function getClashInfo() {
|
|||||||
return invoke<CmdType.ClashInfo | null>("get_clash_info");
|
return invoke<CmdType.ClashInfo | null>("get_clash_info");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getRunningConfig() {
|
||||||
|
return invoke<string | null>("get_running_config");
|
||||||
|
}
|
||||||
|
|
||||||
export async function patchClashConfig(payload: Partial<ApiType.ConfigData>) {
|
export async function patchClashConfig(payload: Partial<ApiType.ConfigData>) {
|
||||||
return invoke<void>("patch_clash_config", { payload });
|
return invoke<void>("patch_clash_config", { payload });
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user