diff --git a/package.json b/package.json index b4600393..6f1e60f8 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "dayjs": "1.11.5", "i18next": "^23.7.16", "lodash-es": "^4.17.21", - "monaco-editor": "^0.34.1", + "monaco-editor": "^0.47.0", + "monaco-yaml": "^5.1.1", "nanoid": "^5.0.4", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/src/components/connection/connection-detail.tsx b/src/components/connection/connection-detail.tsx index 7ed786e2..1ddfc2c7 100644 --- a/src/components/connection/connection-detail.tsx +++ b/src/components/connection/connection-detail.tsx @@ -3,8 +3,8 @@ import { forwardRef, useImperativeHandle, useState } from "react"; import { useLockFn } from "ahooks"; import { Box, Button, Snackbar } from "@mui/material"; import { deleteConnection } from "@/services/api"; -import { truncateStr } from "@/utils/truncate-str"; import parseTraffic from "@/utils/parse-traffic"; +import { t } from "i18next"; export interface ConnectionDetailRef { open: (detail: IConnectionsItem) => void; @@ -69,7 +69,9 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { { label: "Rule", value: rule }, { label: "Process", - value: truncateStr(metadata.process || metadata.processPath), + value: `${metadata.process}${ + metadata.processPath ? `(${metadata.processPath})` : "" + }`, }, { label: "Time", value: dayjs(data.start).fromNow() }, { label: "Source", value: `${metadata.sourceIP}:${metadata.sourcePort}` }, @@ -96,7 +98,7 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { onClose?.(); }} > - Close + {t("Close")} diff --git a/src/components/profile/editor-viewer.tsx b/src/components/profile/editor-viewer.tsx index 0856227d..e2cabc7d 100644 --- a/src/components/profile/editor-viewer.tsx +++ b/src/components/profile/editor-viewer.tsx @@ -12,23 +12,39 @@ import { import { atomThemeMode } from "@/services/states"; import { readProfileFile, saveProfileFile } from "@/services/cmds"; import { Notice } from "@/components/base"; +import { nanoid } from "nanoid"; -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 * as monaco from "monaco-editor"; import { editor } from "monaco-editor/esm/vs/editor/editor.api"; +import { configureMonacoYaml } from "monaco-yaml"; interface Props { uid: string; open: boolean; - mode: "yaml" | "javascript"; + language: "yaml" | "javascript"; + schema?: "clash" | "merge"; onClose: () => void; onChange?: () => void; } -export const EditorViewer = (props: Props) => { - const { uid, open, mode, onClose, onChange } = props; +// yaml worker +configureMonacoYaml(monaco, { + validate: true, + enableSchemaRequest: true, + schemas: [ + { + uri: "https://fastly.jsdelivr.net/gh/dongchengjie/meta-json-schema@main/schemas/meta-json-schema.json", + fileMatch: ["**/*.clash.yaml"], + }, + { + uri: "https://fastly.jsdelivr.net/gh/dongchengjie/meta-json-schema@main/schemas/clash-verge-merge-json-schema.json", + fileMatch: ["**/*.merge.yaml"], + }, + ], +}); +export const EditorViewer = (props: Props) => { + const { uid, open, language, schema, onClose, onChange } = props; const { t } = useTranslation(); const editorRef = useRef(); const instanceRef = useRef(null); @@ -41,13 +57,21 @@ export const EditorViewer = (props: Props) => { const dom = editorRef.current; if (!dom) return; + if (instanceRef.current) instanceRef.current.dispose(); + const uri = monaco.Uri.parse(`${nanoid()}.${schema}.${language}`); + const model = monaco.editor.createModel(data, language, uri); instanceRef.current = editor.create(editorRef.current, { - value: data, - language: mode, + model: model, + language: language, theme: themeMode === "light" ? "vs" : "vs-dark", - minimap: { enabled: false }, + minimap: { enabled: dom.clientWidth >= 1000 }, // 超过一定宽度显示minimap滚动条 + quickSuggestions: { + strings: true, // 字符串类型的建议 + comments: true, // 注释类型的建议 + other: true, // 其他类型的建议 + }, }); }); @@ -77,8 +101,10 @@ export const EditorViewer = (props: Props) => { {t("Edit File")} - -
+ +
diff --git a/src/components/profile/profile-item.tsx b/src/components/profile/profile-item.tsx index 94c092e4..180a0ed6 100644 --- a/src/components/profile/profile-item.tsx +++ b/src/components/profile/profile-item.tsx @@ -386,7 +386,8 @@ export const ProfileItem = (props: Props) => { setFileOpen(false)} /> { setFileOpen(false)} /> { const isTableLayout = setting.layout === "table"; const orderOpts: Record = { - Default: (list) => list, + Default: (list) => + list.sort( + (a, b) => + new Date(b.start || "0").getTime()! - + new Date(a.start || "0").getTime()! + ), "Upload Speed": (list) => list.sort((a, b) => b.curUpload! - a.curUpload!), "Download Speed": (list) => list.sort((a, b) => b.curDownload! - a.curDownload!), diff --git a/vite.config.ts b/vite.config.ts index 186228ee..28916420 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,7 +2,7 @@ import { defineConfig } from "vite"; import path from "path"; import svgr from "vite-plugin-svgr"; import react from "@vitejs/plugin-react"; -import monaco from "vite-plugin-monaco-editor"; +import monacoEditor from "vite-plugin-monaco-editor"; // https://vitejs.dev/config/ export default defineConfig({ @@ -11,7 +11,15 @@ export default defineConfig({ plugins: [ svgr(), react(), - monaco({ languageWorkers: ["editorWorkerService", "typescript"] }), + monacoEditor({ + languageWorkers: ["editorWorkerService", "typescript"], + customWorkers: [ + { + label: "yaml", + entry: "monaco-yaml/yaml.worker", + }, + ], + }), ], build: { outDir: "../dist",