From d1f803783b784ba4eb05d8603953466a2fae0abc Mon Sep 17 00:00:00 2001 From: wil Date: Mon, 9 Sep 2024 14:03:58 -0400 Subject: [PATCH] toolbar main hooked up --- src/KonvaApp/Engine.ts | 8 +-- src/KonvaContainer/index.tsx | 26 ---------- .../ContextualLoadingBar.tsx | 0 .../ContextualToolbarImage.tsx | 0 .../KonvaCanvasContainer.tsx | 14 +++++ src/KonvaRootComponent/KonvaRootComponent.tsx | 37 +++++++++++++ .../SignaledToolbarMain.tsx | 32 ++++++++++++ src/KonvaRootComponent/index.tsx | 1 + src/components/features/ToolbarMain/enum.ts | 11 ++++ src/components/features/ToolbarMain/index.tsx | 52 +++++++++++++++---- src/pages/main/index.tsx | 22 ++------ src/pages/sandbox/index.tsx | 4 +- src/signals/uiAccess/toolbarMain.ts | 43 +++++++++++++++ src/signals/uiEvents/index.ts | 6 +++ src/signals/uiEvents/toolbarMain.ts | 50 ++++++++++++++++++ 15 files changed, 247 insertions(+), 59 deletions(-) delete mode 100644 src/KonvaContainer/index.tsx rename src/{KonvaContainer => KonvaRootComponent}/ContextualLoadingBar.tsx (100%) rename src/{KonvaContainer => KonvaRootComponent}/ContextualToolbarImage.tsx (100%) create mode 100644 src/KonvaRootComponent/KonvaCanvasContainer.tsx create mode 100644 src/KonvaRootComponent/KonvaRootComponent.tsx create mode 100644 src/KonvaRootComponent/SignaledToolbarMain.tsx create mode 100644 src/KonvaRootComponent/index.tsx create mode 100644 src/components/features/ToolbarMain/enum.ts create mode 100644 src/signals/uiAccess/toolbarMain.ts create mode 100644 src/signals/uiEvents/toolbarMain.ts diff --git a/src/KonvaApp/Engine.ts b/src/KonvaApp/Engine.ts index 60b598ce5c..a388c2f032 100644 --- a/src/KonvaApp/Engine.ts +++ b/src/KonvaApp/Engine.ts @@ -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 { @@ -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 diff --git a/src/KonvaContainer/index.tsx b/src/KonvaContainer/index.tsx deleted file mode 100644 index 4f20f85004..0000000000 --- a/src/KonvaContainer/index.tsx +++ /dev/null @@ -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 ->(({ className, ...props }, ref) => { - useRenderCounter("KonvaContainer"); - - const classes = twMerge("pegboard -z-10", className); - return ( - <> -
- - - - - - ); -}); diff --git a/src/KonvaContainer/ContextualLoadingBar.tsx b/src/KonvaRootComponent/ContextualLoadingBar.tsx similarity index 100% rename from src/KonvaContainer/ContextualLoadingBar.tsx rename to src/KonvaRootComponent/ContextualLoadingBar.tsx diff --git a/src/KonvaContainer/ContextualToolbarImage.tsx b/src/KonvaRootComponent/ContextualToolbarImage.tsx similarity index 100% rename from src/KonvaContainer/ContextualToolbarImage.tsx rename to src/KonvaRootComponent/ContextualToolbarImage.tsx diff --git a/src/KonvaRootComponent/KonvaCanvasContainer.tsx b/src/KonvaRootComponent/KonvaCanvasContainer.tsx new file mode 100644 index 0000000000..8d6203f09e --- /dev/null +++ b/src/KonvaRootComponent/KonvaCanvasContainer.tsx @@ -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 +>(({ className, ...props }, ref) => { + useRenderCounter("KonvaCanvasContainer"); + + const classes = twMerge("pegboard -z-10", className); + return
; +}); diff --git a/src/KonvaRootComponent/KonvaRootComponent.tsx b/src/KonvaRootComponent/KonvaRootComponent.tsx new file mode 100644 index 0000000000..5757b7dbc3 --- /dev/null +++ b/src/KonvaRootComponent/KonvaRootComponent.tsx @@ -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 ( + <> + + + + + + + ); +}; diff --git a/src/KonvaRootComponent/SignaledToolbarMain.tsx b/src/KonvaRootComponent/SignaledToolbarMain.tsx new file mode 100644 index 0000000000..c2b00330ab --- /dev/null +++ b/src/KonvaRootComponent/SignaledToolbarMain.tsx @@ -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; + }; + }, + ); + return ( + + ); +}; diff --git a/src/KonvaRootComponent/index.tsx b/src/KonvaRootComponent/index.tsx new file mode 100644 index 0000000000..f644abbfae --- /dev/null +++ b/src/KonvaRootComponent/index.tsx @@ -0,0 +1 @@ +export { KonvaRootComponent } from "./KonvaRootComponent"; diff --git a/src/components/features/ToolbarMain/enum.ts b/src/components/features/ToolbarMain/enum.ts new file mode 100644 index 0000000000..04e78e1c46 --- /dev/null +++ b/src/components/features/ToolbarMain/enum.ts @@ -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", +} diff --git a/src/components/features/ToolbarMain/index.tsx b/src/components/features/ToolbarMain/index.tsx index 3149b7fc6f..3b1b7fe783 100644 --- a/src/components/features/ToolbarMain/index.tsx +++ b/src/components/features/ToolbarMain/index.tsx @@ -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; + }; + }; +}) => { //// 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", )} >
- + + -
{
)}
- - + +
- - - - + + + +
diff --git a/src/pages/main/index.tsx b/src/pages/main/index.tsx index 1644d21f57..33ff5a8814 100644 --- a/src/pages/main/index.tsx +++ b/src/pages/main/index.tsx @@ -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 (
- +
{ )} > -
); diff --git a/src/pages/sandbox/index.tsx b/src/pages/sandbox/index.tsx index 7e08b408c5..18f7859286 100644 --- a/src/pages/sandbox/index.tsx +++ b/src/pages/sandbox/index.tsx @@ -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"; diff --git a/src/signals/uiAccess/toolbarMain.ts b/src/signals/uiAccess/toolbarMain.ts new file mode 100644 index 0000000000..8dce86c30b --- /dev/null +++ b/src/signals/uiAccess/toolbarMain.ts @@ -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({ + 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"]; +} diff --git a/src/signals/uiEvents/index.ts b/src/signals/uiEvents/index.ts index 3f79c64a54..ad8b562cb3 100644 --- a/src/signals/uiEvents/index.ts +++ b/src/signals/uiEvents/index.ts @@ -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, }; diff --git a/src/signals/uiEvents/toolbarMain.ts b/src/signals/uiEvents/toolbarMain.ts new file mode 100644 index 0000000000..0b5ed4ff9c --- /dev/null +++ b/src/signals/uiEvents/toolbarMain.ts @@ -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 | undefined + >(); + return acc; + }, + {} as { + [key in ToolbarMainButtonNames]: Signal< + (React.MouseEvent | undefined) | undefined + >; + }, +); + +export const eventsHandlers = Object.values(ToolbarMainButtonNames).reduce( + (acc, buttonName) => { + acc[buttonName] = { + onClick: (callback: MouseEventHandler) => { + effect(() => { + if (events[buttonName].value) { + callback(events[buttonName].value); + } + }); + }, + }; + return acc; + }, + {} as { + [key in ToolbarMainButtonNames]: { + onClick: (callback: MouseEventHandler) => void; + }; + }, +); + +export const dispatchers = Object.values(ToolbarMainButtonNames).reduce( + (acc, buttonName) => { + acc[buttonName] = (e: React.MouseEvent) => { + events[buttonName].value = e; + }; + return acc; + }, + {} as { + [key in ToolbarMainButtonNames]: MouseEventHandler; + }, +);