Add Modrinth and CurseForge project ID lookup to field validation
This commit is contained in:
parent
9658773fa2
commit
52ef5bf927
@ -13,7 +13,6 @@ import {
|
||||
App,
|
||||
} from "antd";
|
||||
import { PlusOutlined, DeleteOutlined } from "@ant-design/icons";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
import { createConfig, updateConfig } from "@/services/config";
|
||||
import {
|
||||
getModrinthLoaders,
|
||||
@ -25,6 +24,8 @@ import {
|
||||
readProjectVersion,
|
||||
checkArtifactFiles,
|
||||
checkSourceFiles,
|
||||
lookupModrinthProject,
|
||||
lookupCurseforgeProject,
|
||||
} from "@/services/project";
|
||||
import {
|
||||
useFieldValidations,
|
||||
@ -137,6 +138,32 @@ const STATIC_DEFS: StaticValidationDef<Config>[] = [
|
||||
: { status: "error", help: r.error };
|
||||
},
|
||||
},
|
||||
// 5. Modrinth 项目 ID
|
||||
{
|
||||
target: ["modrinth", "project_id"],
|
||||
deps: [["modrinth", "project_id"]],
|
||||
async validate(getVal) {
|
||||
const id = getVal(["modrinth", "project_id"]) as string | undefined;
|
||||
if (!id) return null;
|
||||
const r = await lookupModrinthProject(id);
|
||||
return r.ok
|
||||
? { status: "success", help: `项目:${r.name}` }
|
||||
: { status: "error", help: r.error };
|
||||
},
|
||||
},
|
||||
// 6. CurseForge 项目 ID
|
||||
{
|
||||
target: ["curseforge", "project_id"],
|
||||
deps: [["curseforge", "project_id"]],
|
||||
async validate(getVal) {
|
||||
const id = getVal(["curseforge", "project_id"]) as number | undefined;
|
||||
if (id == null || id === 0) return null;
|
||||
const r = await lookupCurseforgeProject(id);
|
||||
return r.ok
|
||||
? { status: "success", help: `项目:${r.name}` }
|
||||
: { status: "error", help: r.error };
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const LIST_DEFS: ListValidationDef<Config>[] = [];
|
||||
@ -299,29 +326,6 @@ export function ConfigModal({
|
||||
[mode, initialName, onSaved, message],
|
||||
);
|
||||
|
||||
// --------------- Debounced project name lookup ---------------
|
||||
|
||||
const [modrinthProjectName, setModrinthProjectName] = useState<string | null>(null);
|
||||
const [curseforgeProjectName, setCurseforgeProjectName] = useState<string | null>(null);
|
||||
|
||||
const lookupModrinthProject = useDebouncedCallback(async (projectId: string) => {
|
||||
if (!projectId) {
|
||||
setModrinthProjectName(null);
|
||||
return;
|
||||
}
|
||||
// TODO: call Modrinth API to get project name
|
||||
setModrinthProjectName(null);
|
||||
}, 800);
|
||||
|
||||
const lookupCurseforgeProject = useDebouncedCallback(async (projectId: number | null) => {
|
||||
if (projectId == null) {
|
||||
setCurseforgeProjectName(null);
|
||||
return;
|
||||
}
|
||||
// TODO: call CurseForge API to get project name
|
||||
setCurseforgeProjectName(null);
|
||||
}, 800);
|
||||
|
||||
// --------------- Render ---------------
|
||||
|
||||
return (
|
||||
@ -351,10 +355,6 @@ export function ConfigModal({
|
||||
<ConfigModalForm
|
||||
mode={mode}
|
||||
initialConfig={initialConfig}
|
||||
modrinthProjectName={modrinthProjectName}
|
||||
curseforgeProjectName={curseforgeProjectName}
|
||||
lookupModrinthProject={lookupModrinthProject}
|
||||
lookupCurseforgeProject={lookupCurseforgeProject}
|
||||
onSave={handleSave}
|
||||
/>
|
||||
</Modal>
|
||||
@ -368,20 +368,12 @@ export function ConfigModal({
|
||||
interface ConfigModalFormProps {
|
||||
mode: "add" | "edit";
|
||||
initialConfig: Config | null;
|
||||
modrinthProjectName: string | null;
|
||||
curseforgeProjectName: string | null;
|
||||
lookupModrinthProject: (projectId: string) => void;
|
||||
lookupCurseforgeProject: (projectId: number | null) => void;
|
||||
onSave: (values: ConfigValues) => void;
|
||||
}
|
||||
|
||||
function ConfigModalForm({
|
||||
mode,
|
||||
initialConfig,
|
||||
modrinthProjectName,
|
||||
curseforgeProjectName,
|
||||
lookupModrinthProject,
|
||||
lookupCurseforgeProject,
|
||||
onSave,
|
||||
}: ConfigModalFormProps) {
|
||||
const [form] = Form.useForm<ConfigValues>();
|
||||
@ -527,23 +519,15 @@ function ConfigModalForm({
|
||||
label: "Modrinth",
|
||||
children: (
|
||||
<>
|
||||
<Form.Item
|
||||
<ValidatedFormItem
|
||||
name={["modrinth", "project_id"]}
|
||||
label="项目 ID"
|
||||
rules={[
|
||||
{ required: true, message: "请输入 Modrinth 项目 ID" },
|
||||
]}
|
||||
extra={
|
||||
modrinthProjectName
|
||||
? `项目名称: ${modrinthProjectName}`
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Input
|
||||
placeholder="8 位 base62"
|
||||
onChange={(e) => lookupModrinthProject(e.target.value)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Input placeholder="8 位 base62" />
|
||||
</ValidatedFormItem>
|
||||
|
||||
<Form.Item
|
||||
name={["modrinth", "version_name"]}
|
||||
@ -658,7 +642,7 @@ function ConfigModalForm({
|
||||
label: "CurseForge",
|
||||
children: (
|
||||
<>
|
||||
<Form.Item
|
||||
<ValidatedFormItem
|
||||
name={["curseforge", "project_id"]}
|
||||
label="项目 ID"
|
||||
rules={[
|
||||
@ -667,22 +651,12 @@ function ConfigModalForm({
|
||||
message: "请输入 CurseForge 项目 ID",
|
||||
},
|
||||
]}
|
||||
extra={
|
||||
curseforgeProjectName
|
||||
? `项目名称: ${curseforgeProjectName}`
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<InputNumber
|
||||
style={{ width: "100%" }}
|
||||
placeholder="数字 ID"
|
||||
onChange={(val) =>
|
||||
lookupCurseforgeProject(
|
||||
typeof val === "number" ? val : null,
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
</ValidatedFormItem>
|
||||
|
||||
<Form.Item
|
||||
name={["curseforge", "version_name"]}
|
||||
|
||||
@ -250,3 +250,33 @@ export async function checkSourceFiles(
|
||||
}
|
||||
return { ok: true, matched };
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 平台项目查询
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
import { getProject } from "@/lib/modrinth/project";
|
||||
import { getMod } from "@/lib/curseforge/mod";
|
||||
import { modrinthClient, curseforgeClient } from "./clients";
|
||||
|
||||
export async function lookupModrinthProject(
|
||||
projectId: string,
|
||||
): Promise<OkResult<{ name: string }> | ErrResult> {
|
||||
try {
|
||||
const project = await getProject(modrinthClient, projectId);
|
||||
return { ok: true, name: project.title };
|
||||
} catch (err) {
|
||||
return { ok: false, error: err instanceof Error ? err.message : "查询 Modrinth 项目失败" };
|
||||
}
|
||||
}
|
||||
|
||||
export async function lookupCurseforgeProject(
|
||||
projectId: number,
|
||||
): Promise<OkResult<{ name: string }> | ErrResult> {
|
||||
try {
|
||||
const mod = await getMod(curseforgeClient, projectId);
|
||||
return { ok: true, name: mod.data.name };
|
||||
} catch (err) {
|
||||
return { ok: false, error: err instanceof Error ? err.message : "查询 CurseForge 项目失败" };
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user