toolbar main hooked up

This commit is contained in:
wil committed 2024-09-09 14:03:58 -04:00
1 parent 63f13d1e99
commit d1f803783b
15 files changed
+247 -59

No files matched your search

+5 -3
View File
@@ -46,6 +46,10 @@ export class Engine {
uiEvents.imageToolbar.MOVE.onClick(() => {
console.log("move");
});
uiEvents.toolbarMain.SELECT_ONE.onClick(() => {
console.log("select one is clicked");
});
}
sleep(ms: number): Promise<void> {
@@ -101,12 +105,10 @@ export class Engine {
// Testing render engine
this.renderEngine.addNodes(videoNode);
// await this.renderEngine.startProcessing();
// Call this when test video nodes
// await this.renderEngine.startProcessing();
// await this.renderEngine.startProcessing();
//videoNode.simulatedLoading();
// TODO support Text nodes
-26
View File
@@ -1,26 +0,0 @@
import { forwardRef, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
import { useRenderCounter } from "~/hooks/useRenderCounter";
import { ContextualToolbarImage } from "./ContextualToolbarImage";
import { ContextualLoadingBar } from "./ContextualLoadingBar";
import { ToolbarMain, ErrorDialog } from "~/components/features";
export const KonvaContainer = forwardRef<
HTMLDivElement,
HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
useRenderCounter("KonvaContainer");
const classes = twMerge("pegboard -z-10", className);
return (
<>
<div ref={ref} className={classes} {...props} />
<ToolbarMain />
<ContextualToolbarImage />
<ContextualLoadingBar />
<ErrorDialog />
</>
);
});
@@ -0,0 +1,14 @@
import { forwardRef, HTMLAttributes } from "react";
import { twMerge } from "tailwind-merge";
import { useRenderCounter } from "~/hooks/useRenderCounter";
export const KonvaCanvasContainer = forwardRef<
HTMLDivElement,
HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
useRenderCounter("KonvaCanvasContainer");
const classes = twMerge("pegboard -z-10", className);
return <div ref={ref} className={classes} {...props} />;
});
@@ -0,0 +1,37 @@
import { useCallback } from "react";
import { useRenderCounter } from "~/hooks/useRenderCounter";
import { KonvaCanvasContainer } from "./KonvaCanvasContainer";
import { ContextualToolbarImage } from "./ContextualToolbarImage";
import { ContextualLoadingBar } from "./ContextualLoadingBar";
import { SignaledToolbarMain } from "./SignaledToolbarMain";
import { ErrorDialog } from "~/components/features";
// The KonvaApp is the root of the Konva stage
// and only entry point for anything in Konva JS
import { KonvaApp } from "~/KonvaApp";
export const KonvaRootComponent = ({ className }: { className: string }) => {
// 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");
const konvaContainerCallbackRef = useCallback((node: HTMLDivElement) => {
if (node !== null) {
KonvaApp(node);
}
}, []);
return (
<>
<KonvaCanvasContainer
ref={konvaContainerCallbackRef}
className={className}
// retreive the classNames from the parent for sizing/styling
/>
<SignaledToolbarMain />
<ContextualToolbarImage />
<ContextualLoadingBar />
<ErrorDialog />
</>
);
};
@@ -0,0 +1,32 @@
import { MouseEventHandler } from "react";
import { ToolbarMain } from "~/components/features";
import { toolbarMain } from "~/signals/uiAccess/toolbarMain";
import { dispatchers } from "~/signals/uiEvents/toolbarMain";
import { ToolbarMainButtonNames } from "~/components/features/ToolbarMain/enum";
export const SignaledToolbarMain = () => {
const buttonProps = Object.values(ToolbarMainButtonNames).reduce(
(acc, buttonName) => {
acc[buttonName] = {
disabled: toolbarMain.signal.value.buttonStates[buttonName].disabled,
active: toolbarMain.signal.value.buttonStates[buttonName].active,
onClick: dispatchers[buttonName],
};
return acc;
},
{} as {
[key in ToolbarMainButtonNames]: {
disabled: boolean;
active: boolean;
onClick: MouseEventHandler<HTMLButtonElement>;
};
},
);
return (
<ToolbarMain
disabled={toolbarMain.signal.value.disabled}
buttonProps={buttonProps}
/>
);
};
+1
View File
@@ -0,0 +1 @@
export { KonvaRootComponent } from "./KonvaRootComponent";
@@ -0,0 +1,11 @@
export enum ToolbarMainButtonNames {
MENU = "MENU",
SELECT_ONE = "SELECT_ONE",
SELECT_AREA = "SELECT_AREA",
CHANGE_CAMERA_ORIENTATION = "CHANGE_CAMERA_ORIENTATION",
AI_STYLIZE = "AI_STYLIZE",
UNDO = "UNDO",
REDO = "REDO",
SAVE = "SAVE",
DOWNLOAD = "DOWNLOAD",
}
+42 -10
View File
@@ -1,5 +1,5 @@
import { MouseEventHandler, useCallback, useState } from "react";
import { useSignalEffect } from "@preact/signals-react/runtime";
import { useCallback, useState } from "react";
import {
faArrowRotateLeft,
faArrowRotateRight,
@@ -27,13 +27,27 @@ import { paperWrapperStyles } from "~/components/styles";
// for testing
import { layout } from "~/signals";
import { ToolbarMainButtonNames } from "./enum";
const initialState = {
isUploadSubmenuOpen: false,
isUploadVideoOpen: false,
isUploadImageOpen: false,
};
export const ToolbarMain = () => {
export const ToolbarMain = ({
disabled = false,
buttonProps,
}: {
disabled?: boolean;
buttonProps: {
[key in ToolbarMainButtonNames]: {
disabled?: boolean;
active?: boolean;
onClick?: MouseEventHandler<HTMLButtonElement>;
};
};
}) => {
//// for testing
const {
signals: { isMobile },
@@ -65,15 +79,21 @@ export const ToolbarMain = () => {
className={twMerge(
"m-auto flex w-fit items-center divide-x divide-ui-border",
paperWrapperStyles,
disabled &&
"pointer-events-none cursor-default bg-ui-border shadow-md",
)}
>
<div className="flex items-center gap-2 px-2">
<ToolbarButton icon={faBars} />
<ToolbarButton icon={faBars} buttonProps={buttonProps.MENU} />
<ToolbarButton
icon={faLocationArrow}
iconProps={{ className: "fa-flip-horizontal" }}
buttonProps={buttonProps.SELECT_ONE}
/>
<ToolbarButton
icon={faSquareDashed}
buttonProps={buttonProps.SELECT_AREA}
/>
<ToolbarButton icon={faSquareDashed} />
<div className="relative">
<ToolbarButton
icon={faFilePlus}
@@ -111,14 +131,26 @@ export const ToolbarMain = () => {
</div>
)}
</div>
<ToolbarButton icon={faCameraRotate} />
<ToolbarButton icon={faHatWizard} />
<ToolbarButton
icon={faCameraRotate}
buttonProps={buttonProps.CHANGE_CAMERA_ORIENTATION}
/>
<ToolbarButton
icon={faHatWizard}
buttonProps={buttonProps.AI_STYLIZE}
/>
</div>
<div className="flex items-center gap-2 px-2">
<ToolbarButton icon={faArrowRotateLeft} />
<ToolbarButton icon={faArrowRotateRight} />
<ToolbarButton icon={faFloppyDisk} />
<ToolbarButton icon={faDownload} />
<ToolbarButton
icon={faArrowRotateLeft}
buttonProps={buttonProps.UNDO}
/>
<ToolbarButton
icon={faArrowRotateRight}
buttonProps={buttonProps.REDO}
/>
<ToolbarButton icon={faFloppyDisk} buttonProps={buttonProps.SAVE} />
<ToolbarButton icon={faDownload} buttonProps={buttonProps.DOWNLOAD} />
</div>
</div>
+4 -18
View File
@@ -1,34 +1,21 @@
import { useCallback } from "react";
import { twMerge } from "tailwind-merge";
import { withProtectionRoute } from "~/components/hoc";
import { useRenderCounter } from "~/hooks/useRenderCounter";
// Components of the page
import { ToolbarUserProfile, ErrorDialog } from "~/components/features";
import { ToolbarUserProfile } from "~/components/features";
// Components of the Konva App are all in the KonvaContainer
import { KonvaContainer } from "~/KonvaContainer";
// The KonvaApp is the root of the Konva stage
// and only entry point for anything in Konva JS
import { KonvaApp } from "~/KonvaApp";
//Components of the Konva App are all in the KonvaComponent
import { KonvaRootComponent } from "~/KonvaRootComponent";
export const Main = withProtectionRoute(() => {
// This is a hook that will log the number of times the component has rerendered
// Let's make sure we only log once
useRenderCounter("Pages/Main");
const konvaContainerCallbackRef = useCallback((node: HTMLDivElement) => {
if (node !== null) {
KonvaApp(node);
}
}, []);
return (
<div className="fixed grid h-full w-full grid-cols-12 grid-rows-12">
<KonvaContainer
ref={konvaContainerCallbackRef}
className="col-span-12 col-start-1 row-span-12 row-start-1"
/>
<KonvaRootComponent className="col-span-12 col-start-1 row-span-12 row-start-1" />
<div
className={twMerge(
"col-span-8 col-start-5 row-span-1 row-start-1 flex justify-end",
@@ -37,7 +24,6 @@ export const Main = withProtectionRoute(() => {
)}
>
<ToolbarUserProfile />
<ErrorDialog />
</div>
</div>
);
+2 -2
View File
@@ -1,5 +1,5 @@
import { ContextualToolbarImage } from "~/KonvaContainer/ContextualToolbarImage";
import { ContextualLoadingBar } from "~/KonvaContainer/ContextualLoadingBar";
import { ContextualToolbarImage } from "~/KonvaRootComponent/ContextualToolbarImage";
import { ContextualLoadingBar } from "~/KonvaRootComponent/ContextualLoadingBar";
import { ErrorDialog } from "~/components/features";
+43
View File
@@ -0,0 +1,43 @@
import { signal } from "@preact/signals-core";
import { ToolbarMainButtonNames } from "~/components/features/ToolbarMain/enum";
interface ToolbarMainSignalInterface {
disabled: boolean;
buttonStates: {
[key in ToolbarMainButtonNames]: { disabled: boolean; active: boolean };
};
}
const toolbarMainSignal = signal<ToolbarMainSignalInterface>({
disabled: false,
buttonStates: initButtonStates(),
});
export const toolbarMain = {
signal: toolbarMainSignal,
changeButtonState(
buttonName: ToolbarMainButtonNames,
{ disabled, active }: { disabled?: boolean; active?: boolean },
) {
toolbarMainSignal.value = {
...toolbarMainSignal.value,
buttonStates: {
...toolbarMainSignal.value.buttonStates,
[buttonName]: {
disabled: active ? false : (disabled ?? false),
active: active ?? false,
},
},
};
},
};
function initButtonStates() {
const ret: { [key: string]: { disabled: boolean; active: boolean } } = {};
Object.values(ToolbarMainButtonNames).forEach((buttonName) => {
ret[buttonName] = {
disabled: false,
active: false,
};
});
return ret as ToolbarMainSignalInterface["buttonStates"];
}
+6
View File
@@ -6,12 +6,18 @@ import {
dispatchers as imageToolbarDispatchers,
eventsHandlers as imageToolbarEvents,
} from "./imageToolbar";
import {
dispatchers as toolbarMainDispatchers,
eventsHandlers as toolbarMainEvents,
} from "./toolbarMain";
export const uiEvents = {
...addMediaEvents,
imageToolbar: imageToolbarEvents,
toolbarMain: toolbarMainEvents,
};
export const dispatchUiEvents = {
...addMediaDispatchers,
imageToolbar: imageToolbarDispatchers,
toolbarMain: toolbarMainDispatchers,
};
+50
View File
@@ -0,0 +1,50 @@
import { MouseEventHandler } from "react";
import { signal, effect, Signal } from "@preact/signals-core";
import { ToolbarMainButtonNames } from "~/components/features/ToolbarMain/enum";
const events = Object.values(ToolbarMainButtonNames).reduce(
(acc, buttonName) => {
acc[buttonName] = signal<
React.MouseEvent<HTMLButtonElement, MouseEvent> | undefined
>();
return acc;
},
{} as {
[key in ToolbarMainButtonNames]: Signal<
(React.MouseEvent<HTMLButtonElement, MouseEvent> | undefined) | undefined
>;
},
);
export const eventsHandlers = Object.values(ToolbarMainButtonNames).reduce(
(acc, buttonName) => {
acc[buttonName] = {
onClick: (callback: MouseEventHandler<HTMLButtonElement>) => {
effect(() => {
if (events[buttonName].value) {
callback(events[buttonName].value);
}
});
},
};
return acc;
},
{} as {
[key in ToolbarMainButtonNames]: {
onClick: (callback: MouseEventHandler<HTMLButtonElement>) => void;
};
},
);
export const dispatchers = Object.values(ToolbarMainButtonNames).reduce(
(acc, buttonName) => {
acc[buttonName] = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
events[buttonName].value = e;
};
return acc;
},
{} as {
[key in ToolbarMainButtonNames]: MouseEventHandler<HTMLButtonElement>;
},
);