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