From 5935c9e60b9864769c3517e0056413f7d1bbc6d8 Mon Sep 17 00:00:00 2001 From: Devin Abbott Date: Mon, 16 Jan 2023 11:10:03 -0800 Subject: [PATCH] Add duplicate interaction --- .../src/hooks/useInteractionHandlers.tsx | 5 ++- .../noya-canvas/src/interactions/duplicate.ts | 43 +++++++++++++++++++ .../noya-canvas/src/interactions/index.ts | 2 + packages/site/src/ayon/Content.tsx | 11 +++-- 4 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 packages/noya-canvas/src/interactions/duplicate.ts diff --git a/packages/noya-canvas/src/hooks/useInteractionHandlers.tsx b/packages/noya-canvas/src/hooks/useInteractionHandlers.tsx index 6b66930ee..73dd8df68 100644 --- a/packages/noya-canvas/src/hooks/useInteractionHandlers.tsx +++ b/packages/noya-canvas/src/hooks/useInteractionHandlers.tsx @@ -33,6 +33,7 @@ import { ICanvasElement } from '../components/types'; import { useMultipleClickCount } from '../hooks/useMultipleClickCount'; import { ClipboardActions } from '../interactions/clipboard'; import { DrawingActions } from '../interactions/drawing'; +import { DuplicateActions } from '../interactions/duplicate'; import { EditBlockActions } from '../interactions/editBlock'; import { EditTextActions } from '../interactions/editText'; import { EscapeActions } from '../interactions/escape'; @@ -63,7 +64,8 @@ export type Actions = MarqueeActions & EscapeActions & ReorderActions & HistoryActions & - ZoomActions; + ZoomActions & + DuplicateActions; export type Interaction = ( actions: Actions, @@ -168,6 +170,7 @@ export function useInteractionHandlers({ dispatch('interaction', ['insert', layerType]), bringToFront: (id: string[]) => dispatch('bringToFront', id), sendToBack: (id: string[]) => dispatch('sendToBack', id), + duplicateLayer: (id: string[]) => dispatch('duplicateLayer', id), }; }, [dispatch]); diff --git a/packages/noya-canvas/src/interactions/duplicate.ts b/packages/noya-canvas/src/interactions/duplicate.ts new file mode 100644 index 000000000..d7be66ba3 --- /dev/null +++ b/packages/noya-canvas/src/interactions/duplicate.ts @@ -0,0 +1,43 @@ +import { ReactEventHandlers } from 'noya-designsystem'; +import { handleActionType, InteractionState } from 'noya-state'; +import { InteractionAPI } from './types'; + +export interface DuplicateActions { + duplicateLayer: (id: string[]) => void; +} + +type MenuItemType = 'duplicate'; + +export function duplicateInteraction({ duplicateLayer }: DuplicateActions) { + const handlers = handleActionType< + InteractionState, + [InteractionAPI], + ReactEventHandlers + >({ + none: (interactionState, api) => ({ + onContributeMenuItems: () => { + return api.selectedLayerIds.length > 0 + ? [{ value: 'duplicate', title: 'Duplicate', shortcut: 'Mod-d' }] + : []; + }, + onSelectMenuItem: (id) => { + switch (id) { + case 'duplicate': + duplicateLayer(api.selectedLayerIds); + break; + } + }, + }), + }); + + const result: typeof handlers = (interactionState, key, api) => { + return { + ...handlers(interactionState, key, api), + onKeyDown: api.handleKeyboardEvent({ + 'Mod-d': () => duplicateLayer(api.selectedLayerIds), + }), + }; + }; + + return result; +} diff --git a/packages/noya-canvas/src/interactions/index.ts b/packages/noya-canvas/src/interactions/index.ts index 5ef826447..742067347 100644 --- a/packages/noya-canvas/src/interactions/index.ts +++ b/packages/noya-canvas/src/interactions/index.ts @@ -1,5 +1,6 @@ import { clipboardInteraction } from './clipboard'; import { createDrawingInteraction } from './drawing'; +import { duplicateInteraction } from './duplicate'; import { editBlockInteraction } from './editBlock'; import { editTextInteraction } from './editText'; import { escapeInteraction } from './escape'; @@ -29,6 +30,7 @@ export namespace Interactions { export const escape = escapeInteraction; export const zoom = zoomInteraction; export const reorder = reorderInteraction; + export const duplicate = duplicateInteraction; export const scale = createScaleInteraction(); export const createScale = createScaleInteraction; } diff --git a/packages/site/src/ayon/Content.tsx b/packages/site/src/ayon/Content.tsx index ddcb5995e..a5eed209b 100644 --- a/packages/site/src/ayon/Content.tsx +++ b/packages/site/src/ayon/Content.tsx @@ -20,7 +20,7 @@ const Overlay = styled.div({ }); export const Content = memo(function Content() { - const { canvasSize } = useWorkspace(); + const { canvasSize, isContextMenuOpen } = useWorkspace(); const [state, dispatch] = useApplicationState(); const layers = Layers.flat(Selectors.getCurrentPage(state)).filter( Layers.isSymbolInstance, @@ -32,9 +32,10 @@ export const Content = memo(function Content() { - +