fix
This commit is contained in:
130
src/screens/ProxyForm.jsx
Normal file
130
src/screens/ProxyForm.jsx
Normal file
@@ -0,0 +1,130 @@
|
||||
import React, { useState } from "react";
|
||||
import { Box, Text, useInput } from "ink";
|
||||
import TextInput from "ink-text-input";
|
||||
|
||||
import { frpAddProxyPlan } from "../lib/tasks.js";
|
||||
|
||||
const FIELDS = [
|
||||
{ key: "name", label: "Name (e.g. ssh)" },
|
||||
{ key: "type", label: "Type" },
|
||||
{ key: "localIp", label: "Local IP" },
|
||||
{ key: "localPort", label: "Local port" },
|
||||
{ key: "remotePort", label: "Remote port" },
|
||||
];
|
||||
|
||||
export default function ProxyForm({ nav }) {
|
||||
const [values, setValues] = useState({
|
||||
name: "",
|
||||
type: "tcp",
|
||||
localIp: "127.0.0.1",
|
||||
localPort: "",
|
||||
remotePort: "",
|
||||
});
|
||||
const [restart, setRestart] = useState(true);
|
||||
const [step, setStep] = useState(0);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const totalRows = FIELDS.length + 1;
|
||||
|
||||
useInput((input, key) => {
|
||||
if (key.tab || key.downArrow) {
|
||||
setStep((s) => Math.min(s + 1, totalRows - 1));
|
||||
return;
|
||||
}
|
||||
if (key.upArrow) {
|
||||
setStep((s) => Math.max(s - 1, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
if (step === totalRows - 1) {
|
||||
if (input === " ") {
|
||||
setRestart((r) => !r);
|
||||
return;
|
||||
}
|
||||
if (key.return) {
|
||||
submit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (key.return) {
|
||||
if (step < totalRows - 1) {
|
||||
setStep((s) => s + 1);
|
||||
return;
|
||||
}
|
||||
submit();
|
||||
}
|
||||
});
|
||||
|
||||
const update = (key) => (value) => {
|
||||
setValues((v) => ({ ...v, [key]: value }));
|
||||
};
|
||||
|
||||
const submit = () => {
|
||||
setError(null);
|
||||
const localPort = Number(values.localPort);
|
||||
const remotePort = Number(values.remotePort);
|
||||
if (!Number.isInteger(localPort) || localPort < 1 || localPort > 65535) {
|
||||
setError("Local port must be an integer in [1, 65535].");
|
||||
return;
|
||||
}
|
||||
if (!Number.isInteger(remotePort) || remotePort < 1 || remotePort > 65535) {
|
||||
setError("Remote port must be an integer in [1, 65535].");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const plan = frpAddProxyPlan({
|
||||
name: values.name.trim(),
|
||||
type: values.type.trim() || "tcp",
|
||||
localIp: values.localIp.trim() || "127.0.0.1",
|
||||
localPort,
|
||||
remotePort,
|
||||
restart,
|
||||
});
|
||||
nav.replace({ name: "plan", props: { plan, origin: "frp" } });
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>Add frp proxy:</Text>
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
{FIELDS.map((field, index) => (
|
||||
<Box key={field.key}>
|
||||
<Box width={20}>
|
||||
<Text color={index === step ? "cyan" : undefined}>
|
||||
{index === step ? "› " : " "}
|
||||
{field.label}
|
||||
</Text>
|
||||
</Box>
|
||||
<TextInput
|
||||
value={values[field.key]}
|
||||
onChange={update(field.key)}
|
||||
focus={index === step}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
<Box>
|
||||
<Box width={20}>
|
||||
<Text color={step === FIELDS.length ? "cyan" : undefined}>
|
||||
{step === FIELDS.length ? "› " : " "}
|
||||
Restart frpc
|
||||
</Text>
|
||||
</Box>
|
||||
<Text>[{restart ? "x" : " "}] (Space to toggle)</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
{error ? (
|
||||
<Box marginTop={1}>
|
||||
<Text color="red">{error}</Text>
|
||||
</Box>
|
||||
) : null}
|
||||
<Box marginTop={1}>
|
||||
<Text dimColor>Tab/↓ next · ↑ prev · Space toggles restart · Enter on last submits</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user