💄 feat: Optimize UI components and input logic
This commit is contained in:
parent
236bf0ac1f
commit
2220e33a1e
5 changed files with 56 additions and 22 deletions
|
|
@ -30,11 +30,11 @@ export default function ProxyPing({ accountId }: { accountId: string }) {
|
|||
>
|
||||
<ChevronsLeftRightEllipsis className="h-4 w-4 text-gray-500" />
|
||||
{isLoading && (
|
||||
<div className="h-6 w-24 animate-pulse rounded bg-gray-200"></div>
|
||||
<div className="h-6 w-16 animate-pulse rounded bg-gray-200"></div>
|
||||
)}
|
||||
{!isLoading && error && <span>Connection error</span>}
|
||||
{!isLoading && data && (
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="flex h-6 items-center space-x-2">
|
||||
<span className="text-sm">{(data.ping * 1000).toFixed(0)} ms</span>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import useSWRMutation from "swr/mutation";
|
|||
import { request } from "@/lib/api";
|
||||
import { toast } from "@/hooks/use-toast";
|
||||
import ProxyPing from "@/components/proxy-ping";
|
||||
import { Label } from "./ui/label";
|
||||
|
||||
export interface ProxysProps {
|
||||
enableSelect?: boolean;
|
||||
|
|
@ -231,34 +232,46 @@ export default function Proxys({
|
|||
<div className="space-y-4">
|
||||
{/* Radio buttons for proxy type */}
|
||||
<div>
|
||||
<label className="mb-1 block text-lg text-gray-700">Type</label>
|
||||
<Label className="mb-2 block">Type</Label>
|
||||
<div className="flex space-x-4">
|
||||
<label className="flex items-center space-x-2">
|
||||
<label className="flex cursor-pointer items-center">
|
||||
<input
|
||||
type="radio"
|
||||
name="type"
|
||||
value="http"
|
||||
checked={formState.type === "http"}
|
||||
onChange={handleInputChange}
|
||||
className="peer hidden"
|
||||
/>
|
||||
<span>HTTP</span>
|
||||
<div className="mr-2 flex h-5 w-5 items-center justify-center rounded-full border-2 border-gray-300 peer-checked:border-primary peer-checked:bg-primary">
|
||||
<div className="h-2.5 w-2.5 rounded-full bg-white"></div>
|
||||
</div>
|
||||
<span className="text-gray-700 peer-checked:text-primary">
|
||||
HTTP
|
||||
</span>
|
||||
</label>
|
||||
<label className="flex items-center space-x-2">
|
||||
|
||||
<label className="flex cursor-pointer items-center">
|
||||
<input
|
||||
type="radio"
|
||||
name="type"
|
||||
value="socks5"
|
||||
checked={formState.type === "socks5"}
|
||||
onChange={handleInputChange}
|
||||
className="peer hidden"
|
||||
/>
|
||||
<span>SOCKS5</span>
|
||||
<div className="mr-2 flex h-5 w-5 items-center justify-center rounded-full border-2 border-gray-300 peer-checked:border-primary peer-checked:bg-primary">
|
||||
<div className="h-2.5 w-2.5 rounded-full bg-white"></div>
|
||||
</div>
|
||||
<span className="text-gray-400 peer-checked:text-primary">
|
||||
SOCKS5
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Other input fields */}
|
||||
<div>
|
||||
<label className="mb-1 block text-lg text-gray-700">Name</label>
|
||||
<Label className="mb-2 block">Name</Label>
|
||||
<Input
|
||||
name="name"
|
||||
value={formState.name}
|
||||
|
|
@ -267,12 +280,12 @@ export default function Proxys({
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="mb-1 text-lg text-gray-700">
|
||||
<Label className="mb-2 block">
|
||||
Proxy server address and port number
|
||||
</p>
|
||||
</Label>
|
||||
<div className="flex space-x-4">
|
||||
<div className="flex-1">
|
||||
<label className="block text-sm font-medium text-gray-500">
|
||||
<label className="block text-xs font-medium text-gray-500">
|
||||
Server
|
||||
</label>
|
||||
<Input
|
||||
|
|
@ -283,7 +296,7 @@ export default function Proxys({
|
|||
/>
|
||||
</div>
|
||||
<div className="w-24">
|
||||
<label className="block text-sm font-medium text-gray-500">
|
||||
<label className="block text-xs font-medium text-gray-500">
|
||||
Port
|
||||
</label>
|
||||
<Input
|
||||
|
|
@ -296,11 +309,9 @@ export default function Proxys({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p className="mb-1 text-lg text-gray-700">
|
||||
Authentication (optional)
|
||||
</p>
|
||||
<Label className="mb-2 block">Authentication (optional)</Label>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-500">
|
||||
<label className="block text-xs font-medium text-gray-500">
|
||||
Username
|
||||
</label>
|
||||
<Input
|
||||
|
|
@ -311,7 +322,7 @@ export default function Proxys({
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-500">
|
||||
<label className="block text-xs font-medium text-gray-500">
|
||||
Password
|
||||
</label>
|
||||
<Input
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Bell } from "lucide-react";
|
||||
import {Bell, Copy} from "lucide-react";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import {
|
||||
|
|
@ -12,9 +12,13 @@ import { Input } from "@/components/ui/input";
|
|||
import { Button } from "@/components/ui/button";
|
||||
import React, { type FormEvent } from "react";
|
||||
import { useSettings } from "@/hooks/use-settings";
|
||||
import { useTelegramAccount } from "@/hooks/use-telegram-account";
|
||||
import {useCopyToClipboard} from "@/hooks/use-copy-to-clipboard";
|
||||
|
||||
export default function SettingsForm() {
|
||||
const { settings, setSetting, updateSettings } = useSettings();
|
||||
const { account } = useTelegramAccount();
|
||||
const [, copyToClipboard] = useCopyToClipboard();
|
||||
|
||||
const imageLoadSizeOptions = [
|
||||
{ value: "s", label: "box 100x100" },
|
||||
|
|
@ -34,7 +38,7 @@ export default function SettingsForm() {
|
|||
{ value: "600", label: "10 minutes" },
|
||||
{ value: "900", label: "15 minutes" },
|
||||
{ value: "1800", label: "30 minutes" },
|
||||
]
|
||||
];
|
||||
|
||||
const handleSave = async (e: FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
|
@ -51,6 +55,24 @@ export default function SettingsForm() {
|
|||
<Bell className="mr-2 inline-block h-4 w-4" />
|
||||
These settings will be applied to all accounts.
|
||||
</p>
|
||||
<div className="w-full rounded-md border p-4 shadow">
|
||||
<p className="mb-1 text-xs text-muted-foreground">Your root path</p>
|
||||
<div className="flex items-center justify-between space-x-1">
|
||||
<p className="bg-gray-50 rounded-md p-2 text-xs text-muted-foreground">
|
||||
{account?.rootPath}
|
||||
</p>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
void copyToClipboard(account?.rootPath ?? "");
|
||||
}}
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-full flex-col space-y-4 rounded-md border p-4 shadow">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Label htmlFor="unique-only">Unique Only</Label>
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@ export function Toaster() {
|
|||
{toasts.map(function ({ id, title, description, action, ...props }) {
|
||||
return (
|
||||
<Toast key={id} {...props}>
|
||||
<div className="grid gap-1">
|
||||
<div className="grid gap-1" onClick={(e) => e.stopPropagation()}>
|
||||
{title && <ToastTitle>{title}</ToastTitle>}
|
||||
{description && (
|
||||
<ToastDescription>{description}</ToastDescription>
|
||||
)}
|
||||
</div>
|
||||
{action}
|
||||
<ToastClose />
|
||||
<ToastClose onClick={(e) => e.stopPropagation()} />
|
||||
</Toast>
|
||||
);
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export type TelegramAccount = {
|
|||
status: "active" | "inactive";
|
||||
lastAuthorizationState?: TelegramObject;
|
||||
proxy?: string;
|
||||
rootPath: string;
|
||||
};
|
||||
|
||||
export type TelegramChat = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue