✨ 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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user