Repair uploads and let the console follow any registered server

This commit is contained in:
Aryan Singh committed 2026-10-16 20:34:12 -05:00
1 parent 3e24d4a7bb
commit 683cdc4016
15 files changed
+193 -84

No files matched your search

+14 -8
View File
@@ -728,7 +728,7 @@ function ProfileForm({
setP({
...p,
loader,
route: proxyCompatible(loader) ? p.route : "direct",
route: proxyCompatible(loader) || p.route === "internal" ? p.route : "direct",
modpack: loader === "MODRINTH" ? p.modpack : "",
map: ["VANILLA", "MODRINTH"].includes(loader)
? "none"
@@ -810,16 +810,17 @@ function ProfileForm({
Connection
<Select
value={p.route}
onChange={(v) => setP({ ...p, route: v as "proxy" | "direct" })}
onChange={(v) => setP({ ...p, route: v as WorldProfile["route"] })}
options={[
...(proxyCompatible(p.loader)
? [{ value: "proxy", label: "Through Velocity" }]
: []),
{ value: "direct", label: "Direct game port" },
{ value: "internal", label: "Private network / existing gateway" },
]}
/>
</label>
{p.route === "direct"
{p.route === "internal" ? <p className="text-xs text-muted">Private Docker network only. Connect through your existing gateway.</p> : p.route === "direct"
? field("port", "Public game port", "number")
: field(
"hostname",
@@ -1048,6 +1049,7 @@ function ServerTools({
);
}
function ProfileFiles({ id, locked }: { id: string; locked: boolean }) {
const [uploadDir, setUploadDir] = useState("mods");
const [path, setPath] = useState("");
const [entries, setEntries] = useState<
Array<{ name: string; directory: boolean; link: boolean }>
@@ -1146,8 +1148,10 @@ function ProfileFiles({ id, locked }: { id: string; locked: boolean }) {
))}
</div>
<label className={fieldStyle}>
Upload into /
{path || " (open mods, plugins, or world/datapacks first)"}
Upload destination (100 MB per file)
<select aria-label="Upload destination" value={uploadDir} onChange={e => setUploadDir(e.target.value)}>
<option value="mods">Mods (.jar)</option><option value="plugins">Plugins (.jar)</option><option value="world/datapacks">Datapacks (.zip)</option>
</select>
<input
type="file"
accept=".jar,.zip"
@@ -1155,19 +1159,21 @@ function ProfileFiles({ id, locked }: { id: string; locked: boolean }) {
onChange={async (e) => {
const file = e.target.files?.[0];
if (!file) return;
if (file.size > 100 * 1024 * 1024) { setError("Choose a file under 100 MB"); e.target.value = ""; return; }
if (!(uploadDir === "world/datapacks" ? /\.zip$/i : /\.jar$/i).test(file.name)) { setError("Choose a JAR for mods/plugins or a ZIP for datapacks"); e.target.value = ""; return; }
setBusy(true);
try {
const form = new FormData();
form.set("id", id);
form.set("path", [path, file.name].filter(Boolean).join("/"));
form.set("path", `${uploadDir}/${file.name}`);
form.set("file", file);
const res = await fetch("/api/network/files", {
method: "POST",
body: form,
});
const result = await res.json();
const result = await res.json().catch(() => ({ error: res.status === 413 ? "Upload rejected by the web proxy: file is too large" : `Upload failed (${res.status})` }));
if (!res.ok) throw new Error(result.error || "Upload failed");
await load(path);
await load(uploadDir);
toast("Uploaded", "success");
} catch (e) {
setError((e as Error).message);