Compare commits

...
8 changed files with 139 additions and 14 deletions
-10
View File
@@ -4525,8 +4525,6 @@
},
"node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"inBundle": true,
"license": "MIT",
@@ -5267,8 +5265,6 @@
},
"node_modules/npm/node_modules/cross-spawn/node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -5317,8 +5313,6 @@
},
"node_modules/npm/node_modules/debug/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true,
"inBundle": true,
"license": "MIT"
@@ -7145,8 +7139,6 @@
},
"node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"inBundle": true,
"license": "MIT",
@@ -7184,8 +7176,6 @@
},
"node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"inBundle": true,
"license": "MIT",
@@ -3,8 +3,10 @@ import { Container } from "konva/lib/Container";
import { Shape } from "konva/lib/Shape";
import { Group } from "konva/lib/Group";
import { invoke } from "@tauri-apps/api/core";
import { FileUtilities } from "../FileUtilities/FileUtilities";
import { ImageNode, VideoNode, TextNode } from "../Nodes";
import { MediaNode } from "../types";
@@ -266,6 +268,7 @@ export class RealTimeDrawEngine {
});
return canvas;
}
public isProcessing = false;
private handleNodeDragEnd = async () => {
// Clean up any existing state
@@ -376,6 +379,8 @@ export class RealTimeDrawEngine {
}
}
private async imageBitmapToBase64(imageBitmap: ImageBitmap): Promise<string> {
// Create a temporary canvas
const canvas = document.createElement("canvas");
@@ -23,6 +23,8 @@ import { useLayoutContext } from "./contextSignals/layout";
import { useRenderCounter } from "~/hooks/useRenderCounter";
import { useNavigate } from "react-router-dom";
import { SignaledMagicBox } from "./SignaledMagicBox";
import { SignaledPromptSlider } from "./SignaledPromptSlider";
import { SignaledPromptText } from "./SignaledPromptText";
export const KonvaRootComponent = ({
className,
@@ -54,13 +56,15 @@ export const KonvaRootComponent = ({
<KonvaCanvasContainer
ref={konvaContainerCallbackRef}
className={className}
// retreive the classNames from the parent for sizing/styling
// retreive the classNames from the parent for sizing/styling
/>
<SignaledMagicBox />
<SignaledCanvasDragDropFiles
openAddImage={appUiContext.openAddImage}
openAddVideo={appUiContext.openAddVideo}
/>
<SignaledPromptSlider />
<SignaledPromptText />
<SignaledToolbarMain
layoutSignal={layoutContext.signal}
appUiContext={appUiContext}
@@ -0,0 +1,22 @@
import { useSignalEffect } from "@preact/signals-react";
import { Slider } from "~/components/ui"
import { dispatchUiEvents } from "~/signals"
import { promptStrength } from "~/signals/uiEvents/promptSettings";
export const SignaledPromptSlider = () => {
const sliderValue = promptStrength.value
const onSliderValueChanged = dispatchUiEvents.promptSettings.setPromptStrength
// This makes component re-render whenever the signal value changes
useSignalEffect(() => {
promptStrength.value;
})
return (
<div className="fixed bottom-96 left-1/2 -translate-x-1/2 h-4 w-48">
<Slider min={0} max={100} value={sliderValue} onChange={onSliderValueChanged} step={1} />
</div>
)
}
@@ -0,0 +1,45 @@
import { useSignalEffect } from "@preact/signals-react";
import { useCallback, useEffect, useRef } from "react";
import { ResizeType, Textarea } from "~/components/ui";
import { dispatchUiEvents } from "~/signals";
import { promptText } from "~/signals/uiEvents/promptSettings";
export const SignaledPromptText = ({
}) => {
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const focusOnTextArea = useCallback(() => {
if (textAreaRef.current === null) {
return;
}
textAreaRef.current.focus();
}, []);
useEffect(() => {
focusOnTextArea();
}, []);
const TextAreaStates = {
style: {
width: "500px",
height: "240px",
},
placeholder: "...",
label: "Prompt Text",
resize: "none" as ResizeType,
};
const textContent = promptText.value;
const onTextChanged = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
dispatchUiEvents.promptSettings.setPrompt(event.target.value);
};
// This makes component re-render whenever the signal value changes
useSignalEffect(() => {
promptText.value;
})
return (
<div className="fixed bottom-24 left-1/2 -translate-x-1/2">
<Textarea {...TextAreaStates} ref={textAreaRef} onChange={onTextChanged} value={textContent} />
</div>
);
};
@@ -7,10 +7,16 @@ export type ResizeType =
| "both"
| "horizontal"
| "vertical"
| "block"
| "inline"
| undefined;
const resizeStyles = {
none: "resize-none",
both: "resize",
horizontal: "resize-x",
vertical: "resize-y",
undefined: "",
}
export interface TextareaInterface
extends TextareaHTMLAttributes<HTMLTextAreaElement> {
label?: string;
@@ -21,6 +27,9 @@ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaInterface>(
{ className, label, resize = "vertical", id, ...rest }: TextareaInterface,
ref,
) => {
const resizeStyle = resizeStyles[resize];
return (
<div className="flex flex-col">
{label && <label htmlFor={id ? id : kebabCase(label)}>{label}</label>}
@@ -31,11 +40,11 @@ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaInterface>(
className={twMerge(
"border-ui-panel-border bg-ui-controls rounded-lg border px-3 py-2",
className,
resizeStyle,
)}
style={{
outline: "2px solid transparent",
transition: "outline-color 0.15s ease-in-out",
resize: resize,
}}
onFocus={(e) => {
// disableHotkeyInput(DomLevels.INPUT);
@@ -24,6 +24,10 @@ import {
dispatchers as toolbarVideoExtractionDispatchers,
eventsHandlers as toolbarVideoExtractionEvents,
} from "./toolbarVideoExtraction";
import {
dispatchers as promptDispatchers,
events as promptEvents,
} from "./promptSettings";
export const uiEvents = {
...addMediaEvents,
@@ -34,6 +38,7 @@ export const uiEvents = {
toolbarMain: toolbarMainEvents,
toolbarNode: toolbarNodeEvents,
toolbarVideoExtraction: toolbarVideoExtractionEvents,
promptEvents: promptEvents,
};
export const dispatchUiEvents = {
...addMediaDispatchers,
@@ -44,4 +49,5 @@ export const dispatchUiEvents = {
toolbarMain: toolbarMainDispatchers,
toolbarNode: toolbarNodeDispatchers,
toolbarVideoExtraction: toolbarVideoExtractionDispatchers,
promptSettings: promptDispatchers,
};
@@ -0,0 +1,44 @@
import { effect, signal } from "@preact/signals-react";
// Prompt settings
// - Prompt text
// - Prompt strength
export const DEFAULT_PROMPT_TEXT: string = "";
export const promptText = signal<string>(DEFAULT_PROMPT_TEXT);
const setPrompt = (data: string) => {
promptText.value = data;
};
const onPromptTextChanged = (callback: (data: string) => void) => {
effect(() => {
if (promptText.value) {
callback(promptText.value);
}
});
};
export const DEFAULT_PROMPT_STRENGTH = 100;
export const promptStrength = signal<number>(DEFAULT_PROMPT_STRENGTH);
const setPromptStrength = (data: number) => {
// Round to integer, then clamp between 0 and 100
promptStrength.value = Math.max(0, Math.min(100, Math.round(data)));
};
const onPromptStrengthChanged = (callback: (data: number) => void) => {
effect(() => {
if (promptStrength.value) {
callback(promptStrength.value);
}
});
};
//EXPORTS
export const dispatchers = {
setPrompt,
setPromptStrength,
};
export const events = {
onPromptTextChanged,
onPromptStrengthChanged,
};