bug fixes

This commit is contained in:
bflatastic committed 2026-03-10 21:04:53 +07:00
1 parent 40a2e8a514
commit e9316bcdb5
12 files changed
+64 -47

No files matched your search

@@ -152,15 +152,17 @@ export const ImageTo3DExperience = ({
);
useEffect(() => {
if (variant === "world" && pendingExternalImage) {
// Read from store directly to avoid Strict Mode double-execution adding the image twice
const pending = useImageTo3DWorldStore.getState().pendingExternalImage;
if (variant === "world" && pending) {
setWorldImages((prev) => {
if (prev.length >= MAX_WORLD_IMAGES) return prev;
return [
...prev,
{
id: generateId(),
preview: pendingExternalImage.url,
mediaToken: pendingExternalImage.mediaToken,
preview: pending.url,
mediaToken: pending.mediaToken,
name: "Library Image",
isUploading: false,
},
@@ -400,9 +402,6 @@ export const ImageTo3DExperience = ({
if ("error_type" in result) {
throw new Error(result.error_message || result.error_type);
}
setWorldImages([]);
setWorldPrompt("");
} else {
const snapshotPrompt = prompt.trim();
const snapshotPreview = uploadedPreview || undefined;
@@ -735,7 +734,7 @@ export const ImageTo3DExperience = ({
key={img.id}
className={twMerge(
"glass group relative aspect-square overflow-hidden rounded-lg border-2 border-white/30 transition-all",
hasResults ? "w-10" : "w-14",
hasResults ? "w-10" : "w-auto",
img.isUploading
? "cursor-default"
: "cursor-pointer hover:cursor-zoom-in hover:border-white/80",
@@ -412,13 +412,21 @@ export const TaskQueue = () => {
? getProviderDisplayName(String(t.provider).toLowerCase())
: undefined;
const taskTypeStr = t.task_type ? String(t.task_type).toLowerCase() : "";
const modelTypeStr = t.model_type ? String(t.model_type).toLowerCase() : "";
const isSplatModel =
taskTypeStr.includes("gaussian") ||
modelTypeStr.includes("marble") ||
modelTypeStr.includes("worldlabs");
const is3DModel =
taskTypeStr.includes("3d") ||
taskTypeStr.includes("object") ||
taskTypeStr.includes("dimensional");
taskTypeStr.includes("dimensional") ||
isSplatModel;
let kind = undefined;
if (taskTypeStr.includes("image") && is3DModel) {
if (isSplatModel) {
kind = "3D World";
} else if (taskTypeStr.includes("image") && is3DModel) {
kind = "Image to 3D";
} else if (is3DModel) {
kind = "3D Model";
@@ -26,7 +26,7 @@ import { OrbitSphere, snapToNearest } from "./OrbitSphere";
import { twMerge } from "tailwind-merge";
import { LoadingSpinner } from "@storyteller/ui-loading-spinner";
import { SliderV2 } from "@storyteller/ui-sliderv2";
import { Switch } from "@headlessui/react";
// import { Switch } from "@headlessui/react";
import { EnqueueEditImage } from "@storyteller/tauri-api";
import { listen } from "@tauri-apps/api/event";
import {
@@ -41,10 +41,7 @@ import {
useCostBreakdownModalStore,
} from "@storyteller/ui-pricing-modal";
import { HelpMenuButton } from "@storyteller/ui-help-menu";
import {
HistoryStack,
ImageBundle,
} from "../PageEdit/HistoryStack";
import { HistoryStack, ImageBundle } from "../PageEdit/HistoryStack";
import type { BaseSelectorImage } from "../PageEdit/BaseImageSelector";
const ANGLES_MODEL_PAGE = ModelPage.Angles;
@@ -84,9 +81,9 @@ export const Angles = () => {
const sourceMediaToken = useAnglesStore((s) => s.sourceMediaToken);
const imageDimensions = useAnglesStore((s) => s.imageDimensions);
const angleConfig = useAnglesStore((s) => s.angleConfig);
const generateFromBestAngles = useAnglesStore(
(s) => s.generateFromBestAngles,
);
// const generateFromBestAngles = useAnglesStore(
// (s) => s.generateFromBestAngles,
// );
const generatedAngles = useAnglesStore((s) => s.generatedAngles);
const activeAngleId = useAnglesStore((s) => s.activeAngleId);
const isProcessing = useAnglesStore((s) => s.isProcessing);
@@ -98,9 +95,9 @@ export const Angles = () => {
const setRotation = useAnglesStore((s) => s.setRotation);
const setTilt = useAnglesStore((s) => s.setTilt);
const setZoom = useAnglesStore((s) => s.setZoom);
const setGenerateFromBestAngles = useAnglesStore(
(s) => s.setGenerateFromBestAngles,
);
// const setGenerateFromBestAngles = useAnglesStore(
// (s) => s.setGenerateFromBestAngles,
// );
const setActiveAngle = useAnglesStore((s) => s.setActiveAngle);
const setIsLoadingImage = useAnglesStore((s) => s.setIsLoadingImage);
const resetSource = useAnglesStore((s) => s.resetSource);
@@ -160,9 +157,7 @@ export const Angles = () => {
// Resolve pending placeholder
const resolveId =
event.maybe_frontend_subscriber_id ?? state.pendingSubscriberId;
setPendingGenerations((prev) =>
prev.filter((p) => p.id !== resolveId),
);
setPendingGenerations((prev) => prev.filter((p) => p.id !== resolveId));
});
return () => {
@@ -469,21 +464,18 @@ export const Angles = () => {
[setActiveAngle],
);
const handleHistoryImageRemove = useCallback(
(image: BaseSelectorImage) => {
setHistoryBundles((prev) =>
prev
.map((bundle) => ({
...bundle,
images: bundle.images.filter(
(img) => img.mediaToken !== image.mediaToken,
),
}))
.filter((bundle) => bundle.images.length > 0),
);
},
[],
);
const handleHistoryImageRemove = useCallback((image: BaseSelectorImage) => {
setHistoryBundles((prev) =>
prev
.map((bundle) => ({
...bundle,
images: bundle.images.filter(
(img) => img.mediaToken !== image.mediaToken,
),
}))
.filter((bundle) => bundle.images.length > 0),
);
}, []);
const handleHistoryClear = useCallback(() => {
setHistoryBundles([]);
@@ -738,7 +730,7 @@ export const Angles = () => {
{/* Toggle + Generate */}
<div className="flex shrink-0 flex-col items-end gap-2.5">
<Switch.Group>
{/* <Switch.Group>
<div className="flex items-center gap-2">
<Switch.Label className="cursor-pointer whitespace-nowrap text-xs text-base-fg/50">
Best 12 angles
@@ -761,11 +753,10 @@ export const Angles = () => {
/>
</Switch>
</div>
</Switch.Group>
</Switch.Group> */}
<GenerateButton
variant="primary"
icon={faCrosshairs}
onClick={handleGenerate}
disabled={isProcessing || !sourceMediaToken}
loading={isProcessing}
@@ -516,7 +516,7 @@ export const PageEditor = () => {
onClick={handleOverlayClick}
>
<div
className="absolute bottom-14 mb-4 ml-4 flex origin-bottom-left flex-col gap-2"
className="absolute bottom-20 mb-4 ml-4 flex origin-bottom-left flex-col gap-2"
style={{ transform: `scale(${getScale()})` }}
>
<Outliner />
@@ -186,7 +186,7 @@ export const ControlPanelSceneObject = () => {
as="div"
show={isShowing.value}
className={twMerge(
"glass absolute bottom-0 right-0 mb-4 mr-4 flex h-fit w-56 origin-bottom-right flex-col gap-2 rounded-lg border border-ui-panel-border p-3.5 text-white shadow-lg",
"glass absolute bottom-16 right-0 mb-4 mr-4 flex h-fit w-56 origin-bottom-right flex-col gap-2 rounded-lg border border-ui-panel-border p-3.5 text-white shadow-lg",
)}
enter="transition-opacity duration-150"
enterFrom="opacity-0"
@@ -6,5 +6,6 @@ export enum TaskType {
ImageInpaintEdit = "image_inpaint_edit",
VideoGeneration = "video_generation",
ObjectGeneration = "object_generation",
SplatGeneration = "gaussian_generation",
BackgroundRemoval = "background_removal",
}
@@ -51,10 +51,14 @@ export const MODEL_TYPE_TO_CREATOR: Record<string, ModelCreator> = {
hunyuan_3d: ModelCreator.Tencent,
hunyuan_3d_2p0: ModelCreator.Tencent,
hunyuan_3d_2p1: ModelCreator.Tencent,
hunyuan_3d_2: ModelCreator.Tencent,
hunyuan_3d_3: ModelCreator.Tencent,
// Hunyuan — dot-normalized aliases
hunyuan_3d_2_0: ModelCreator.Tencent,
hunyuan_3d_2_1: ModelCreator.Tencent,
worldlabs_gaussian: ModelCreator.WorldLabs,
marble_0p1_mini: ModelCreator.WorldLabs,
marble_0p1_plus: ModelCreator.WorldLabs,
grok_image: ModelCreator.Grok,
grok_video: ModelCreator.Grok,
midjourney: ModelCreator.Midjourney,
@@ -195,14 +199,18 @@ export const getModelDisplayName = (modelType: string): string => {
// Hunyuan (Tencent) — p-style IDs
hunyuan_3d: "Hunyuan 3D",
hunyuan_3d_2: "Hunyuan 3D 2.0",
hunyuan_3d_2p0: "Hunyuan 3D 2.0",
hunyuan_3d_2p1: "Hunyuan 3D 2.1",
hunyuan_3d_3: "Hunyuan 3D 3.0",
// Hunyuan — dot-normalized aliases
hunyuan_3d_2_0: "Hunyuan 3D 2.0",
hunyuan_3d_2_1: "Hunyuan 3D 2.1",
// World Labs
worldlabs_gaussian: "World Labs Marble",
marble_0p1_mini: "Marble Mini",
marble_0p1_plus: "Marble Plus",
// Catch-all bucket for Midjourney.
midjourney: "Midjourney",
@@ -15,4 +15,6 @@ export enum GenerationAction {
GenerateVideo = "generate_video",
RemoveBackground = "remove_background",
ImageTo3d = "image_to_3d",
GenerateGaussian = "generate_gaussian",
ImageInpaintEdit = "image_inpaint_edit",
}
@@ -57,7 +57,9 @@ const makeMessage = (event: GenerationCompleteEvent) => {
case GenerationAction.RemoveBackground:
return "Background removal complete!";
case GenerationAction.ImageTo3d:
return "Image to 3D complete!";
return "3D model generation complete!";
case GenerationAction.GenerateGaussian:
return "3D world generation complete!";
default:
return "Generation complete!";
}
@@ -58,7 +58,9 @@ const makeMessage = (event: GenerationEnqueueFailureEvent) => {
case GenerationAction.RemoveBackground:
return "Couldn't enqueue background removal!";
case GenerationAction.ImageTo3d:
return "Couldn't enqueue image to 3D!";
return "Couldn't enqueue 3D model generation!";
case GenerationAction.GenerateGaussian:
return "Couldn't enqueue 3D world generation!";
default:
return "Couldn't enqueue generation!";
}
@@ -54,7 +54,9 @@ const makeMessage = (event: GenerationEnqueueSuccessEvent) => {
case GenerationAction.RemoveBackground:
return "Background removal enqueued!";
case GenerationAction.ImageTo3d:
return "Image to 3D enqueued!";
return "3D model generation enqueued!";
case GenerationAction.GenerateGaussian:
return "3D world generation enqueued!";
default:
return "Generation enqueued!";
}
@@ -58,7 +58,9 @@ const makeMessage = (event: GenerationFailedEvent) => {
case GenerationAction.RemoveBackground:
return "Background removal failed!";
case GenerationAction.ImageTo3d:
return "Image to 3D failed!";
return "3D model generation failed!";
case GenerationAction.GenerateGaussian:
return "3D world generation failed!";
default:
return "Generation failed!";
}