Validate and deduplicate custom difficulty presets
Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 6m4s
Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 6m4s
This commit is contained in:
@@ -7,9 +7,11 @@ import { useRouter } from "next/navigation";
|
||||
import { ArrowRight, Timer, ZoomIn, Users } from "lucide-react";
|
||||
import {
|
||||
difficulties,
|
||||
customDifficultySchema,
|
||||
type DifficultyPreset,
|
||||
} from "@/shared/protocol";
|
||||
import { api } from "@/lib/client-api";
|
||||
import { mergeDifficultyPresets } from "@/shared/difficulty-presets";
|
||||
export { api } from "@/lib/client-api";
|
||||
export function StartGame({
|
||||
datasetId,
|
||||
@@ -32,13 +34,19 @@ export function StartGame({
|
||||
[error, setError] = useState("");
|
||||
const router = useRouter();
|
||||
const starting = useRef(false);
|
||||
const savingPreset = useRef(false);
|
||||
useEffect(() => {
|
||||
let disposed = false;
|
||||
api<{ presets: DifficultyPreset[] }>("difficulty-presets")
|
||||
.then(({ presets }) => {
|
||||
if (!disposed) setCustomPresets(presets);
|
||||
if (!disposed)
|
||||
setCustomPresets((current) =>
|
||||
mergeDifficultyPresets(current, presets),
|
||||
);
|
||||
})
|
||||
.catch(() => {});
|
||||
.catch((failure) => {
|
||||
if (!disposed) setError(failure.message);
|
||||
});
|
||||
return () => {
|
||||
disposed = true;
|
||||
};
|
||||
@@ -54,19 +62,25 @@ export function StartGame({
|
||||
];
|
||||
async function saveDifficulty(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
if (savingDifficulty) return;
|
||||
if (savingPreset.current || starting.current) return;
|
||||
const parsed = customDifficultySchema.safeParse({
|
||||
name: difficultyName,
|
||||
seconds: difficultySeconds,
|
||||
zoom: difficultyZoom,
|
||||
});
|
||||
if (!parsed.success) {
|
||||
setError(parsed.error.issues[0].message);
|
||||
return;
|
||||
}
|
||||
savingPreset.current = true;
|
||||
setSavingDifficulty(true);
|
||||
setError("");
|
||||
try {
|
||||
const { preset } = await api<{ preset: DifficultyPreset }>(
|
||||
"difficulty-presets",
|
||||
{
|
||||
name: difficultyName.trim(),
|
||||
seconds: difficultySeconds,
|
||||
zoom: difficultyZoom,
|
||||
},
|
||||
parsed.data,
|
||||
);
|
||||
setCustomPresets((current) => [...current, preset]);
|
||||
setCustomPresets((current) => mergeDifficultyPresets(current, [preset]));
|
||||
setDifficulty(preset.id);
|
||||
setDifficultyName("");
|
||||
setDifficultySeconds(90);
|
||||
@@ -75,11 +89,12 @@ export function StartGame({
|
||||
} catch (failure) {
|
||||
setError((failure as Error).message);
|
||||
} finally {
|
||||
savingPreset.current = false;
|
||||
setSavingDifficulty(false);
|
||||
}
|
||||
}
|
||||
async function start() {
|
||||
if (starting.current) return;
|
||||
if (starting.current || savingPreset.current) return;
|
||||
starting.current = true;
|
||||
setLoading(true);
|
||||
setError("");
|
||||
@@ -168,17 +183,17 @@ export function StartGame({
|
||||
<input
|
||||
id="custom-difficulty-name"
|
||||
value={difficultyName}
|
||||
onChange={(event) => setDifficultyName(event.target.value)}
|
||||
onChange={(event) =>
|
||||
setDifficultyName([...event.target.value].slice(0, 40).join(""))
|
||||
}
|
||||
minLength={2}
|
||||
maxLength={40}
|
||||
maxLength={80}
|
||||
required
|
||||
autoComplete="off"
|
||||
placeholder={t("Name this difficulty")}
|
||||
disabled={savingDifficulty || loading}
|
||||
/>
|
||||
<label htmlFor="custom-difficulty-seconds">
|
||||
{t("Round time")}
|
||||
</label>
|
||||
<label htmlFor="custom-difficulty-seconds">{t("Round time")}</label>
|
||||
<div className="difficulty-builder-time">
|
||||
<input
|
||||
id="custom-difficulty-seconds"
|
||||
@@ -253,7 +268,9 @@ export function StartGame({
|
||||
<button
|
||||
className="button primary full"
|
||||
onClick={start}
|
||||
disabled={loading || (mode === "multiplayer" && !hostName)}
|
||||
disabled={
|
||||
loading || savingDifficulty || (mode === "multiplayer" && !hostName)
|
||||
}
|
||||
>
|
||||
{loading
|
||||
? t("Preparing your world…")
|
||||
|
||||
Reference in New Issue
Block a user