feat: Add bandwidth fields and placeholders for upload and download in server configuration forms; update localization files for multiple languages

This commit is contained in:
web
2025-09-13 02:59:10 -07:00
parent c4a47a47dd
commit 3e5402f2fc
25 changed files with 129 additions and 9 deletions
@@ -25,6 +25,7 @@ export type FieldConfig = {
max?: number;
step?: number;
suffix?: string;
password?: number;
condition?: (protocol: any, values: any) => boolean;
group?: 'basic' | 'transport' | 'security' | 'reality' | 'plugin';
gridSpan?: 1 | 2;
@@ -187,6 +188,8 @@ const hysteria2 = z.object({
sni: nullableString,
allow_insecure: nullableBool,
fingerprint: nullableString,
up_mbps: z.number().nullish(),
down_mbps: z.number().nullish(),
});
const tuic = z.object({
@@ -295,6 +298,8 @@ export function getProtocolDefaultConfig(proto: ProtocolType) {
hop_interval: null,
obfs_password: null,
security: 'tls',
up_mbps: null,
down_mbps: null,
} as any;
case 'tuic':
return {
@@ -371,6 +376,7 @@ export const PROTOCOL_FIELDS: Record<string, FieldConfig[]> = {
name: 'server_key',
type: 'input',
label: 'server_key',
password: 32,
group: 'basic',
condition: (p) =>
[
@@ -677,13 +683,6 @@ export const PROTOCOL_FIELDS: Record<string, FieldConfig[]> = {
placeholder: '1-65535',
group: 'basic',
},
{
name: 'obfs_password',
type: 'input',
label: 'obfs_password',
placeholder: (t) => t('obfs_password_placeholder'),
group: 'basic',
},
{
name: 'hop_ports',
type: 'input',
@@ -695,10 +694,37 @@ export const PROTOCOL_FIELDS: Record<string, FieldConfig[]> = {
name: 'hop_interval',
type: 'number',
label: 'hop_interval',
placeholder: 'e.g. 300',
min: 0,
suffix: 'S',
group: 'basic',
},
{
name: 'obfs_password',
type: 'input',
label: 'obfs_password',
placeholder: (t) => t('obfs_password_placeholder'),
password: 16,
group: 'basic',
},
{
name: 'up_mbps',
type: 'number',
label: 'up_mbps',
min: 0,
placeholder: (t) => t('bandwidth_placeholder'),
suffix: 'Mbps',
group: 'basic',
},
{
name: 'down_mbps',
type: 'number',
label: 'down_mbps',
min: 0,
placeholder: (t) => t('bandwidth_placeholder'),
suffix: 'Mbps',
group: 'basic',
},
{ name: 'sni', type: 'input', label: 'security_sni', group: 'security' },
{ name: 'allow_insecure', type: 'switch', label: 'security_allow_insecure', group: 'security' },
{
@@ -37,6 +37,7 @@ import { Switch } from '@workspace/ui/components/switch';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { Icon } from '@workspace/ui/custom-components/icon';
import { useTranslations } from 'next-intl';
import { uid } from 'radash';
import { useEffect, useState } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { toast } from 'sonner';
@@ -85,6 +86,7 @@ function DynamicField({
<FormControl>
<EnhancedInput
{...fieldProps}
type='text'
placeholder={
field.placeholder
? typeof field.placeholder === 'function'
@@ -93,6 +95,23 @@ function DynamicField({
: undefined
}
onValueChange={(v) => fieldProps.onChange(v)}
suffix={
field.password ? (
<Button
type='button'
variant='ghost'
onClick={() => {
const length = field.password || 16;
const result = uid(length).toLowerCase();
fieldProps.onChange(result);
}}
>
<Icon icon='mdi:refresh' className='h-4 w-4' />
</Button>
) : (
field.suffix
)
}
/>
</FormControl>
<FormMessage />
@@ -116,7 +135,13 @@ function DynamicField({
max={field.max}
step={field.step || 1}
suffix={field.suffix}
placeholder={field.placeholder as string}
placeholder={
field.placeholder
? typeof field.placeholder === 'function'
? field.placeholder(t, protocolData)
: field.placeholder
: undefined
}
onValueChange={(v) => fieldProps.onChange(v)}
/>
</FormControl>
@@ -371,7 +396,7 @@ export default function ServerForm(props: {
{trigger}
</Button>
</SheetTrigger>
<SheetContent className='w-[580px] max-w-full md:max-w-screen-md'>
<SheetContent className='w-[700px] max-w-full md:max-w-screen-md'>
<SheetHeader>
<SheetTitle>{title}</SheetTitle>
</SheetHeader>