diff --git a/app/api/v1/[...path]/route.ts b/app/api/v1/[...path]/route.ts
index b3df3d4..8009a7b 100644
--- a/app/api/v1/[...path]/route.ts
+++ b/app/api/v1/[...path]/route.ts
@@ -2,6 +2,7 @@ import { NextRequest } from "next/server";
import { handle } from "@/lib/api";
export const runtime = "nodejs";
export const dynamic = "force-dynamic";
+export const maxDuration = 300;
async function route(
request: NextRequest,
{ params }: { params: Promise<{ path: string[] }> },
diff --git a/app/globals.css b/app/globals.css
index 2a5bbfa..c5be507 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -706,10 +706,32 @@ nav a:hover,
}
.catalog-controls {
display: flex;
+ align-items: center;
+ flex-wrap: wrap;
gap: 20px;
justify-content: space-between;
margin: 35px 0;
}
+.map-import-dialog {
+ margin: auto;
+ background: var(--panel);
+ color: var(--text);
+ border: 1px solid var(--line);
+ border-radius: 12px;
+ padding: 24px;
+ width: min(540px, calc(100vw - 32px));
+ max-height: calc(100dvh - 32px);
+ overflow: auto;
+}
+.map-import-dialog::backdrop { background: rgb(0 0 0 / 65%); }
+.map-import-heading { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
+.map-import-heading h2 { margin: 0; }
+.map-import-dialog .field input { max-width: 100%; }
+.map-export { margin: 16px 0; }
+.catalog-search { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; }
+.catalog-search .search-field { flex: 1; min-width: 0; }
+.catalog-search .search-field input { min-width: 0; }
+.catalog-search > .button { flex-shrink: 0; }
.search-field {
border: 1px solid var(--line);
background: var(--panel);
@@ -1399,6 +1421,7 @@ pre {
}
.catalog-controls {
flex-direction: column;
+ align-items: stretch;
}
.difficulty-options {
gap: 8px;
diff --git a/app/servers/[id]/page.tsx b/app/servers/[id]/page.tsx
index d92c7e4..025ce39 100644
--- a/app/servers/[id]/page.tsx
+++ b/app/servers/[id]/page.tsx
@@ -6,6 +6,8 @@ import { StartGame } from "@/components/StartGame";
import { getMap } from "@/lib/catalog";
import { ContributionInstructions } from "@/components/ContributionInstructions";
import { ReportContent } from "@/components/ReportContent";
+import { user } from "@/lib/supabase";
+import { ExportMap } from "@/components/MapTransfer";
export default async function ServerPage({
params,
}: {
@@ -15,6 +17,7 @@ export default async function ServerPage({
const { id } = await params;
const map = await getMap(id);
if (!map) notFound();
+ const account = await user();
return (
<>
{t("Map ID:")} {map.id}
+ {t( + "This shared map is private and playable without moderator review. Only the original owner can submit it for public review.", + )} +
+ {draft.state === "draft" &&+ {t( + "The newest eligible capture is selected automatically. Choose the original capture only if you want its older terrain.", + )} +