159 lines
4.4 KiB
TypeScript
159 lines
4.4 KiB
TypeScript
import { Modal, ModalContent, ModalHeader } from '@heroui/modal';
|
||
import toast from 'react-hot-toast';
|
||
|
||
import useConfig from '@/hooks/use-config';
|
||
import useDialog from '@/hooks/use-dialog';
|
||
|
||
import HTTPClientForm from './http_client';
|
||
import HTTPServerForm from './http_server';
|
||
import HTTPServerSSEForm from './http_sse';
|
||
import WebsocketClientForm from './ws_client';
|
||
import WebsocketServerForm from './ws_server';
|
||
|
||
const modalTitle = {
|
||
httpServers: 'HTTP Server',
|
||
httpClients: 'HTTP Client',
|
||
httpSseServers: 'HTTP SSE Server',
|
||
websocketServers: 'Websocket Server',
|
||
websocketClients: 'Websocket Client',
|
||
};
|
||
|
||
export interface NetworkFormModalProps<
|
||
T extends keyof OneBotConfig['network']
|
||
> {
|
||
isOpen: boolean;
|
||
field: T;
|
||
data?: OneBotConfig['network'][T][0];
|
||
onOpenChange: (isOpen: boolean) => void;
|
||
}
|
||
|
||
const NetworkFormModal = <T extends keyof OneBotConfig['network']> (
|
||
props: NetworkFormModalProps<T>
|
||
) => {
|
||
const { isOpen, onOpenChange, field, data } = props;
|
||
const { createNetworkConfig, updateNetworkConfig } = useConfig();
|
||
const dialog = useDialog();
|
||
const isCreate = !data;
|
||
|
||
const onSubmit = async (data: OneBotConfig['network'][typeof field][0]) => {
|
||
const saveData = async (dataToSave: OneBotConfig['network'][typeof field][0]) => {
|
||
try {
|
||
if (isCreate) {
|
||
await createNetworkConfig(field, dataToSave);
|
||
} else {
|
||
await updateNetworkConfig(field, dataToSave);
|
||
}
|
||
toast.success('保存配置成功');
|
||
} catch (error) {
|
||
const msg = (error as Error).message;
|
||
|
||
toast.error(`保存配置失败: ${msg}`);
|
||
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
if (['httpServers', 'httpSseServers', 'websocketServers'].includes(field)) {
|
||
const serverData = data as any;
|
||
if (!serverData.token && serverData.host !== '127.0.0.1') {
|
||
await new Promise<void>((resolve, reject) => {
|
||
dialog.confirm({
|
||
title: '安全警告',
|
||
content: (
|
||
<div>
|
||
<p>检测到未配置Token,这可能导致安全风险。确认要继续吗?</p>
|
||
<p className='text-sm text-gray-500 mt-2'>(未配置Token时,Host将被强制限制为 127.0.0.1)</p>
|
||
</div>
|
||
),
|
||
onConfirm: async () => {
|
||
serverData.host = '127.0.0.1';
|
||
try {
|
||
await saveData(serverData);
|
||
resolve();
|
||
} catch (e) {
|
||
reject(e);
|
||
}
|
||
},
|
||
onCancel: () => {
|
||
reject(new Error('Cancelled'));
|
||
},
|
||
});
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
await saveData(data);
|
||
};
|
||
|
||
const renderFormComponent = (onClose: () => void) => {
|
||
switch (field) {
|
||
case 'httpServers':
|
||
return (
|
||
<HTTPServerForm
|
||
data={data as OneBotConfig['network']['httpServers'][0]}
|
||
onClose={onClose}
|
||
onSubmit={onSubmit}
|
||
/>
|
||
);
|
||
case 'httpClients':
|
||
return (
|
||
<HTTPClientForm
|
||
data={data as OneBotConfig['network']['httpClients'][0]}
|
||
onClose={onClose}
|
||
onSubmit={onSubmit}
|
||
/>
|
||
);
|
||
case 'websocketServers':
|
||
return (
|
||
<WebsocketServerForm
|
||
data={data as OneBotConfig['network']['websocketServers'][0]}
|
||
onClose={onClose}
|
||
onSubmit={onSubmit}
|
||
/>
|
||
);
|
||
case 'websocketClients':
|
||
return (
|
||
<WebsocketClientForm
|
||
data={data as OneBotConfig['network']['websocketClients'][0]}
|
||
onClose={onClose}
|
||
onSubmit={onSubmit}
|
||
/>
|
||
);
|
||
case 'httpSseServers':
|
||
return (
|
||
<HTTPServerSSEForm
|
||
data={data as OneBotConfig['network']['httpSseServers'][0]}
|
||
onClose={onClose}
|
||
onSubmit={onSubmit}
|
||
/>
|
||
);
|
||
default:
|
||
return null;
|
||
}
|
||
};
|
||
|
||
return (
|
||
<Modal
|
||
backdrop='blur'
|
||
isDismissable={false}
|
||
isOpen={isOpen}
|
||
size='lg'
|
||
scrollBehavior='outside'
|
||
onOpenChange={onOpenChange}
|
||
>
|
||
<ModalContent>
|
||
{(onClose) => (
|
||
<>
|
||
<ModalHeader className='flex flex-col gap-1'>
|
||
{modalTitle[field]}
|
||
</ModalHeader>
|
||
{renderFormComponent(onClose)}
|
||
</>
|
||
)}
|
||
</ModalContent>
|
||
</Modal>
|
||
);
|
||
};
|
||
|
||
export default NetworkFormModal;
|