소스 검색

feat: css injection editor

dongchengjie 1 년 전
부모
커밋
da4bf167ee

+ 1 - 1
package.json

@@ -36,7 +36,7 @@
     "dayjs": "1.11.5",
     "i18next": "^23.11.3",
     "lodash-es": "^4.17.21",
-    "meta-json-schema": "1.18.4-beta4",
+    "meta-json-schema": "1.18.4-beta5",
     "monaco-editor": "^0.47.0",
     "monaco-yaml": "^5.1.1",
     "nanoid": "^5.0.7",

+ 5 - 5
pnpm-lock.yaml

@@ -62,8 +62,8 @@ importers:
         specifier: ^4.17.21
         version: 4.17.21
       meta-json-schema:
-        specifier: 1.18.4-beta4
-        version: 1.18.4-beta4
+        specifier: 1.18.4-beta5
+        version: 1.18.4-beta5
       monaco-editor:
         specifier: ^0.47.0
         version: 0.47.0
@@ -2444,10 +2444,10 @@ packages:
         integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==,
       }
 
-  meta-json-schema@1.18.4-beta4:
+  meta-json-schema@1.18.4-beta5:
     resolution:
       {
-        integrity: sha512-CRyl8cv53LlzAKGdG5NyoUu7LwTL0NjDWqARuYEiQXPKBQPqEYh0MlZtQOTsFwfdTaaxUHZQZDAotRW7DudfxA==,
+        integrity: sha512-Z0+VeKEK6Oh2qAhwCg9kD9tHIoTs9ktqIuG2nV2PZ/vam6ZWCXYkN6yl0AF/75gKqSxfprDAaC8Xaun+8ta8CA==,
       }
 
   micromark-core-commonmark@2.0.1:
@@ -4969,7 +4969,7 @@ snapshots:
 
   merge-stream@2.0.0: {}
 
-  meta-json-schema@1.18.4-beta4: {}
+  meta-json-schema@1.18.4-beta5: {}
 
   micromark-core-commonmark@2.0.1:
     dependencies:

+ 21 - 8
src/components/profile/editor-viewer.tsx

@@ -23,12 +23,13 @@ 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 {
-  uid: string;
+  mode: "profile" | "text";
+  property: string;
   open: boolean;
-  language: "yaml" | "javascript";
+  language: "yaml" | "javascript" | "css";
   schema?: "clash" | "merge";
   onClose: () => void;
-  onChange?: () => void;
+  onChange?: (content?: string) => void;
 }
 
 // yaml worker
@@ -50,7 +51,7 @@ configureMonacoYaml(monaco, {
 });
 
 export const EditorViewer = (props: Props) => {
-  const { uid, open, language, schema, onClose, onChange } = props;
+  const { mode, property, open, language, schema, onClose, onChange } = props;
   const { t } = useTranslation();
   const editorRef = useRef<any>();
   const instanceRef = useRef<editor.IStandaloneCodeEditor | null>(null);
@@ -59,7 +60,14 @@ export const EditorViewer = (props: Props) => {
   useEffect(() => {
     if (!open) return;
 
-    readProfileFile(uid).then((data) => {
+    let fetchContent;
+    switch (mode) {
+      case "profile": // profile文件
+        fetchContent = readProfileFile(property);
+      case "text": // 文本内容
+        fetchContent = Promise.resolve(property);
+    }
+    fetchContent.then((data) => {
       const dom = editorRef.current;
 
       if (!dom) return;
@@ -71,7 +79,7 @@ export const EditorViewer = (props: Props) => {
       instanceRef.current = editor.create(editorRef.current, {
         model: model,
         language: language,
-        tabSize: ["yaml", "javascript"].includes(language) ? 2 : 4, // 根据语言类型设置缩进
+        tabSize: ["yaml", "javascript", "css"].includes(language) ? 2 : 4, // 根据语言类型设置缩进
         theme: themeMode === "light" ? "vs" : "vs-dark",
         minimap: { enabled: dom.clientWidth >= 1000 }, // 超过一定宽度显示minimap滚动条
         mouseWheelZoom: true, // Ctrl+滚轮调节缩放
@@ -80,6 +88,9 @@ export const EditorViewer = (props: Props) => {
           comments: true, // 注释类型的建议
           other: true, // 其他类型的建议
         },
+        padding: {
+          top: 33, // 顶部padding防止遮挡snippets
+        },
       });
     });
 
@@ -97,8 +108,10 @@ export const EditorViewer = (props: Props) => {
     if (value == null) return;
 
     try {
-      await saveProfileFile(uid, value);
-      onChange?.();
+      if (mode === "profile") {
+        await saveProfileFile(property, value);
+      }
+      onChange?.(value);
       onClose();
     } catch (err: any) {
       Notice.error(err.message || err.toString());

+ 3 - 2
src/components/profile/profile-item.tsx

@@ -20,7 +20,7 @@ import { RefreshRounded, DragIndicator } from "@mui/icons-material";
 import { atomLoadingCache } from "@/services/states";
 import { updateProfile, deleteProfile, viewProfile } from "@/services/cmds";
 import { Notice } from "@/components/base";
-import { EditorViewer } from "./editor-viewer";
+import { EditorViewer } from "@/components/profile/editor-viewer";
 import { ProfileBox } from "./profile-box";
 import parseTraffic from "@/utils/parse-traffic";
 import { ConfirmViewer } from "./confirm-viewer";
@@ -384,7 +384,8 @@ export const ProfileItem = (props: Props) => {
       </Menu>
 
       <EditorViewer
-        uid={uid}
+        mode="profile"
+        property={uid}
         open={fileOpen}
         language="yaml"
         schema="clash"

+ 3 - 2
src/components/profile/profile-more.tsx

@@ -14,7 +14,7 @@ import {
 import { FeaturedPlayListRounded } from "@mui/icons-material";
 import { viewProfile } from "@/services/cmds";
 import { Notice } from "@/components/base";
-import { EditorViewer } from "./editor-viewer";
+import { EditorViewer } from "@/components/profile/editor-viewer";
 import { ProfileBox } from "./profile-box";
 import { LogViewer } from "./log-viewer";
 import { ConfirmViewer } from "./confirm-viewer";
@@ -233,7 +233,8 @@ export const ProfileMore = (props: Props) => {
       </Menu>
 
       <EditorViewer
-        uid={uid}
+        mode="profile"
+        property={uid}
         open={fileOpen}
         language={type === "merge" ? "yaml" : "javascript"}
         schema={type === "merge" ? "merge" : undefined}

+ 26 - 7
src/components/setting/mods/theme-viewer.tsx

@@ -1,7 +1,8 @@
-import { forwardRef, useImperativeHandle, useState } from "react";
+import { forwardRef, useImperativeHandle, useRef, useState } from "react";
 import { useLockFn } from "ahooks";
 import { useTranslation } from "react-i18next";
 import {
+  Button,
   List,
   ListItem,
   ListItemText,
@@ -12,11 +13,14 @@ import {
 import { useVerge } from "@/hooks/use-verge";
 import { defaultTheme, defaultDarkTheme } from "@/pages/_theme";
 import { BaseDialog, DialogRef, Notice } from "@/components/base";
+import { EditorViewer } from "@/components/profile/editor-viewer";
+import { Edit, SwitchAccessShortcut } from "@mui/icons-material";
 
 export const ThemeViewer = forwardRef<DialogRef>((props, ref) => {
   const { t } = useTranslation();
 
   const [open, setOpen] = useState(false);
+  const [editorOpen, setEditorOpen] = useState(false);
   const { verge, patchVerge } = useVerge();
   const { theme_setting } = verge ?? {};
   const [theme, setTheme] = useState(theme_setting || {});
@@ -108,14 +112,29 @@ export const ThemeViewer = forwardRef<DialogRef>((props, ref) => {
             onKeyDown={(e) => e.key === "Enter" && onSave()}
           />
         </Item>
-
         <Item>
           <ListItemText primary="CSS Injection" />
-          <TextField
-            {...textProps}
-            value={theme.css_injection ?? ""}
-            onChange={handleChange("css_injection")}
-            onKeyDown={(e) => e.key === "Enter" && onSave()}
+          <Button
+            startIcon={<Edit />}
+            variant="outlined"
+            onClick={() => {
+              setEditorOpen(true);
+            }}
+          >
+            {t("Edit")} CSS
+          </Button>
+          <EditorViewer
+            mode="text"
+            property={theme.css_injection ?? ""}
+            open={editorOpen}
+            language="css"
+            onChange={(content) => {
+              theme.css_injection = content;
+              handleChange("css_injection");
+            }}
+            onClose={() => {
+              setEditorOpen(false);
+            }}
           />
         </Item>
       </List>

+ 1 - 1
vite.config.ts

@@ -12,7 +12,7 @@ export default defineConfig({
     svgr(),
     react(),
     monacoEditor({
-      languageWorkers: ["editorWorkerService", "typescript"],
+      languageWorkers: ["editorWorkerService", "typescript", "css"],
       customWorkers: [
         {
           label: "yaml",