code formatting with prettier
This commit is contained in:
@@ -28,14 +28,14 @@ export const TestBox = React.forwardRef<HTMLDivElement, TestBoxProps>(
|
||||
"data-[selected=true]:bg-primary/20 data-[selected=true]:text-primary data-[selected=true]:shadow-lg",
|
||||
|
||||
// --- Дополнительные классы от пользователя ---
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
TestBox.displayName = "TestBox";
|
||||
|
||||
@@ -15,7 +15,12 @@ import { cmdTestDelay, downloadIconCache } from "@/services/cmds";
|
||||
import { BaseLoading } from "@/components/base";
|
||||
import { TestBox } from "./test-box"; // Наш рефакторенный компонент
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from "@/components/ui/context-menu";
|
||||
import {
|
||||
ContextMenu,
|
||||
ContextMenuContent,
|
||||
ContextMenuItem,
|
||||
ContextMenuTrigger,
|
||||
} from "@/components/ui/context-menu";
|
||||
import { Languages } from "lucide-react"; // Новая иконка
|
||||
|
||||
// Вспомогательная функция для цвета задержки
|
||||
@@ -35,7 +40,14 @@ interface Props {
|
||||
|
||||
export const TestItem = (props: Props) => {
|
||||
const { itemData, onEdit, onDelete: onDeleteItem } = props;
|
||||
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: props.id });
|
||||
const {
|
||||
attributes,
|
||||
listeners,
|
||||
setNodeRef,
|
||||
transform,
|
||||
transition,
|
||||
isDragging,
|
||||
} = useSortable({ id: props.id });
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [delay, setDelay] = useState(-1);
|
||||
@@ -59,7 +71,9 @@ export const TestItem = (props: Props) => {
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => { initIconCachePath(); }, [icon]);
|
||||
useEffect(() => {
|
||||
initIconCachePath();
|
||||
}, [icon]);
|
||||
|
||||
const onDelete = useLockFn(async () => {
|
||||
try {
|
||||
@@ -81,7 +95,9 @@ export const TestItem = (props: Props) => {
|
||||
unlistenFn = await addListener("verge://test-all", onDelay);
|
||||
};
|
||||
setupListener();
|
||||
return () => { unlistenFn?.(); };
|
||||
return () => {
|
||||
unlistenFn?.();
|
||||
};
|
||||
}, [url, addListener, onDelay]);
|
||||
|
||||
const style = {
|
||||
@@ -96,32 +112,53 @@ export const TestItem = (props: Props) => {
|
||||
<ContextMenuTrigger>
|
||||
<TestBox>
|
||||
{/* Мы применяем `listeners` к иконке, чтобы за нее можно было таскать */}
|
||||
<div {...listeners} className="flex h-12 cursor-move items-center justify-center">
|
||||
<div
|
||||
{...listeners}
|
||||
className="flex h-12 cursor-move items-center justify-center"
|
||||
>
|
||||
{icon ? (
|
||||
<img
|
||||
src={icon.startsWith('data') ? icon : icon.startsWith('<svg') ? `data:image/svg+xml;base64,${btoa(icon)}` : (iconCachePath || icon)}
|
||||
className="h-10"
|
||||
alt={name}
|
||||
/>
|
||||
<img
|
||||
src={
|
||||
icon.startsWith("data")
|
||||
? icon
|
||||
: icon.startsWith("<svg")
|
||||
? `data:image/svg+xml;base64,${btoa(icon)}`
|
||||
: iconCachePath || icon
|
||||
}
|
||||
className="h-10"
|
||||
alt={name}
|
||||
/>
|
||||
) : (
|
||||
<Languages className="h-10 w-10 text-muted-foreground" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<p className="mt-1 text-center text-sm font-semibold truncate" title={name}>{name}</p>
|
||||
<p
|
||||
className="mt-1 text-center text-sm font-semibold truncate"
|
||||
title={name}
|
||||
>
|
||||
{name}
|
||||
</p>
|
||||
|
||||
<Separator className="my-2" />
|
||||
|
||||
<div
|
||||
className="flex h-6 items-center justify-center text-sm font-medium"
|
||||
onClick={(e) => { e.stopPropagation(); onDelay(); }}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onDelay();
|
||||
}}
|
||||
>
|
||||
{delay === -2 ? (
|
||||
<BaseLoading className="h-4 w-4" />
|
||||
) : delay === -1 ? (
|
||||
<span className="cursor-pointer rounded-md px-2 py-0.5 hover:bg-accent">{t("Test")}</span>
|
||||
<span className="cursor-pointer rounded-md px-2 py-0.5 hover:bg-accent">
|
||||
{t("Test")}
|
||||
</span>
|
||||
) : (
|
||||
<span className={`cursor-pointer rounded-md px-2 py-0.5 hover:bg-accent ${getDelayColorClass(delay)}`}>
|
||||
<span
|
||||
className={`cursor-pointer rounded-md px-2 py-0.5 hover:bg-accent ${getDelayColorClass(delay)}`}
|
||||
>
|
||||
{delayManager.formatDelay(delay)} ms
|
||||
</span>
|
||||
)}
|
||||
@@ -131,7 +168,11 @@ export const TestItem = (props: Props) => {
|
||||
|
||||
<ContextMenuContent>
|
||||
{menu.map((item) => (
|
||||
<ContextMenuItem key={item.label} onClick={item.handler} className={item.isDestructive ? "text-destructive" : ""}>
|
||||
<ContextMenuItem
|
||||
key={item.label}
|
||||
onClick={item.handler}
|
||||
className={item.isDestructive ? "text-destructive" : ""}
|
||||
>
|
||||
{t(item.label)}
|
||||
</ContextMenuItem>
|
||||
))}
|
||||
|
||||
@@ -51,7 +51,9 @@ export const TestViewer = forwardRef<TestViewerRef, Props>((props, ref) => {
|
||||
const { control, handleSubmit, reset, setValue } = form;
|
||||
|
||||
const patchTestList = async (uid: string, patch: Partial<IVergeTestItem>) => {
|
||||
const newList = testList.map((x) => (x.uid === uid ? { ...x, ...patch } : x));
|
||||
const newList = testList.map((x) =>
|
||||
x.uid === uid ? { ...x, ...patch } : x,
|
||||
);
|
||||
await patchVerge({ test_list: newList });
|
||||
};
|
||||
|
||||
@@ -81,7 +83,10 @@ export const TestViewer = forwardRef<TestViewerRef, Props>((props, ref) => {
|
||||
formData.icon = formData.icon.replace(/<!--[\s\S]*?-->/g, "");
|
||||
// --- КОНЕЦ ИСПРАВЛЕНИЯ ---
|
||||
|
||||
const doc = new DOMParser().parseFromString(formData.icon, "image/svg+xml");
|
||||
const doc = new DOMParser().parseFromString(
|
||||
formData.icon,
|
||||
"image/svg+xml",
|
||||
);
|
||||
if (doc.querySelector("parsererror")) {
|
||||
throw new Error("`Icon`svg format error");
|
||||
}
|
||||
@@ -112,7 +117,9 @@ export const TestViewer = forwardRef<TestViewerRef, Props>((props, ref) => {
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{openType === "new" ? t("Create Test") : t("Edit Test")}</DialogTitle>
|
||||
<DialogTitle>
|
||||
{openType === "new" ? t("Create Test") : t("Edit Test")}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<Form {...form}>
|
||||
@@ -124,7 +131,9 @@ export const TestViewer = forwardRef<TestViewerRef, Props>((props, ref) => {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("Name")}</FormLabel>
|
||||
<FormControl><Input {...field} /></FormControl>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
@@ -135,7 +144,13 @@ export const TestViewer = forwardRef<TestViewerRef, Props>((props, ref) => {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("Icon")}</FormLabel>
|
||||
<FormControl><Textarea {...field} rows={4} placeholder="<svg>...</svg> or http(s)://..." /></FormControl>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
{...field}
|
||||
rows={4}
|
||||
placeholder="<svg>...</svg> or http(s)://..."
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
@@ -147,7 +162,13 @@ export const TestViewer = forwardRef<TestViewerRef, Props>((props, ref) => {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("Test URL")}</FormLabel>
|
||||
<FormControl><Textarea {...field} rows={3} placeholder="https://www.google.com" /></FormControl>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
{...field}
|
||||
rows={3}
|
||||
placeholder="https://www.google.com"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
@@ -157,11 +178,15 @@ export const TestViewer = forwardRef<TestViewerRef, Props>((props, ref) => {
|
||||
</Form>
|
||||
|
||||
<DialogFooter>
|
||||
<DialogClose asChild><Button type="button" variant="outline">{t("Cancel")}</Button></DialogClose>
|
||||
<Button type="button" onClick={handleOk} disabled={loading}>
|
||||
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||
{t("Save")}
|
||||
<DialogClose asChild>
|
||||
<Button type="button" variant="outline">
|
||||
{t("Cancel")}
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<Button type="button" onClick={handleOk} disabled={loading}>
|
||||
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||
{t("Save")}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
Reference in New Issue
Block a user