2d signal fixes

This commit is contained in:
bflatastic committed 2025-05-09 21:36:37 +07:00
1 parent 67d280df84
commit 18ac503f54
12 files changed
+180 -131

No files matched your search

@@ -9,6 +9,8 @@ export const KonvaCanvasContainer = forwardRef<
>(({ className, ...props }, ref) => {
// useRenderCounter("KonvaCanvasContainer");
const classes = twMerge("pegboard -z-10", className);
const classes = twMerge("pegboard -z-10", "h-[calc(100vh-56px)]", className);
return <div ref={ref} className={classes} {...props} />;
});
KonvaCanvasContainer.displayName = "KonvaCanvasContainer";
@@ -4,7 +4,7 @@ import { useCallback, useRef, useState } from "react";
import { KonvaCanvasContainer } from "./KonvaCanvasContainer";
import { ContextualToolbarNode } from "./ContextualToolbarNode";
// import { SignaledCanvasDragDropFiles } from "./SignaledCanvasDragDropFiles";
import { SignaledDialogs } from "./SignaledDialogs";
// import { SignaledDialogs } from "./SignaledDialogs";
import { SignaledToolbarMain } from "./SignaledToolbarMain";
// The KonvaApp is the root of the Konva stage
@@ -33,7 +33,17 @@ import { uploadImage } from "../../components/reusable/UploadModalMedia/uploadIm
// import { EncodeImageBitmapToBase64 } from "./utilities/EncodeImageBitmapToBase64";
import { JobProvider, useJobContext } from "./JobContext";
import { RealTimeDrawEngine } from "./KonvaApp/RenderingPrimitives/RealTimeDrawEngine";
import { VideoResolutions } from "./KonvaApp/constants";
// import { VideoResolutions } from "./KonvaApp/constants";
import {
DialogAddImage,
DialogEditText,
DialogError,
} from "./components/features";
import { dispatchUiEvents } from "./signals";
import { useSignals } from "@preact/signals-react/runtime";
import { dialogError } from "./signals/uiAccess/dialogError";
export const KonvaRootComponent = ({
className,
sceneToken,
@@ -41,6 +51,7 @@ export const KonvaRootComponent = ({
className: string;
sceneToken?: string;
}) => {
useSignals();
// This is a hook that will log the number of times the component has rerendered
// Let's make sure we only log once
useRenderCounter("KonvaRootComponent");
@@ -53,29 +64,38 @@ export const KonvaRootComponent = ({
const engineRef = useRef<EngineType | null>(null);
const renderEngineRef = useRef<RealTimeDrawEngine | null>(null);
const konvaContainerCallbackRef = useCallback((node: HTMLDivElement) => {
// Only initialize if we have a node and haven't initialized yet
if (node !== null && !isEngineReady && engineRef.current === null) {
try {
const options = {
navigate: navigate,
sceneToken: sceneToken,
};
const konvaContainerCallbackRef = useCallback(
(node: HTMLDivElement) => {
// Only initialize if we have a node and haven't initialized yet
if (node !== null && !isEngineReady && engineRef.current === null) {
try {
const options = {
navigate: navigate,
sceneToken: sceneToken,
};
engineRef.current = KonvaApp(node, options);
renderEngineRef.current = engineRef.current.realTimeDrawEngine;
// Only set ready if initialization succeeded
if (engineRef.current) {
setIsEngineReady(true);
engineRef.current = KonvaApp(node, options);
renderEngineRef.current = engineRef.current.realTimeDrawEngine;
// Only set ready if initialization succeeded
if (engineRef.current) {
setIsEngineReady(true);
}
} catch (error) {
console.error("Failed to initialize KonvaApp:", error);
engineRef.current = null;
setIsEngineReady(false);
}
} catch (error) {
console.error("Failed to initialize KonvaApp:", error);
engineRef.current = null;
setIsEngineReady(false);
}
}
}, [navigate, sceneToken, isEngineReady]);
},
[navigate, sceneToken, isEngineReady],
);
// Modal stuff
const props = dialogError.signal.value;
const { isShowing, title, message } = props;
const onClose = useCallback(() => {
dialogError.hide();
}, []);
return (
<>
@@ -95,7 +115,6 @@ export const KonvaRootComponent = ({
{/* Conditionally render the UI components that need the engine */}
{isEngineReady && engineRef.current && (
<UndoRedo engine={engineRef.current}>
{/* <SignaledCanvasDragDropFiles
openAddImage={appUiContext.openAddImage}
openAddVideo={appUiContext.openAddVideo}
@@ -104,25 +123,52 @@ export const KonvaRootComponent = ({
<PromptBox2D
uploadImage={uploadImage}
getCanvasRenderBitmap={getCanvasRenderBitmap}
EncodeImageBitmapToBase64={EncodeImageBitmapToBase64}
useJobContext={useJobContext}
onEnqueuePressed={async ()=> {
// will set the snapshot of the canvas internally.
await renderEngineRef.current?.render();
}}
/> </JobProvider>
EncodeImageBitmapToBase64={EncodeImageBitmapToBase64}
useJobContext={useJobContext}
onEnqueuePressed={async () => {
// will set the snapshot of the canvas internally.
await renderEngineRef.current?.render();
}}
/>{" "}
</JobProvider>
<SignaledToolbarMain
layoutSignal={layoutContext.signal}
appUiContext={appUiContext}
/>
<SignaledDialogs
{/* <SignaledDialogs
appUiSignal={appUiContext.signal}
resetAll={appUiContext.resetAll}
/>
/> */}
<ContextualToolbarNode />
</UndoRedo>
)}
{/* Modals */}
<DialogEditText
isOpen={appUiContext.signal.value.isEditTextOpen}
onDoneEditText={(data) => {
dispatchUiEvents.addTextToEngine(data);
}}
closeCallback={appUiContext.resetAll}
/>
<DialogAddImage
isOpen={appUiContext.signal.value.isAddImageOpen}
stagedImage={appUiContext.signal.value.stagedImage}
closeCallback={appUiContext.resetAll}
onAddImage={(file) => {
dispatchUiEvents.addImageToEngine(file);
}}
/>
<DialogError
isShowing={isShowing}
title={title}
message={message}
onClose={onClose}
/>
</>
);
};
@@ -6,11 +6,9 @@ import {
DialogEditText,
DialogError,
} from "./components/features";
import { AppUiSignalType } from "./contextSignals/appUi";
import { dialogError } from "./signals/uiAccess/dialogError";
export const SignaledDialogs = ({
appUiSignal,
resetAll,
@@ -13,6 +13,7 @@ import { AppUiContextInterface } from "./contextSignals/appUi";
import { twMerge } from "tailwind-merge";
import { paperWrapperStyles } from "./components/styles";
import { dispatchUiEvents } from "./signals/uiEvents";
import { useSignals } from "@preact/signals-react/runtime";
export const SignaledToolbarMain = ({
// layoutSignal,
@@ -21,7 +22,7 @@ export const SignaledToolbarMain = ({
layoutSignal: LayoutSignalType;
appUiContext: AppUiContextInterface;
}) => {
useSignals();
const loadingBar = toolbarMain.loadingBar.signal.value;
const getButtonDispatcher = (buttonName: ToolbarMainButtonNames) => {
switch (buttonName) {
@@ -6,8 +6,7 @@ import { FileUploader } from "../../../components/reusable/FileUploader";
import { Button } from "@storyteller/ui-button";
import { IMAGE_FILE_TYPE } from "../../../constants/fileTypeEnums";
import { BaseDialog } from "../../../components/ui/BaseDialog";
import { Modal } from "@storyteller/ui-modal";
export const DialogAddImage = ({
stagedImage = null,
@@ -39,38 +38,40 @@ export const DialogAddImage = ({
}
return (
<BaseDialog isOpen={isOpen} onClose={closeCallback}>
<DialogTitle className="text-3xl font-bold">Upload Image</DialogTitle>
<div className="flex flex-col rounded-lg border-2 border-dashed border-ui-border">
<FileUploader
title=""
fileTypes={Object.values(IMAGE_FILE_TYPE)}
file={currFile}
setFile={(file: File | null) => {
setAssetFile(file);
if (file) {
onAddImage(file);
handleClose();
}
}}
/>
{currFile && (
<div
className="relative flex items-center justify-center bg-ui-border"
style={{ height: "calc(100vh - 500px)" }}
>
<img
src={URL.createObjectURL(currFile)}
className="max-h-full object-contain"
/>
</div>
)}
<Modal isOpen={isOpen} onClose={closeCallback}>
<div className="flex flex-col gap-3">
<DialogTitle className="text-3xl font-bold">Upload Image</DialogTitle>
<div className="border-ui-border flex flex-col rounded-lg border-2 border-dashed">
<FileUploader
fileTypes={Object.values(IMAGE_FILE_TYPE)}
file={currFile}
setFile={(file: File | null) => {
setAssetFile(file);
if (file) {
onAddImage(file);
handleClose();
}
}}
/>
{currFile && (
<div
className="bg-ui-border relative flex items-center justify-center"
style={{ height: "calc(100vh - 500px)" }}
>
<img
src={URL.createObjectURL(currFile)}
className="max-h-full object-contain"
alt="upload img"
/>
</div>
)}
</div>
<div className="flex w-full justify-end gap-2">
<Button onClick={handleClose} variant="secondary">
Cancel
</Button>
</div>
</div>
<div className="flex w-full justify-end gap-2">
<Button onClick={handleClose} variant="secondary">
Cancel
</Button>
</div>
</BaseDialog>
</Modal>
);
};
@@ -31,14 +31,12 @@ export type TextNodeData = {
text: string;
} & TextFormatData;
import { useState } from "react";
import { DialogTitle } from "@headlessui/react";
import { Button, TextEditor } from "../../../components/ui";
import { BaseDialog } from "../../../components/ui/BaseDialog";
import { Modal } from "@storyteller/ui-modal";
export const DialogEditText = ({
isOpen,
@@ -92,26 +90,28 @@ export const DialogEditText = ({
closeCallback();
};
return (
<BaseDialog isOpen={isOpen} onClose={closeCallback} className="w-fit">
<DialogTitle className="text-2xl font-bold">Edit Text</DialogTitle>
<TextEditor
text={text}
formatData={textFormatData}
onChangeText={handleOnChangeText}
onChangeFormatting={handleOnChangeFormatting}
/>
<div className="flex w-full justify-end gap-2">
<Button onClick={closeCallback} variant="secondary">
Cancel
</Button>
<Button
className="hover:animate-pulse"
onClick={handleOnDoneEditText}
disabled={text === ""}
>
Enter
</Button>
<Modal isOpen={isOpen} onClose={closeCallback} className="w-fit max-w-2xl">
<div className="flex flex-col gap-3">
<DialogTitle className="text-2xl font-bold">Edit Text</DialogTitle>
<TextEditor
text={text}
formatData={textFormatData}
onChangeText={handleOnChangeText}
onChangeFormatting={handleOnChangeFormatting}
/>
<div className="flex w-full justify-end gap-2">
<Button onClick={closeCallback} variant="secondary">
Cancel
</Button>
<Button
className="hover:animate-pulse"
onClick={handleOnDoneEditText}
disabled={text === ""}
>
Enter
</Button>
</div>
</div>
</BaseDialog>
</Modal>
);
};
@@ -2,10 +2,8 @@ import {
faArrowRotateLeft,
faArrowRotateRight,
faCircle,
faEraser,
faFilePlus,
faImage,
faImages,
faLocationArrow,
faPaintbrush,
faShapes,
@@ -19,18 +17,18 @@ import { Fragment, MouseEventHandler } from "react";
import { twMerge } from "tailwind-merge";
import { ToolbarButton } from "../../../components/features/ToolbarButton";
import { Tooltip } from "~/components/ui/Tooltip";
// import { Tooltip } from "~/components/ui/Tooltip";
// style and constants
import { paperWrapperStyles, toolTipStyles } from "../../../components/styles";
import { ToolbarMainButtonNames } from "./enum";
import { dispatchUiEvents, uiEvents } from "../../../signals/uiEvents";
import { dispatchUiEvents } from "../../../signals/uiEvents";
import { paintColor } from "../../../signals/uiEvents/toolbarMain/paintMode";
import { ColorPicker } from "../../../components/ui/TextEditor/ColorPicker";
// import { ColorPicker } from "../../../components/ui/TextEditor/ColorPicker";
import { PaintModeMenu } from "../../../components/ui/ToolbarMain/PaintModeMenu";
import { EraseModeMenu } from "../../../components/ui/ToolbarMain/EraseModeMenu";
import { BackgroundMenu } from "../../../components/ui/ToolbarMain/BackgroundMenu";
import { bgColor } from "../../../signals/uiEvents/toolbarMain/backgroundMenu";
// import { EraseModeMenu } from "../../../components/ui/ToolbarMain/EraseModeMenu";
// import { BackgroundMenu } from "../../../components/ui/ToolbarMain/BackgroundMenu";
// import { bgColor } from "../../../signals/uiEvents/toolbarMain/backgroundMenu";
export const ToolbarMain = ({
disabled = false,
@@ -53,7 +51,7 @@ export const ToolbarMain = ({
paperWrapperStyles,
"glass",
disabled &&
"pointer-events-none cursor-default bg-ui-border shadow-md",
"bg-ui-border pointer-events-none cursor-default shadow-md",
)}
>
<div className="flex flex-col items-center gap-2">
@@ -234,11 +232,11 @@ export const ToolbarMain = ({
/> */}
</div>
<hr className="w-full border-t border-white/15" />
{/* <hr className="w-full border-t border-white/15" />
<div className="flex flex-col items-center gap-2">
<div className="relative">
{/* <Tooltip tip="Background Color" position="right">
<Tooltip tip="Background Color" position="right">
<div>
<BackgroundMenu
color={bgColor.value}
@@ -258,9 +256,9 @@ export const ToolbarMain = ({
style={{ backgroundColor: bgColor.value }}
/>
</div>
</Tooltip> */}
</Tooltip>
</div>
</div>
</div> */}
</div>
</>
);
@@ -1,7 +1,7 @@
import { twMerge } from "tailwind-merge";
export const paperWrapperStyles =
"rounded-xl border border-ui-border p-1.5 shadow-lg bg-ui-panel";
"rounded-xl border border-ui-panel-border p-1.5 shadow-lg bg-ui-background";
export const transitionTimingStyles = "transition duration-150 ease-in-out";
@@ -29,7 +29,7 @@ export const Combobox = ({ options, value, onChange }: ComboBoxInterface) => {
onChange={onChange}
onClose={() => setQuery("")}
>
<div className="relative flex h-10 rounded-md border border-ui-border">
<div className="relative flex h-10 rounded-lg border border-ui-panel-border">
<ComboboxInput
className="rounded-lg px-3"
displayValue={(font: string) => font}
@@ -41,7 +41,7 @@ export const Combobox = ({ options, value, onChange }: ComboBoxInterface) => {
</div>
<ComboboxOptions
anchor="bottom"
className="mt-1 w-[var(--input-width)] rounded-lg border border-ui-border empty:invisible"
className="mt-1 w-[var(--input-width)] rounded-lg border border-ui-panel-border empty:invisible"
>
{filteredOptions.map((option, idx) => (
<ComboboxOption
@@ -1,4 +1,4 @@
export const buttonGroupButton =
"size-10 rounded-none bg-ui-controls text-white/80 hover:bg-white/30 data-[selected=true]:text-white data-[selected=true]:bg-primary/30 disabled:hover:bg-transparent disabled:text-gray-400 border border-ui-border";
"size-10 rounded-none bg-ui-controls text-white/80 hover:bg-white/30 data-[selected=true]:text-white data-[selected=true]:bg-primary/30 disabled:hover:bg-transparent disabled:text-gray-400";
export const buttonGroupGrouper =
"flex divide-x overflow-hidden rounded-md border border-ui-border";
"flex divide-x divide-ui-panel-border overflow-hidden rounded-md border border-ui-panel-border";
@@ -53,7 +53,9 @@ export const toolbarMain = {
this.changeButtonState(ToolbarMainButtonNames.ERASER, { active: false });
this.changeButtonState(ToolbarMainButtonNames.PAINT, { active: false });
this.changeButtonState(mode, { active: true });
}
console.log("setMode", mode);
},
};
function initButtonStates() {
@@ -345,24 +345,6 @@ export const PageEditor = () => {
</div>
</div>
</div>
<LoginModal
onClose={() => {}}
videoSrc2D="/resources/videos/artcraft-canvas-demo.mp4"
videoSrc3D="/resources/videos/artcraft-3d-demo.mp4"
openAiLogo="/resources/images/openai-logo.png"
onOpenChange={(isOpen: boolean) => {
if (isOpen) {
disableHotkeyInput(DomLevels.DIALOGUE);
} else {
enableHotkeyInput(DomLevels.DIALOGUE);
}
}}
onArtCraftAuthSuccess={(userInfo: any) => {
authentication.status.value = AUTH_STATUS.LOGGED_IN;
authentication.userInfo.value = userInfo;
}}
/>
</>
);
};
@@ -382,7 +364,26 @@ export const PageEditor = () => {
appTabIdSignal={appTabId}
setAppTabId={setAppTabId}
/>
{appTabId.value === "3D" ? <ContentFor3D /> : <ContentFor2D />}
<LoginModal
onClose={() => {}}
videoSrc2D="/resources/videos/artcraft-canvas-demo.mp4"
videoSrc3D="/resources/videos/artcraft-3d-demo.mp4"
openAiLogo="/resources/images/openai-logo.png"
onOpenChange={(isOpen: boolean) => {
if (isOpen) {
disableHotkeyInput(DomLevels.DIALOGUE);
} else {
enableHotkeyInput(DomLevels.DIALOGUE);
}
}}
onArtCraftAuthSuccess={(userInfo: any) => {
authentication.status.value = AUTH_STATUS.LOGGED_IN;
authentication.userInfo.value = userInfo;
}}
/>
</div>
);
};