Compare commits

...
Author SHA1 Message Date
Brandon Thomas e44c679a25 fixes for frontend build failures 2026-06-16 02:39:45 -04:00
31 changed files with 98 additions and 103 deletions
@@ -17,7 +17,6 @@ import {
faVideo,
faWandMagicSparkles,
faArrowRotateRight,
faWaveformLines,
} from "@fortawesome/pro-solid-svg-icons";
import { MediaFileDelete } from "@storyteller/tauri-api";
import { LoadingSpinner } from "@storyteller/ui-loading-spinner";
@@ -6,7 +6,6 @@ import {
Model,
VIDEO_MODELS,
IMAGE_MODELS,
IMAGE_MODELS_BY_ID,
SPLAT_MODELS,
OBJECT_3D_MODELS,
} from "@storyteller/model-list";
@@ -6,7 +6,7 @@ import { useEffect, useMemo } from "react";
import { PopoverMenu, type PopoverItem } from "@storyteller/ui-popover";
import { ModelPage } from "./model-pages";
import { Model } from "@storyteller/model-list";
import { Provider } from "@storyteller/tauri-api";
import { GenerationProvider } from "@storyteller/api-enums";
import { getProviderDisplayName, getProviderIcon } from "./provider-icons";
import {
useClassyModelSelectorStore,
@@ -16,17 +16,17 @@ import {
interface ProviderSelectorProps {
page: ModelPage;
model: Model | undefined;
providersByModel?: Partial<Record<string, Provider[]>>;
providersByModel?: Partial<Record<string, GenerationProvider[]>>;
panelTitle?: string;
buttonClassName?: string;
panelClassName?: string;
triggerLabel?: string;
}
const DEFAULT_PROVIDER_OPTIONS: Provider[] = [
Provider.ArtCraft,
Provider.Fal,
Provider.Sora,
const DEFAULT_PROVIDER_OPTIONS: GenerationProvider[] = [
GenerationProvider.Artcraft,
GenerationProvider.Fal,
GenerationProvider.Sora,
];
export function ProviderSelector({
@@ -38,7 +38,7 @@ export function ProviderSelector({
const { setSelectedProvider } = useClassyModelSelectorStore();
const modelId = model?.id;
const allowedProviders: Provider[] = useMemo(() => {
const allowedProviders: GenerationProvider[] = useMemo(() => {
if (!modelId) return DEFAULT_PROVIDER_OPTIONS;
return providersByModel?.[modelId] ?? DEFAULT_PROVIDER_OPTIONS;
}, [providersByModel, modelId]);
@@ -74,8 +74,8 @@ export function ProviderSelector({
const handleSelect = (item: PopoverItem) => {
if (!modelId) return;
const prov: Provider | undefined = (item as any).provider as
| Provider
const prov: GenerationProvider | undefined = (item as any).provider as
| GenerationProvider
| undefined;
if (!prov) return;
setSelectedProvider(page, modelId, prov);
@@ -173,7 +173,3 @@ export class Node {
}
}
}
function generateId(): string {
return `node-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
@@ -198,7 +198,7 @@ function DragScrubButton({
interface Edit3DScrubControlsProps {
nodeId: string;
stageRef: { current: Konva.Stage };
overlayHandle: React.RefObject<Model3DOverlayHandle>;
overlayHandle: React.RefObject<Model3DOverlayHandle | null>;
}
const Edit3DScrubControls = memo(function Edit3DScrubControls({
@@ -351,7 +351,6 @@ const PageDraw = ({ adapter }: PageDrawProps) => {
historyImageBundles,
pendingGenerations,
getAspectRatioDimensions,
finishRemoveBackground,
createImageFromUrl,
createImageFromFile,
createImageFrom3DModel,
@@ -361,7 +360,6 @@ const PageDraw = ({ adapter }: PageDrawProps) => {
removeHistoryImage,
addHistoryImageBundle,
addPendingGeneration,
resolvePendingGeneration,
removePendingGeneration,
clearPendingGenerations,
setAspectRatioType,
@@ -391,8 +389,6 @@ const PageDraw = ({ adapter }: PageDrawProps) => {
(state) => state.setGenerationCount,
);
const useSystemPrompt = promptStoreProvider((state) => state.useSystemPrompt);
const referenceImages = promptStoreProvider((state) => state.referenceImages);
const prompt = promptStoreProvider((state) => state.prompt);
const baseImageKonvaRef = useRef<Konva.Image>({} as Konva.Image);
const baseImageUrl = baseImageInfo?.url;
@@ -524,13 +520,13 @@ const PageDraw = ({ adapter }: PageDrawProps) => {
window.addEventListener(
"gallery-2d-drop",
handleGallery2DDrop as EventListener,
handleGallery2DDrop as unknown as EventListener,
);
return () => {
window.removeEventListener(
"gallery-2d-drop",
handleGallery2DDrop as EventListener,
handleGallery2DDrop as unknown as EventListener,
);
};
}, [createImageFromUrl, createImageFrom3DModel]);
@@ -15,12 +15,10 @@ import {
Line,
Image,
Transformer,
Group,
} from "react-konva";
import Konva from "konva";
import { LineNode, SceneState, useSceneStore } from "./stores/SceneState";
import { Node } from "./Node";
import { useStageSnapshot } from "./hooks/useUpdateSnapshot";
import "./pagedraw.css";
import SplitPane from "./components/ui/SplitPane";
import { useRightPanelLayoutManagement } from "./hooks/useRightPanelLayoutManagement";
@@ -4,10 +4,6 @@ import { ImageStyleSelectorProps } from './types';
const ImageStyleSelector: React.FC<ImageStyleSelectorProps> = ({ onImageSelect }) => {
const fileInputRef = useRef<HTMLInputElement>(null);
const handleClick = () => {
fileInputRef.current?.click();
};
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const files = e.target.files;
if (files && files.length > 0) {
@@ -2,7 +2,6 @@ import React, { useState, useRef, useEffect } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faMousePointer,
faTrash,
faEyeDropper,
faImage,
faUndo,
@@ -1,4 +1,3 @@
import { Vector2d } from "konva/lib/types";
import { useEffect } from "react";
import { DragState } from "../types";
// This piece of code ensures that when you are selecting or dragging and go off the stage,
@@ -210,7 +210,7 @@ export const ControlPanelSceneObject = () => {
// document mouseup/keydown listeners can interact poorly with the
// freecam pointer-capture and canvas keydown handlers).
useEffect(() => {
if (!isShowing) return;
if (!isShowing) return undefined;
const flush = () => {
transformSessionRef.current?.commit();
transformSessionRef.current = null;
@@ -151,14 +151,12 @@ export const Outliner = () => {
}
}
if (viewport.width < 2000) {
if (camAspect === CameraAspectRatio.VERTICAL_9_16) {
return `${editorHeight * 0.7 - 10}px`;
} else if (camAspect === CameraAspectRatio.SQUARE_1_1) {
return `${editorHeight * 0.7}px`;
} else {
return `${editorHeight * 0.7}px`;
}
if (camAspect === CameraAspectRatio.VERTICAL_9_16) {
return `${editorHeight * 0.7 - 10}px`;
} else if (camAspect === CameraAspectRatio.SQUARE_1_1) {
return `${editorHeight * 0.7}px`;
} else {
return `${editorHeight * 0.7}px`;
}
};
@@ -59,7 +59,7 @@ export const EngineProvider = ({
// available; callback refs in SceneContainer / EditorCanvas /
// CameraViewCanvas drive this by setting their nodes (and clearing
// them to null on unmount).
if (!sceneContainer || !editorCanvas || !camViewCanvas) return;
if (!sceneContainer || !editorCanvas || !camViewCanvas) return undefined;
const newEditor = new Editor(adapterRef.current);
newEditor.initialize({
@@ -153,29 +153,35 @@ function removeObject3D(object3D) {
obj.traverse(child => {
(child as THREE.Mesh)?.geometry?.dispose()
if (Array.isArray((child as THREE.Mesh).texture)) {
(child as THREE.Mesh).texture.forEach(mat => mat.dispose());
} else if ((child as THREE.Mesh).texture) {
(child as THREE.Mesh).texture.dispose();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const childTexture = (child as any).texture;
if (Array.isArray(childTexture)) {
childTexture.forEach(mat => mat.dispose());
} else if (childTexture) {
childTexture.dispose();
}
if (Array.isArray((child as THREE.Mesh).material)) {
(child as THREE.Mesh).material.forEach(mat => mat.dispose());
} else if ((child as THREE.Mesh).material) {
(child as THREE.Mesh).material.dispose();
const childMaterial = (child as THREE.Mesh).material;
if (Array.isArray(childMaterial)) {
childMaterial.forEach(mat => mat.dispose());
} else if (childMaterial) {
childMaterial.dispose();
}
})
if (Array.isArray((obj as THREE.Mesh).texture)) {
(obj as THREE.Mesh).texture.forEach(mat => mat.dispose());
} else if ((obj as THREE.Mesh).texture) {
(obj as THREE.Mesh).texture.dispose();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const objTexture = (obj as any).texture;
if (Array.isArray(objTexture)) {
objTexture.forEach(mat => mat.dispose());
} else if (objTexture) {
objTexture.dispose();
}
if (Array.isArray((obj as THREE.Mesh).material)) {
(obj as THREE.Mesh).material.forEach(mat => mat.dispose());
} else if ((obj as THREE.Mesh).material) {
(obj as THREE.Mesh).material.dispose();
const objMaterial = (obj as THREE.Mesh).material;
if (Array.isArray(objMaterial)) {
objMaterial.forEach(mat => mat.dispose());
} else if (objMaterial) {
objMaterial.dispose();
}
if ((obj as THREE.Mesh).geometry) {
@@ -399,7 +399,8 @@ export class MouseControls {
event.preventDefault();
this.isProcessing = true;
try {
await this.sceneManager?.undo();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await (this.sceneManager as any)?.undo();
} finally {
this.isProcessing = false;
}
@@ -408,7 +409,8 @@ export class MouseControls {
event.preventDefault();
this.isProcessing = true;
try {
await this.sceneManager?.redo();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await (this.sceneManager as any)?.redo();
} finally {
this.isProcessing = false;
}
@@ -417,7 +419,8 @@ export class MouseControls {
event.preventDefault();
this.isProcessing = true;
try {
await this.sceneManager?.redo();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
await (this.sceneManager as any)?.redo();
} finally {
this.isProcessing = false;
}
@@ -372,7 +372,7 @@ class Scene {
);
if (obj_keyframe_uuid === keyframe_uuid) {
keyframe_point = object;
return object;
return;
}
}
});
@@ -611,7 +611,7 @@ class Scene {
async loadObjectFromUrl(
url: string,
position: THREE.Vector3 = new THREE.Vector3(-0.5, 1.5, 0),
): Promise<THREE.Object3D> {
): Promise<THREE.Object3D | undefined> {
console.log("loadObjectFromUrl!!!!!!!!", url);
if (
url.includes(".png") ||
@@ -628,6 +628,7 @@ class Scene {
}
return obj;
}
return undefined;
}
async loadObject(
@@ -910,8 +911,8 @@ class Scene {
media_url: string,
onComplete: () => void,
signal?: AbortSignal,
) {
return new Promise(async (resolve, reject) => {
): Promise<GLTF> {
return new Promise<GLTF>(async (resolve, reject) => {
let buffer;
try {
// Host-supplied CORS-bypassed binary fetch (FetchProxy under
@@ -92,6 +92,7 @@ export class SceneManager implements SceneManagerAPI {
} else {
return this.scene.instantiate(name, position);
}
return undefined;
}
updateSkybox(media_id: string) {
@@ -89,7 +89,7 @@ export const useFreeCam = (
// Hand the state to the editor so its render loop can integrate it.
useEffect(() => {
if (!editor) return;
if (!editor) return undefined;
editor.cameraController.setFreeCamState(stateRef.current);
return () => editor.cameraController.setFreeCamState(null);
}, [editor]);
@@ -98,7 +98,7 @@ export const useFreeCam = (
// inside the viewport); keys on document so the user doesn't need
// to click canvas first for WASD to work.
useEffect(() => {
if (!canvas || !editor) return;
if (!canvas || !editor) return undefined;
const state = stateRef.current;
state.enabled = true;
@@ -44,7 +44,7 @@ export const useViewportKeyboard = (editor: Editor | null) => {
const bindings = useMemo(() => buildKeymap(), []);
useEffect(() => {
if (!editor) return;
if (!editor) return undefined;
const onKeyDown = (event: KeyboardEvent) => {
if (isEventFromEditableElement(event)) return;
@@ -25,7 +25,7 @@ export const useViewportPointer = (
);
useEffect(() => {
if (!canvas || !editor) return;
if (!canvas || !editor) return undefined;
const onPointerMove = (e: PointerEvent) => {
if (!editor.mouse) return;
@@ -18,7 +18,7 @@ export const useViewportSize = (): { width: number; height: number } => {
);
useEffect(() => {
if (typeof window === "undefined") return;
if (typeof window === "undefined") return undefined;
const onResize = () => {
setSize(
adapterGet?.() ?? {
@@ -22,6 +22,10 @@ export interface ObjectJSON {
object_uuid: string;
object_user_data_name: string;
media_file_token: string;
// Legacy top-level field. Not written by toJSON() (the value is
// carried inside user_data.media_file_type); kept optional so reads
// that reference it directly type-check without changing behavior.
media_file_type?: MediaFileType;
color: string;
metalness: number;
shininess: number;
@@ -96,7 +96,6 @@ export function CostBreakdownModal({ activeTabId }: CostBreakdownModalProps) {
const {
currency,
setCurrency,
currencyOption,
formatPrice,
currencyOptions,
} = useCurrency();
@@ -547,7 +547,7 @@ export const PromptBox3D = ({
};
const getCurrentAspectRatio = (): CommonAspectRatio => {
switch (cameraAspectRatio.value) {
switch (cameraAspectRatio) {
case CameraAspectRatio.HORIZONTAL_3_2:
return CommonAspectRatio.Wide;
case CameraAspectRatio.VERTICAL_2_3:
@@ -5,8 +5,6 @@ import {
} from "@fortawesome/pro-regular-svg-icons";
import {
faEdit,
faMessageCheck,
faMessageXmark,
faMousePointer,
faFrame,
faPen,
@@ -19,7 +17,7 @@ import {
faChevronUp,
} from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Button, ToggleButton, GenerateButton } from "@storyteller/ui-button";
import { Button, GenerateButton } from "@storyteller/ui-button";
import { ButtonIconSelect } from "@storyteller/ui-button-icon-select";
import { PopoverMenu, PopoverItem } from "@storyteller/ui-popover";
import { Tooltip } from "@storyteller/ui-tooltip";
@@ -83,7 +81,6 @@ export const PromptBoxEdit = ({
credits,
}: PromptBoxEditProps) => {
const [prompt, setPrompt] = useState("");
const [useSystemPrompt, setUseSystemPrompt] = useState(true);
const [isFocused, setIsFocused] = useState(false);
const [isExpanded, setIsExpanded] = useState(false);
@@ -11,17 +11,17 @@ interface State {
}
export class PromptBoxErrorBoundary extends Component<Props, State> {
state: State = { hasError: false, resetKey: 0 };
override state: State = { hasError: false, resetKey: 0 };
static getDerivedStateFromError(): Partial<State> {
return { hasError: true };
}
componentDidCatch(error: Error, info: ErrorInfo) {
override componentDidCatch(error: Error, info: ErrorInfo) {
console.error("PromptBox crashed:", error, info.componentStack);
}
render() {
override render() {
if (this.state.hasError) {
return (
<div className="flex items-center justify-center rounded-xl border border-red-500/30 bg-red-500/10 px-6 py-4 text-sm text-red-300">
@@ -4,18 +4,16 @@ import { JobContextType, UploaderState } from "@storyteller/common";
import { toast } from "@storyteller/ui-toaster";
import { PopoverMenu, PopoverItem } from "@storyteller/ui-popover";
import { Tooltip } from "@storyteller/ui-tooltip";
import { Button, ToggleButton, GenerateButton } from "@storyteller/ui-button";
import { Button, GenerateButton } from "@storyteller/ui-button";
import { Modal } from "@storyteller/ui-modal";
import { GenerateImage, GenerateImageRequest } from "@storyteller/tauri-api";
import {
faMessageXmark,
faMessageCheck,
faExpand,
faChevronDown,
faChevronUp,
} from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { CommonAspectRatio, ImageModel } from "@storyteller/model-list";
import { ImageModel } from "@storyteller/model-list";
import {
usePromptImageStore,
RefImage,
@@ -30,7 +28,6 @@ import { AspectRatioIcon } from "./common/AspectRatioIcon";
import { GenerationCountPicker } from "./common/GenerationCountPicker";
import { ResolutionPicker } from "./common/ResolutionPicker";
import { QualityPicker } from "./common/QualityPicker";
import { CommonResolution } from "@storyteller/model-list";
interface PromptBoxImageProps {
useJobContext: () => JobContextType;
@@ -96,8 +93,6 @@ export const PromptBoxImage = ({
const prompt = usePromptImageStore((s) => s.prompt);
const setPrompt = usePromptImageStore((s) => s.setPrompt);
const useSystemPrompt = usePromptImageStore((s) => s.useSystemPrompt);
const setUseSystemPrompt = usePromptImageStore((s) => s.setUseSystemPrompt);
const aspectRatio = usePromptImageStore((s) => s.aspectRatio);
const setAspectRatio = usePromptImageStore((s) => s.setAspectRatio);
const resolution = usePromptImageStore((s) => s.resolution);
@@ -274,7 +274,7 @@ export const PromptBoxVideo = ({
aspectRatioOptions = buildAspectRatioOptions(DEFAULT_RESOLUTIONS);
}
const [aspectRatioList, setAspectRatioList] =
const [, setAspectRatioList] =
useState<PopoverItem[]>(aspectRatioOptions);
const textareaRef = useRef<HTMLTextAreaElement>(null);
@@ -349,8 +349,8 @@ export const UploadFiles3D = ({
{selectionError && <h6 className="z-10 text-red">{selectionError}</h6>}
{isMulti ? (
<PanelGroup orientation="horizontal">
<Panel defaultSize="33%" minSize="20%">
<PanelGroup direction="horizontal">
<Panel defaultSize={33} minSize={20}>
<ul className="flex h-full flex-col gap-1 overflow-y-auto rounded-lg bg-brand-secondary p-2">
{fileEntries.map((entry, i) => (
<li
@@ -412,11 +412,14 @@ export const UploadFiles3D = ({
</ul>
</Panel>
<PanelResizeHandle className="flex w-4 items-center justify-center" onPointerDown={(e) => e.stopPropagation()}>
<div className="h-8 w-1 rounded-full bg-white/20 transition-colors hover:bg-white/40" />
<PanelResizeHandle className="flex w-4 items-center justify-center">
<div
className="h-8 w-1 rounded-full bg-white/20 transition-colors hover:bg-white/40"
onPointerDown={(e) => e.stopPropagation()}
/>
</PanelResizeHandle>
<Panel defaultSize="67%" minSize="25%">
<Panel defaultSize={67} minSize={25}>
<div className="flex h-full flex-col gap-2">
<div className="relative w-full min-h-48 overflow-hidden rounded-lg bg-brand-secondary">
<canvas
@@ -211,8 +211,8 @@ export const UploadFilesImage = ({
{fileEntries.length > 0 && (
isMulti ? (
<PanelGroup orientation="horizontal">
<Panel defaultSize="33%" minSize="20%">
<PanelGroup direction="horizontal">
<Panel defaultSize={33} minSize={20}>
<ul className="flex h-full flex-col gap-1 overflow-y-auto rounded-lg bg-brand-secondary p-2">
{fileEntries.map((entry, i) => (
<li
@@ -274,11 +274,14 @@ export const UploadFilesImage = ({
</ul>
</Panel>
<PanelResizeHandle className="flex w-4 items-center justify-center" onPointerDown={(e) => e.stopPropagation()}>
<div className="h-8 w-1 rounded-full bg-white/20 transition-colors hover:bg-white/40" />
<PanelResizeHandle className="flex w-4 items-center justify-center">
<div
className="h-8 w-1 rounded-full bg-white/20 transition-colors hover:bg-white/40"
onPointerDown={(e) => e.stopPropagation()}
/>
</PanelResizeHandle>
<Panel defaultSize="67%" minSize="25%">
<Panel defaultSize={67} minSize={25}>
<div className="flex h-full flex-col gap-2">
<div className="relative aspect-square w-full overflow-hidden rounded-lg bg-brand-secondary flex items-center justify-center">
{previewUrl && (
@@ -339,8 +339,8 @@ export const UploadFilesSplat = ({
)}
{isMulti ? (
<PanelGroup orientation="horizontal">
<Panel defaultSize="33%" minSize="20%">
<PanelGroup direction="horizontal">
<Panel defaultSize={33} minSize={20}>
<ul className="flex h-full flex-col gap-1 overflow-y-auto rounded-lg bg-brand-secondary p-2">
{fileEntries.map((entry, i) => (
<li
@@ -399,11 +399,14 @@ export const UploadFilesSplat = ({
</ul>
</Panel>
<PanelResizeHandle className="flex w-4 items-center justify-center" onPointerDown={(e) => e.stopPropagation()}>
<div className="h-8 w-1 rounded-full bg-white/20 transition-colors hover:bg-white/40" />
<PanelResizeHandle className="flex w-4 items-center justify-center">
<div
className="h-8 w-1 rounded-full bg-white/20 transition-colors hover:bg-white/40"
onPointerDown={(e) => e.stopPropagation()}
/>
</PanelResizeHandle>
<Panel defaultSize="67%" minSize="25%">
<Panel defaultSize={67} minSize={25}>
<div className="flex h-full flex-col gap-2">
<div className="relative w-full min-h-48 overflow-hidden rounded-lg bg-brand-secondary">
<canvas
@@ -1,4 +1,4 @@
export * from './lib/subscription-plan-details';
export * from './lib/subscription-plans';
export * from './lib/subscription-state';
export * from './lib/subscription-plan-details.js';
export * from './lib/subscription-plans.js';
export * from './lib/subscription-state.js';