From a50ce98803fa49e830e19bb21cc28caaf85c20f9 Mon Sep 17 00:00:00 2001 From: BFlat Date: Tue, 19 May 2026 22:59:34 +0700 Subject: [PATCH] webapp: coming soon model (#1539) --- .../src/pages/create-image/create-image.tsx | 1 + .../src/pages/create-video/create-video.tsx | 50 ++++++++++++++++--- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/frontend/apps/artcraft-webapp/src/pages/create-image/create-image.tsx b/frontend/apps/artcraft-webapp/src/pages/create-image/create-image.tsx index 4c6fefba0c..5b922bf48b 100644 --- a/frontend/apps/artcraft-webapp/src/pages/create-image/create-image.tsx +++ b/frontend/apps/artcraft-webapp/src/pages/create-image/create-image.tsx @@ -416,6 +416,7 @@ export default function CreateImage() { onSelect={handleModelChange} mode="toggle" panelTitle="Select Model" + panelClassName="w-max" showIconsInList triggerIcon={ = Object.fromEntries( // ── Model lookup ───────────────────────────────────────────────────────── +// Placeholder entries shown in the picker as disabled "SOON" items. These are +// UI-only — they are not in `_modelLookup`, so the click handler is a no-op +// (the `disabled` flag also prevents the row from firing). +const COMING_SOON_MODELS: ReadonlyArray<{ id: string; label: string }> = [ + { id: "seedance_2p1", label: "Seedance 2.1" }, +]; + let _modelLookup = new Map(); function buildModelPopoverItems( @@ -104,7 +108,7 @@ function buildModelPopoverItems( selectedId: string, ): PopoverItem[] { _modelLookup = new Map(models.map((m) => [m.model, m])); - return models.map((model) => ({ + const apiItems: PopoverItem[] = models.map((model) => ({ label: model.full_name || model.model, selected: model.model === selectedId, icon: ( @@ -116,6 +120,27 @@ function buildModelPopoverItems( ), action: model.model, })); + const comingSoonItems: PopoverItem[] = COMING_SOON_MODELS.map( + ({ id, label }) => ({ + label, + selected: false, + disabled: true, + className: "!ml-0", + icon: ( + {`${id} + ), + trailing: ( + + Soon + + ), + }), + ); + return [...apiItems, ...comingSoonItems]; } function buildSizePopoverItems( @@ -750,11 +775,15 @@ export default function CreateVideo() { : undefined; const referenceVideoTokens = isReferenceMode && referenceVideos.length > 0 - ? referenceVideos.map((v) => v.mediaToken).filter((t): t is string => typeof t === "string" && t.length > 0) + ? referenceVideos + .map((v) => v.mediaToken) + .filter((t): t is string => typeof t === "string" && t.length > 0) : undefined; const referenceAudioTokens = isReferenceMode && referenceAudios.length > 0 - ? referenceAudios.map((a) => a.mediaToken).filter((t): t is string => typeof t === "string" && t.length > 0) + ? referenceAudios + .map((a) => a.mediaToken) + .filter((t): t is string => typeof t === "string" && t.length > 0) : undefined; // Extract character tokens from @-mentions in the prompt. Match longest @@ -809,7 +838,11 @@ export default function CreateVideo() { console.log("[generate-video] params", baseParams); const modelLabel = selectedModel.full_name ?? selectedModel.model; - const batchId = startBatch(prompt, modelLabel, numVideos > 1 ? numVideos : undefined); + const batchId = startBatch( + prompt, + modelLabel, + numVideos > 1 ? numVideos : undefined, + ); try { console.log("[generate-video] enqueueing job..."); @@ -975,6 +1008,7 @@ export default function CreateVideo() { onSelect={handleModelChange} mode="toggle" panelTitle="Select Model" + panelClassName="w-max" showIconsInList triggerIcon={