From 4a43e1c1b8ec66ed9eff6c5c573ee368e5d43bfd Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Wed, 3 Jan 2024 07:31:47 +1100 Subject: [PATCH] fix(ui): restore global hotkeys --- .../frontend/web/src/app/components/App.tsx | 2 + .../web/src/common/hooks/useGlobalHotkeys.ts | 95 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index 07fc7e39f7..4a88c2af58 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -8,6 +8,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import type { PartialAppConfig } from 'app/types/invokeai'; import ImageUploader from 'common/components/ImageUploader'; import { useClearStorage } from 'common/hooks/useClearStorage'; +import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys'; import { useGlobalModifiersInit } from 'common/hooks/useGlobalModifiers'; import ChangeBoardModal from 'features/changeBoardModal/components/ChangeBoardModal'; import DeleteImageModal from 'features/deleteImageModal/components/DeleteImageModal'; @@ -44,6 +45,7 @@ const App = ({ config = DEFAULT_CONFIG, selectedImage }: Props) => { // singleton! useSocketIO(); useGlobalModifiersInit(); + useGlobalHotkeys(); const handleReset = useCallback(() => { clearStorage(); diff --git a/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts b/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts new file mode 100644 index 0000000000..a023de15be --- /dev/null +++ b/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts @@ -0,0 +1,95 @@ +import { useAppDispatch } from 'app/store/storeHooks'; +import { useQueueBack } from 'features/queue/hooks/useQueueBack'; +import { useQueueFront } from 'features/queue/hooks/useQueueFront'; +import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; +import { setActiveTab } from 'features/ui/store/uiSlice'; +import { useHotkeys } from 'react-hotkeys-hook'; + +export const useGlobalHotkeys = () => { + const dispatch = useAppDispatch(); + const isModelManagerEnabled = + useFeatureStatus('modelManager').isFeatureEnabled; + const { + queueBack, + isDisabled: isDisabledQueueBack, + isLoading: isLoadingQueueBack, + } = useQueueBack(); + + useHotkeys( + ['ctrl+enter', 'meta+enter'], + queueBack, + { + enabled: () => !isDisabledQueueBack && !isLoadingQueueBack, + preventDefault: true, + enableOnFormTags: ['input', 'textarea', 'select'], + }, + [queueBack, isDisabledQueueBack, isLoadingQueueBack] + ); + + const { + queueFront, + isDisabled: isDisabledQueueFront, + isLoading: isLoadingQueueFront, + } = useQueueFront(); + + useHotkeys( + ['ctrl+shift+enter', 'meta+shift+enter'], + queueFront, + { + enabled: () => !isDisabledQueueFront && !isLoadingQueueFront, + preventDefault: true, + enableOnFormTags: ['input', 'textarea', 'select'], + }, + [queueFront, isDisabledQueueFront, isLoadingQueueFront] + ); + + useHotkeys( + '1', + () => { + dispatch(setActiveTab('txt2img')); + }, + [dispatch] + ); + + useHotkeys( + '2', + () => { + dispatch(setActiveTab('img2img')); + }, + [dispatch] + ); + + useHotkeys( + '3', + () => { + dispatch(setActiveTab('unifiedCanvas')); + }, + [dispatch] + ); + + useHotkeys( + '4', + () => { + dispatch(setActiveTab('nodes')); + }, + [dispatch] + ); + + useHotkeys( + '5', + () => { + if (isModelManagerEnabled) { + dispatch(setActiveTab('modelManager')); + } + }, + [dispatch, isModelManagerEnabled] + ); + + useHotkeys( + isModelManagerEnabled ? '6' : '5', + () => { + dispatch(setActiveTab('queue')); + }, + [dispatch, isModelManagerEnabled] + ); +};