From 28c12102c299ba2fa6022c334cc110de2683149d Mon Sep 17 00:00:00 2001 From: ReaJason Date: Tue, 16 Dec 2025 21:33:19 +0800 Subject: [PATCH] refactor: migrate radix-ui to base-ui --- web/app/components/magicui/rainbow-button.tsx | 59 -- .../components/memshell/main-config-card.tsx | 647 ++++++++------- .../memshell/package-config-card.tsx | 117 ++- web/app/components/memshell/quick-usage.tsx | 4 +- .../memshell/results/multi-packer.tsx | 4 +- .../components/memshell/tabs/antsword-tab.tsx | 109 ++- .../components/memshell/tabs/behinder-tab.tsx | 102 ++- .../memshell/tabs/classname-field.tsx | 79 +- .../components/memshell/tabs/command-tab.tsx | 257 +++--- .../components/memshell/tabs/custom-tab.tsx | 145 ++-- .../components/memshell/tabs/godzilla-tab.tsx | 149 ++-- .../components/memshell/tabs/neoreg-tab.tsx | 88 +- .../memshell/tabs/shelltype-field.tsx | 77 +- web/app/components/memshell/tabs/suo5-tab.tsx | 88 +- .../memshell/tabs/urlpattern-field.tsx | 40 +- .../probeshell/main-config-card.tsx | 778 +++++++++--------- .../probeshell/package-config-card.tsx | 70 +- web/app/components/ui/alert-dialog.tsx | 100 ++- web/app/components/ui/alert.tsx | 20 +- web/app/components/ui/avatar.tsx | 78 +- web/app/components/ui/badge.tsx | 48 +- web/app/components/ui/breadcrumb.tsx | 108 --- web/app/components/ui/button.tsx | 45 +- web/app/components/ui/card.tsx | 23 +- web/app/components/ui/checkbox.tsx | 30 - web/app/components/ui/collapsible.tsx | 18 +- web/app/components/ui/context-menu.tsx | 250 ------ web/app/components/ui/dialog.tsx | 141 ---- web/app/components/ui/dropdown-menu.tsx | 255 ------ web/app/components/ui/field.tsx | 245 ++++++ web/app/components/ui/form.tsx | 199 ----- web/app/components/ui/input.tsx | 7 +- web/app/components/ui/label.tsx | 11 +- web/app/components/ui/navigation-menu.tsx | 168 ---- web/app/components/ui/popover.tsx | 46 -- web/app/components/ui/radio-group.tsx | 33 +- web/app/components/ui/scroll-area.tsx | 56 -- web/app/components/ui/select.tsx | 143 ++-- web/app/components/ui/separator.tsx | 11 +- web/app/components/ui/skeleton.tsx | 13 + web/app/components/ui/sonner.tsx | 22 +- web/app/components/ui/spinner.tsx | 15 + web/app/components/ui/switch.tsx | 15 +- web/app/components/ui/table.tsx | 114 --- web/app/components/ui/tabs.tsx | 60 +- web/app/components/ui/textarea.tsx | 2 +- web/app/components/ui/tooltip.tsx | 55 +- web/app/routes/about.tsx | 2 +- web/app/routes/memshell.tsx | 67 +- web/app/routes/probeshell.tsx | 57 +- web/app/types/schema.ts | 4 +- web/biome.json | 2 +- web/bun.lock | 96 +-- web/components.json | 10 +- web/package.json | 4 +- 55 files changed, 2117 insertions(+), 3269 deletions(-) delete mode 100644 web/app/components/magicui/rainbow-button.tsx delete mode 100644 web/app/components/ui/breadcrumb.tsx delete mode 100644 web/app/components/ui/checkbox.tsx delete mode 100644 web/app/components/ui/context-menu.tsx delete mode 100644 web/app/components/ui/dialog.tsx delete mode 100644 web/app/components/ui/dropdown-menu.tsx create mode 100644 web/app/components/ui/field.tsx delete mode 100644 web/app/components/ui/form.tsx delete mode 100644 web/app/components/ui/navigation-menu.tsx delete mode 100644 web/app/components/ui/popover.tsx delete mode 100644 web/app/components/ui/scroll-area.tsx create mode 100644 web/app/components/ui/skeleton.tsx create mode 100644 web/app/components/ui/spinner.tsx delete mode 100644 web/app/components/ui/table.tsx diff --git a/web/app/components/magicui/rainbow-button.tsx b/web/app/components/magicui/rainbow-button.tsx deleted file mode 100644 index 57bb689e..00000000 --- a/web/app/components/magicui/rainbow-button.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; -import React from "react"; -import { cn } from "@/lib/utils"; - -const rainbowButtonVariants = cva( - cn( - "relative cursor-pointer group transition-all animate-rainbow", - "inline-flex items-center justify-center gap-2 shrink-0", - "rounded-sm outline-none focus-visible:ring-[3px] aria-invalid:border-destructive", - "text-sm font-medium whitespace-nowrap", - "disabled:pointer-events-none disabled:opacity-50", - "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0", - ), - { - variants: { - variant: { - default: - "border-0 bg-[linear-gradient(#121213,#121213),linear-gradient(#121213_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))] bg-[length:200%] text-primary-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.125rem)_solid_transparent] before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))] before:[filter:blur(0.75rem)] dark:bg-[linear-gradient(#fff,#fff),linear-gradient(#fff_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))]", - outline: - "border border-input border-b-transparent bg-[linear-gradient(#ffffff,#ffffff),linear-gradient(#ffffff_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))] bg-[length:200%] text-accent-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))] before:[filter:blur(0.75rem)] dark:bg-[linear-gradient(#0a0a0a,#0a0a0a),linear-gradient(#0a0a0a_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-1),var(--color-5),var(--color-3),var(--color-4),var(--color-2))]", - }, - size: { - default: "h-9 px-4 py-2", - sm: "h-8 rounded-xl px-3 text-xs", - lg: "h-11 rounded-xl px-8", - icon: "size-9", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - }, -); - -interface RainbowButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean; -} - -const RainbowButton = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button"; - return ( - - ); - }, -); - -RainbowButton.displayName = "RainbowButton"; - -export { RainbowButton, rainbowButtonVariants, type RainbowButtonProps }; diff --git a/web/app/components/memshell/main-config-card.tsx b/web/app/components/memshell/main-config-card.tsx index 038bdcc2..fbeda2d0 100644 --- a/web/app/components/memshell/main-config-card.tsx +++ b/web/app/components/memshell/main-config-card.tsx @@ -10,8 +10,8 @@ import { WaypointsIcon, ZapIcon, } from "lucide-react"; -import { type JSX, useCallback, useEffect, useState } from "react"; -import { FormProvider, type UseFormReturn } from "react-hook-form"; +import { type JSX, useCallback, useRef, useState } from "react"; +import { Controller, type UseFormReturn, useWatch } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { AntSwordTabContent } from "@/components/memshell/tabs/antsword-tab"; import { BehinderTabContent } from "@/components/memshell/tabs/behinder-tab"; @@ -22,15 +22,12 @@ import { NeoRegTabContent } from "@/components/memshell/tabs/neoreg-tab"; import { Suo5TabContent } from "@/components/memshell/tabs/suo5-tab"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { - FormControl, - FormDescription, - FormField, - FormFieldItem, - FormFieldLabel, - FormItem, - FormLabel, - FormMessage, -} from "@/components/ui/form"; + Field, + FieldContent, + FieldDescription, + FieldError, + FieldLabel, +} from "@/components/ui/field"; import { Label } from "@/components/ui/label"; import { Select, @@ -52,6 +49,7 @@ import { ShellToolType, } from "@/types/memshell"; import type { MemShellFormSchema } from "@/types/schema"; +import { Spinner } from "../ui/spinner"; const shellToolIcons: Record = { [ShellToolType.Behinder]: , @@ -67,7 +65,7 @@ const shellToolIcons: Record = { const defaultServerVersionOptions = [ { name: "Unknown", - value: "unknown", + value: "Unknown", }, ]; @@ -80,32 +78,21 @@ export default function MainConfigCard({ form: UseFormReturn; servers?: ServerConfig; }>) { + const { t } = useTranslation(["common", "memshell"]); + const [shellToolMap, setShellToolMap] = useState<{ [toolName: string]: string[]; }>(); - const [shellTools, setShellTools] = useState([ - ShellToolType.Godzilla, - ShellToolType.Behinder, - ShellToolType.AntSword, - ShellToolType.Command, - ShellToolType.Suo5, - ShellToolType.NeoreGeorg, - ShellToolType.Custom, - ]); + const [shellTools, setShellTools] = useState([]); const [shellTypes, setShellTypes] = useState([]); - const shellTool = form.watch("shellTool"); - const { t } = useTranslation(["common", "memshell"]); - const [serverVersionOptions, setServerVersionOptions] = useState( defaultServerVersionOptions, ); - // 处理一下 shellTypes 由于 server 或 shellTool 变更时无法正常为 form.shellType 赋值的问题 - useEffect(() => { - if (shellTypes.length > 0) { - form.setValue("shellType", shellTypes[0]); - } - }, [shellTypes, form]); + const shellTool = useWatch({ + control: form.control, + name: "shellTool", + }); const handleServerChange = useCallback( (value: string) => { @@ -132,7 +119,10 @@ export default function MainConfigCard({ } setShellTypes(currentShellTypes); - // 特殊环境的 JDK 版本 + if (currentShellTypes && currentShellTypes.length > 0) { + form.setValue("shellType", currentShellTypes[0]); + } + if ( (value === "SpringWebFlux" || value === "XXLJOB") && Number.parseInt(form.getValues("targetJdkVersion") as string, 10) < 52 @@ -142,7 +132,6 @@ export default function MainConfigCard({ form.setValue("targetJdkVersion", "50"); } - // 特殊的服务需要指定版本 if (value === "TongWeb") { setServerVersionOptions([ ...defaultServerVersionOptions, @@ -169,16 +158,6 @@ export default function MainConfigCard({ [form, mainConfig], ); - // 处理一下默认值 server 不刷新 shellType 的问题 - useEffect(() => { - if (mainConfig) { - const initialServer = form.getValues("server"); - if (initialServer && mainConfig[initialServer]) { - handleServerChange(initialServer); - } - } - }, [mainConfig, form, handleServerChange]); - const handleShellToolChange = useCallback( (value: string) => { const resetCommand = () => { @@ -229,6 +208,11 @@ export default function MainConfigCard({ } setShellTypes(currentShellTypes); + // 直接设置 shellType 而不是依赖 useEffect + if (currentShellTypes && currentShellTypes.length > 0) { + form.setValue("shellType", currentShellTypes[0]); + } + form.resetField("urlPattern"); form.resetField("shellClassName"); form.resetField("injectorClassName"); @@ -253,8 +237,17 @@ export default function MainConfigCard({ [form, servers, shellToolMap], ); + const initializedRef = useRef(false); + if (!initializedRef.current && mainConfig) { + const initialServer = form.getValues("server"); + if (initialServer && mainConfig[initialServer]) { + handleServerChange(initialServer); + initializedRef.current = true; + } + } + return ( - + <> @@ -263,284 +256,300 @@ export default function MainConfigCard({ -
- ( - - {t("common:server")} - - - {t("memshell:tips.targetServerNotFound")}  - + + + {t("loading")} + +
+ ) : ( +
+ -
- ( - - {t("common:shellTool")} - - - )} - /> -
-
- ( - - - - -
- {t("common:debug")} - - - - - -

{t("common:debug.description")}

-
-
-
-
- )} - /> - ( - - - - -
- - - - - - -

{t("common:probe.description")}

-
-
-
-
- )} - /> - ( - - - - -
- - - - - - -

{t("common:byPassJavaModule.description")}

-
-
-
-
- )} - /> - ( - - - - -
- - - - - - -

{t("common:lambdaSuffix.description")}

-
-
-
-
- )} - /> - ( - - - - -
- - - - - - -

{t("common:shrink.description")}

-
-
-
-
- )} - /> - ( - - - - -
- - - - - - -

{t("common:staticInitialize.description")}

-
-
-
-
- )} - /> -
+ + + {t("common:serverVersion")} + + + {fieldState.error && ( + + )} + + + )} + /> +
+
+ ( + + + + {t("common:shellTool")} + + + + + )} + /> +
+
+ ( +
+ + + + + + + +

{t("common:debug.description")}

+
+
+
+ )} + /> + ( +
+ + + + + + + +

{t("common:probe.description")}

+
+
+
+ )} + /> + ( +
+ + + + + + + +

{t("common:byPassJavaModule.description")}

+
+
+
+ )} + /> + ( +
+ + + + + + + +

{t("common:lambdaSuffix.description")}

+
+
+
+ )} + /> + ( +
+ + + + + + + +

{t("common:shrink.description")}

+
+
+
+ )} + /> + ( +
+ + + + + + + +

{t("common:staticInitialize.description")}

+
+
+
+ )} + /> +
+ + )}
- - - - - - - - - - -
+ {mainConfig && ( + + + + + + + + + + + )} + ); } diff --git a/web/app/components/memshell/package-config-card.tsx b/web/app/components/memshell/package-config-card.tsx index 61cc5a37..43b0ee90 100644 --- a/web/app/components/memshell/package-config-card.tsx +++ b/web/app/components/memshell/package-config-card.tsx @@ -1,23 +1,14 @@ import { PackageIcon } from "lucide-react"; -import { useEffect, useState } from "react"; -import { FormProvider, type UseFormReturn } from "react-hook-form"; +import { useMemo } from "react"; +import { Controller, type UseFormReturn, useWatch } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { - FormControl, - FormField, - FormItem, - FormLabel, -} from "@/components/ui/form"; +import { FieldLabel, FieldSet } from "@/components/ui/field"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import { Spinner } from "@/components/ui/spinner"; import type { PackerConfig } from "@/types/memshell"; import type { MemShellFormSchema } from "@/types/schema"; -type Option = { - name: string; - value: string; -}; - export default function PackageConfigCard({ packerConfig, form, @@ -25,13 +16,19 @@ export default function PackageConfigCard({ packerConfig: PackerConfig | undefined; form: UseFormReturn; }>) { - const [options, setOptions] = useState>([]); - - const shellType = form.watch("shellType"); - const server = form.watch("server"); const { t } = useTranslation("common"); - useEffect(() => { + const shellType = useWatch({ + control: form.control, + name: "shellType", + }); + + const server = useWatch({ + control: form.control, + name: "server", + }); + + const options = useMemo(() => { const filteredOptions = (packerConfig ?? []).filter((name) => { if (!shellType || shellType === " ") { return true; @@ -44,23 +41,12 @@ export default function PackageConfigCard({ } return !name.startsWith("Agent") && !name.toLowerCase().startsWith("xxl"); }); - - const mappedOptions = filteredOptions.map((name) => { - return { - name: t(name), - value: name, - }; - }); - - setOptions(mappedOptions); - const currentValue = form.getValues("packingMethod"); - if ( - filteredOptions.length > 0 && - (!currentValue || !filteredOptions.includes(currentValue)) - ) { - form.setValue("packingMethod", filteredOptions[0]); - } - }, [form, packerConfig, server, shellType, t]); + form.setValue("packingMethod", filteredOptions[0]); + return filteredOptions.map((name) => ({ + name: t(name), + value: name, + })); + }, [packerConfig, shellType, server, t, form]); return ( @@ -72,41 +58,34 @@ export default function PackageConfigCard({ {options.length > 0 ? ( - - ( - - {t("packerMethod")} - - - {options.map(({ name, value }) => ( - - - - - - {name} - - - ))} - - - - )} - /> - + ( +
+ {t("packerMethod")} + + {options.map(({ name, value }) => ( +
+ + + {name} + +
+ ))} +
+
+ )} + /> ) : ( -
-
+
+ {t("loading")} diff --git a/web/app/components/memshell/quick-usage.tsx b/web/app/components/memshell/quick-usage.tsx index 8d050e75..72b1cd00 100644 --- a/web/app/components/memshell/quick-usage.tsx +++ b/web/app/components/memshell/quick-usage.tsx @@ -7,13 +7,13 @@ export function QuickUsage() { return ( - + {t("common:quickUsage.title")} -
    +
    1. {t("memshell:quickUsage.step1")}
    2. {t("memshell:quickUsage.step2")}
    3. {t("memshell:quickUsage.step3")}
    4. diff --git a/web/app/components/memshell/results/multi-packer.tsx b/web/app/components/memshell/results/multi-packer.tsx index fdcc2bfb..8dbb2091 100644 --- a/web/app/components/memshell/results/multi-packer.tsx +++ b/web/app/components/memshell/results/multi-packer.tsx @@ -79,7 +79,7 @@ export function MultiPackResult({
      + + )} + /> +
      + ( - - - {t("shellToolConfig.antSword.pass")} {t("common:optional")} - + + {t("common:headerName")} - + )} /> -
      - ( - - {t("common:headerName")} - - - - - )} - /> - ( - - - {t("common:headerValue")} {t("common:optional")} - - - - )} - /> -
      - - - - - + ( + + + {t("common:headerValue")} {t("common:optional")} + + + + )} + /> +
      + + + + ); } diff --git a/web/app/components/memshell/tabs/behinder-tab.tsx b/web/app/components/memshell/tabs/behinder-tab.tsx index cad5a954..bb662ad1 100644 --- a/web/app/components/memshell/tabs/behinder-tab.tsx +++ b/web/app/components/memshell/tabs/behinder-tab.tsx @@ -1,7 +1,7 @@ -import { FormProvider, type UseFormReturn } from "react-hook-form"; +import { Controller, type UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { Card, CardContent } from "@/components/ui/card"; -import { FormField, FormFieldItem, FormFieldLabel } from "@/components/ui/form"; +import { Field, FieldLabel } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { TabsContent } from "@/components/ui/tabs"; import type { MemShellFormSchema } from "@/types/schema"; @@ -18,63 +18,61 @@ export function BehinderTabContent({ }>) { const { t } = useTranslation(["memshell", "common"]); return ( - - - - -
      - - -
      - + + +
      + + +
      + ( + + + {t("shellToolConfig.behinder.pass")} {t("common:optional")} + + + + )} + /> +
      + ( - - - {t("shellToolConfig.behinder.pass")} {t("common:optional")} - + + {t("common:headerName")} - + )} /> -
      - ( - - {t("common:headerName")} - - - )} - /> - ( - - - {t("common:headerValue")} {t("common:optional")} - - - - )} - /> -
      - - - - - + ( + + + {t("common:headerValue")} {t("common:optional")} + + + + )} + /> +
      + +
      +
      +
      ); } diff --git a/web/app/components/memshell/tabs/classname-field.tsx b/web/app/components/memshell/tabs/classname-field.tsx index b2b18877..834cc06e 100644 --- a/web/app/components/memshell/tabs/classname-field.tsx +++ b/web/app/components/memshell/tabs/classname-field.tsx @@ -1,8 +1,8 @@ import { Shuffle } from "lucide-react"; import { Fragment, useEffect, useState } from "react"; -import { FormProvider, type UseFormReturn } from "react-hook-form"; +import { Controller, type UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; -import { FormField, FormFieldItem, FormFieldLabel } from "@/components/ui/form"; +import { Field, FieldLabel } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { Switch } from "@/components/ui/switch"; import type { MemShellFormSchema } from "@/types/schema"; @@ -72,44 +72,43 @@ export function OptionalClassFormField({ onCheckedChange={handleToggleRandomClass} />
      - - {!useRandomClassName && ( - ( - - - {t("mainConfig.shellClassName")} {t("common:optional")} - - - - )} - /> - )} - {!useRandomClassName && ( - ( - - - {t("mainConfig.injectorClassName")} {t("common:optional")} - - - - )} - /> - )} - + + {!useRandomClassName && ( + ( + + + {t("mainConfig.shellClassName")} {t("common:optional")} + + + + )} + /> + )} + {!useRandomClassName && ( + ( + + + {t("mainConfig.injectorClassName")} {t("common:optional")} + + + + )} + /> + )} ); } diff --git a/web/app/components/memshell/tabs/command-tab.tsx b/web/app/components/memshell/tabs/command-tab.tsx index caf92d4e..bff17206 100644 --- a/web/app/components/memshell/tabs/command-tab.tsx +++ b/web/app/components/memshell/tabs/command-tab.tsx @@ -1,7 +1,7 @@ import { useQuery } from "@tanstack/react-query"; import { ChevronDown, ChevronRight, InfoIcon } from "lucide-react"; import { useState } from "react"; -import { FormProvider, type UseFormReturn } from "react-hook-form"; +import { Controller, type UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { Card, CardContent } from "@/components/ui/card"; import { @@ -9,12 +9,7 @@ import { CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; -import { - FormControl, - FormField, - FormFieldItem, - FormFieldLabel, -} from "@/components/ui/form"; +import { Field, FieldLabel } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { Select, @@ -56,141 +51,129 @@ export function CommandTabContent({ }); return ( - - - - -
      - - -
      - ( - -
      - - {t("common:paramName")} {t("common:optional")} - - - - - - -

      {t("common:paramName.description")}

      -
      -
      -
      - - - -
      - )} - /> - - - - {isAdvancedOpen ? ( - - ) : ( - - )} - {t("common:advancedConfig")} - - -
      - ( - - {t("common:encryptor")} - - - )} - /> - ( - - - {t("common:implementationClass")} - - - - )} - /> + + + +
      + + +
      + ( + +
      + + {t("common:paramName")} {t("common:optional")} + + + + + + +

      {t("common:paramName.description")}

      +
      +
      - +
      + )} + /> + + + + {isAdvancedOpen ? ( + + ) : ( + + )} + {t("common:advancedConfig")} + + +
      + ( - - - {t("common:commandTemplate")} {t("common:optional")} - - - - -

      - {t("common:commandTemplate.description")} -

      -
      + + {t("common:encryptor")} + + )} /> - - + ( + + {t("common:implementationClass")} + + + )} + /> +
      + ( + + + {t("common:commandTemplate")} {t("common:optional")} + + +

      + {t("common:commandTemplate.description")} +

      +
      + )} + /> +
      +
      - -
      -
      -
      - + + + + ); } diff --git a/web/app/components/memshell/tabs/custom-tab.tsx b/web/app/components/memshell/tabs/custom-tab.tsx index 756e4c14..21fe7f14 100644 --- a/web/app/components/memshell/tabs/custom-tab.tsx +++ b/web/app/components/memshell/tabs/custom-tab.tsx @@ -1,15 +1,9 @@ import { useEffect, useRef, useState } from "react"; -import { FormProvider, type UseFormReturn } from "react-hook-form"; +import { Controller, type UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; import { Card, CardContent } from "@/components/ui/card"; -import { - FormControl, - FormField, - FormFieldItem, - FormFieldLabel, - FormMessage, -} from "@/components/ui/form"; +import { Field, FieldError, FieldLabel } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; @@ -90,74 +84,71 @@ export default function CustomTabContent({ }, [classNameEndpoint, form, shellClassBase64, t]); return ( - - - - -
      - - -
      - ( - - {t("shellClass")} - { - field.onChange(""); - setIsFile(value === "file"); - }} - className="flex items-center space-x-2" - > -
      - - -
      -
      - - -
      -
      - - {isFile ? ( - { - const file = e.target.files?.[0]; - if (file) { - const reader = new FileReader(); - reader.onload = (event) => { - const base64String = - (event.target?.result as string)?.split( - ",", - )[1] || ""; - field.onChange(base64String); - }; - reader.readAsDataURL(file); - } - }} - accept=".class" - placeholder={t("common:placeholders.input")} - type="file" - /> - ) : ( -