fix: 使用npm安装meta-json-schema (#895)

* feat: allow manual selection of url-test group

* feat: fixed proxy indicator

* fix: try to fix traffic websocket no longer updating

* fixup: group delay test use defined url

* feat: connections sorted by start by default

* feat: Connection details show the full path of the process

* fix: editor no hints and add yaml support

* feat: quick suggestions

* chore: use monaco-editor

* chore: update schema url

* chore: change default merge config content

* fix: load schema via npm

* feat: runtime config viewer style auto adjust

* feat: adjust fixed proxy style

* fix: headState "showType" won't toggle hover text

* chore: switch version

* chore: Update pnpm lockfile
This commit is contained in:
dongchengjie 2024-04-19 13:54:16 +08:00 committed by GitHub
parent d13b8fd486
commit 0865b702a3
9 changed files with 766 additions and 717 deletions

View File

@ -34,6 +34,7 @@
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"monaco-editor": "^0.47.0", "monaco-editor": "^0.47.0",
"monaco-yaml": "^5.1.1", "monaco-yaml": "^5.1.1",
"meta-json-schema": "^1.18.3-beta",
"nanoid": "^5.0.4", "nanoid": "^5.0.4",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",

1405
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,10 @@ import * as monaco from "monaco-editor";
import { editor } from "monaco-editor/esm/vs/editor/editor.api"; import { editor } from "monaco-editor/esm/vs/editor/editor.api";
import { configureMonacoYaml } from "monaco-yaml"; import { configureMonacoYaml } from "monaco-yaml";
import { type JSONSchema7 } from "json-schema";
import metaSchema from "meta-json-schema/schemas/meta-json-schema.json";
import mergeSchema from "meta-json-schema/schemas/clash-verge-merge-json-schema.json";
interface Props { interface Props {
uid: string; uid: string;
open: boolean; open: boolean;
@ -33,12 +37,14 @@ configureMonacoYaml(monaco, {
enableSchemaRequest: true, enableSchemaRequest: true,
schemas: [ schemas: [
{ {
uri: "https://fastly.jsdelivr.net/gh/dongchengjie/meta-json-schema@main/schemas/meta-json-schema.json", uri: "http://example.com/meta-json-schema.json",
fileMatch: ["**/*.clash.yaml"], fileMatch: ["**/*.clash.yaml"],
schema: metaSchema as JSONSchema7,
}, },
{ {
uri: "https://fastly.jsdelivr.net/gh/dongchengjie/meta-json-schema@main/schemas/clash-verge-merge-json-schema.json", uri: "http://example.com/clash-verge-merge-json-schema.json",
fileMatch: ["**/*.merge.yaml"], fileMatch: ["**/*.merge.yaml"],
schema: mergeSchema as JSONSchema7,
}, },
], ],
}); });
@ -65,8 +71,10 @@ export const EditorViewer = (props: Props) => {
instanceRef.current = editor.create(editorRef.current, { instanceRef.current = editor.create(editorRef.current, {
model: model, model: model,
language: language, language: language,
tabSize: ["yaml", "javascript"].includes(language) ? 2 : 4, // 根据语言类型设置缩进
theme: themeMode === "light" ? "vs" : "vs-dark", theme: themeMode === "light" ? "vs" : "vs-dark",
minimap: { enabled: dom.clientWidth >= 1000 }, // 超过一定宽度显示minimap滚动条 minimap: { enabled: dom.clientWidth >= 1000 }, // 超过一定宽度显示minimap滚动条
mouseWheelZoom: true, // Ctrl+滚轮调节缩放
quickSuggestions: { quickSuggestions: {
strings: true, // 字符串类型的建议 strings: true, // 字符串类型的建议
comments: true, // 注释类型的建议 comments: true, // 注释类型的建议
@ -102,7 +110,7 @@ export const EditorViewer = (props: Props) => {
<DialogTitle>{t("Edit File")}</DialogTitle> <DialogTitle>{t("Edit File")}</DialogTitle>
<DialogContent <DialogContent
sx={{ width: "95%", height: "100vh", pb: 1, userSelect: "text" }} sx={{ width: "94%", height: "100vh", pb: 1, userSelect: "text" }}
> >
<div style={{ width: "100%", height: "100%" }} ref={editorRef} /> <div style={{ width: "100%", height: "100%" }} ref={editorRef} />
</DialogContent> </DialogContent>

View File

@ -109,7 +109,7 @@ export const ProxyHead = (props: Props) => {
<IconButton <IconButton
size="small" size="small"
color="inherit" color="inherit"
title={t("Proxy detail")} title={showType ? t("Proxy basic") : t("Proxy detail")}
onClick={() => onHeadState({ showType: !showType })} onClick={() => onHeadState({ showType: !showType })}
> >
{showType ? <VisibilityRounded /> : <VisibilityOffRounded />} {showType ? <VisibilityRounded /> : <VisibilityOffRounded />}

View File

@ -67,8 +67,9 @@ export const ProxyItemMini = (props: Props) => {
"&:hover .the-icon": { display: "none" }, "&:hover .the-icon": { display: "none" },
"& .the-pin, & .the-unpin": { "& .the-pin, & .the-unpin": {
position: "absolute", position: "absolute",
top: "-8px", fontSize: "12px",
right: "-8px", top: "-5px",
right: "-5px",
}, },
"& .the-unpin": { filter: "grayscale(1)" }, "& .the-unpin": { filter: "grayscale(1)" },
"&.Mui-selected": { "&.Mui-selected": {

View File

@ -7,10 +7,17 @@ import {
} from "react"; } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useRecoilValue } from "recoil"; import { useRecoilValue } from "recoil";
import { Chip } from "@mui/material"; import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Chip,
} from "@mui/material";
import { atomThemeMode } from "@/services/states"; import { atomThemeMode } from "@/services/states";
import { getRuntimeYaml } from "@/services/cmds"; import { getRuntimeYaml } from "@/services/cmds";
import { BaseDialog, DialogRef } from "@/components/base"; import { DialogRef } from "@/components/base";
import { editor } from "monaco-editor/esm/vs/editor/editor.api"; import { editor } from "monaco-editor/esm/vs/editor/editor.api";
import "monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js"; import "monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js";
@ -47,9 +54,12 @@ export const ConfigViewer = forwardRef<DialogRef>((props, ref) => {
instanceRef.current = editor.create(editorRef.current, { instanceRef.current = editor.create(editorRef.current, {
value: data ?? "# Error\n", value: data ?? "# Error\n",
language: "yaml", language: "yaml",
tabSize: 2,
theme: themeMode === "light" ? "vs" : "vs-dark", theme: themeMode === "light" ? "vs" : "vs-dark",
minimap: { enabled: false }, minimap: { enabled: dom.clientWidth >= 1000 }, // 超过一定宽度显示minimap滚动条
readOnly: true, mouseWheelZoom: true, // Ctrl+滚轮调节缩放
readOnly: true, // 只读
readOnlyMessage: { value: t("ReadOnlyMessage") },
}); });
}); });
}, },
@ -57,20 +67,22 @@ export const ConfigViewer = forwardRef<DialogRef>((props, ref) => {
})); }));
return ( return (
<BaseDialog <Dialog open={open} onClose={() => setOpen(false)} maxWidth="xl" fullWidth>
open={open} <DialogTitle>
title={
<>
{t("Runtime Config")} <Chip label={t("ReadOnly")} size="small" /> {t("Runtime Config")} <Chip label={t("ReadOnly")} size="small" />
</> </DialogTitle>
}
contentSx={{ width: 520, pb: 1, userSelect: "text" }} <DialogContent
cancelBtn={t("Back")} sx={{ width: "94%", height: "100vh", pb: 1, userSelect: "text" }}
disableOk
onClose={() => setOpen(false)}
onCancel={() => setOpen(false)}
> >
<div style={{ width: "100%", height: "420px" }} ref={editorRef} /> <div style={{ width: "100%", height: "100%" }} ref={editorRef} />
</BaseDialog> </DialogContent>
<DialogActions>
<Button onClick={() => setOpen(false)} variant="outlined">
{t("Back")}
</Button>
</DialogActions>
</Dialog>
); );
}); });

View File

@ -54,6 +54,7 @@
"Sort by delay": "Sort by delay", "Sort by delay": "Sort by delay",
"Sort by name": "Sort by name", "Sort by name": "Sort by name",
"Delay check URL": "Delay check URL", "Delay check URL": "Delay check URL",
"Proxy basic": "Proxy basic",
"Proxy detail": "Proxy detail", "Proxy detail": "Proxy detail",
"Filter": "Filter", "Filter": "Filter",
"Filter conditions": "Filter conditions", "Filter conditions": "Filter conditions",
@ -129,6 +130,7 @@
"Clash Field": "Clash Field", "Clash Field": "Clash Field",
"Runtime Config": "Runtime Config", "Runtime Config": "Runtime Config",
"ReadOnly": "ReadOnly", "ReadOnly": "ReadOnly",
"ReadOnlyMessage": "Cannot edit in read-only editor",
"Restart": "Restart", "Restart": "Restart",
"Upgrade": "Upgrade", "Upgrade": "Upgrade",

View File

@ -54,6 +54,7 @@
"Sort by delay": "Сортировать по задержке", "Sort by delay": "Сортировать по задержке",
"Sort by name": "Сортировать по названию", "Sort by name": "Сортировать по названию",
"Delay check URL": "URL проверки задержки", "Delay check URL": "URL проверки задержки",
"Proxy basic": "Резюме о прокси",
"Proxy detail": "Подробности о прокси", "Proxy detail": "Подробности о прокси",
"Filter": "Фильтр", "Filter": "Фильтр",
"Filter conditions": "Условия фильтрации", "Filter conditions": "Условия фильтрации",
@ -115,6 +116,7 @@
"Clash Field": "Используемые настройки Clash", "Clash Field": "Используемые настройки Clash",
"Runtime Config": "Используемый конфиг", "Runtime Config": "Используемый конфиг",
"ReadOnly": "Только для чтения", "ReadOnly": "Только для чтения",
"ReadOnlyMessage": "Невозможно редактировать в режиме только для чтения",
"Restart": "Перезапуск", "Restart": "Перезапуск",
"Upgrade": "Обновлять", "Upgrade": "Обновлять",

View File

@ -56,6 +56,7 @@
"Sort by delay": "按延迟排序", "Sort by delay": "按延迟排序",
"Sort by name": "按名称排序", "Sort by name": "按名称排序",
"Delay check URL": "延迟测试链接", "Delay check URL": "延迟测试链接",
"Proxy basic": "隐藏节点细节",
"Proxy detail": "展示节点细节", "Proxy detail": "展示节点细节",
"Filter": "过滤节点", "Filter": "过滤节点",
"Filter conditions": "过滤条件", "Filter conditions": "过滤条件",
@ -135,6 +136,7 @@
"Clash Field": "Clash 字段", "Clash Field": "Clash 字段",
"Runtime Config": "当前配置", "Runtime Config": "当前配置",
"ReadOnly": "只读", "ReadOnly": "只读",
"ReadOnlyMessage": "无法在只读模式下编辑",
"Restart": "重启内核", "Restart": "重启内核",
"Upgrade": "升级内核", "Upgrade": "升级内核",