mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): use @invoke-ai/ui
hooks for modifiers, global menu state
This commit is contained in:
parent
53cf518390
commit
e96ad41729
@ -1,7 +1,7 @@
|
|||||||
import { PropsWithChildren, memo, useEffect } from 'react';
|
import { PropsWithChildren, memo, useEffect } from 'react';
|
||||||
import { modelChanged } from '../src/features/parameters/store/generationSlice';
|
import { modelChanged } from '../src/features/parameters/store/generationSlice';
|
||||||
import { useAppDispatch } from '../src/app/store/storeHooks';
|
import { useAppDispatch } from '../src/app/store/storeHooks';
|
||||||
import { useGlobalModifiersInit } from '../src/common/hooks/useGlobalModifiers';
|
import { useGlobalModifiersInit } from '@invoke-ai/ui';
|
||||||
/**
|
/**
|
||||||
* Initializes some state for storybook. Must be in a different component
|
* Initializes some state for storybook. Must be in a different component
|
||||||
* so that it is run inside the redux context.
|
* so that it is run inside the redux context.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Box } from '@invoke-ai/ui';
|
import { Box, useGlobalModifiersInit } from '@invoke-ai/ui';
|
||||||
import { useSocketIO } from 'app/hooks/useSocketIO';
|
import { useSocketIO } from 'app/hooks/useSocketIO';
|
||||||
import { useLogger } from 'app/logging/useLogger';
|
import { useLogger } from 'app/logging/useLogger';
|
||||||
import { appStarted } from 'app/store/middleware/listenerMiddleware/listeners/appStarted';
|
import { appStarted } from 'app/store/middleware/listenerMiddleware/listeners/appStarted';
|
||||||
@ -8,7 +8,6 @@ import ImageUploadOverlay from 'common/components/ImageUploadOverlay';
|
|||||||
import { useClearStorage } from 'common/hooks/useClearStorage';
|
import { useClearStorage } from 'common/hooks/useClearStorage';
|
||||||
import { useFullscreenDropzone } from 'common/hooks/useFullscreenDropzone';
|
import { useFullscreenDropzone } from 'common/hooks/useFullscreenDropzone';
|
||||||
import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
|
import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
|
||||||
import { useGlobalModifiersInit } from 'common/hooks/useGlobalModifiers';
|
|
||||||
import ChangeBoardModal from 'features/changeBoardModal/components/ChangeBoardModal';
|
import ChangeBoardModal from 'features/changeBoardModal/components/ChangeBoardModal';
|
||||||
import DeleteImageModal from 'features/deleteImageModal/components/DeleteImageModal';
|
import DeleteImageModal from 'features/deleteImageModal/components/DeleteImageModal';
|
||||||
import { DynamicPromptsModal } from 'features/dynamicPrompts/components/DynamicPromptsPreviewModal';
|
import { DynamicPromptsModal } from 'features/dynamicPrompts/components/DynamicPromptsPreviewModal';
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
import { atom } from 'nanostores';
|
|
||||||
import { useCallback, useEffect } from 'react';
|
|
||||||
|
|
||||||
type CB = () => void;
|
|
||||||
|
|
||||||
const $onCloseCallbacks = atom<CB[]>([]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The reactflow background element somehow prevents the chakra `useOutsideClick()` hook from working.
|
|
||||||
* With a menu open, clicking on the reactflow background element doesn't close the menu.
|
|
||||||
*
|
|
||||||
* Reactflow does provide an `onPaneClick` to handle clicks on the background element, but it is not
|
|
||||||
* straightforward to programatically close all menus.
|
|
||||||
*
|
|
||||||
* This hook provides a way to close all menus by calling `onCloseGlobal()`. Menus that want to be closed
|
|
||||||
* in this way should register themselves by passing a callback to `useGlobalMenuCloseTrigger()`.
|
|
||||||
*/
|
|
||||||
export const useGlobalMenuClose = (onClose?: CB) => {
|
|
||||||
useEffect(() => {
|
|
||||||
if (!onClose) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$onCloseCallbacks.set([...$onCloseCallbacks.get(), onClose]);
|
|
||||||
return () => {
|
|
||||||
$onCloseCallbacks.set(
|
|
||||||
$onCloseCallbacks.get().filter((c) => c !== onClose)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}, [onClose]);
|
|
||||||
|
|
||||||
const onCloseGlobal = useCallback(() => {
|
|
||||||
$onCloseCallbacks.get().forEach((cb) => cb());
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return { onCloseGlobal };
|
|
||||||
};
|
|
@ -1,52 +0,0 @@
|
|||||||
import { atom } from 'nanostores';
|
|
||||||
import { useCallback, useEffect } from 'react';
|
|
||||||
|
|
||||||
export const $shift = atom(false);
|
|
||||||
export const $ctrl = atom(false);
|
|
||||||
export const $meta = atom(false);
|
|
||||||
export const $alt = atom(false);
|
|
||||||
|
|
||||||
const $subscribers = atom(0);
|
|
||||||
|
|
||||||
const listener = (e: KeyboardEvent) => {
|
|
||||||
$shift.set(e.shiftKey);
|
|
||||||
$ctrl.set(e.ctrlKey);
|
|
||||||
$alt.set(e.altKey);
|
|
||||||
$meta.set(e.metaKey);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useGlobalModifiersInit = () => {
|
|
||||||
useEffect(() => {
|
|
||||||
$subscribers.set($subscribers.get() + 1);
|
|
||||||
|
|
||||||
if ($subscribers.get() === 1) {
|
|
||||||
window.addEventListener('keydown', listener);
|
|
||||||
window.addEventListener('keyup', listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
$subscribers.set(Math.max($subscribers.get() - 1, 0));
|
|
||||||
if ($subscribers.get() > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
window.removeEventListener('keydown', listener);
|
|
||||||
window.removeEventListener('keyup', listener);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useGlobalModifiersSetters = () => {
|
|
||||||
const setShift = useCallback((shift: boolean) => {
|
|
||||||
$shift.set(shift);
|
|
||||||
}, []);
|
|
||||||
const setCtrl = useCallback((ctrl: boolean) => {
|
|
||||||
$ctrl.set(ctrl);
|
|
||||||
}, []);
|
|
||||||
const setAlt = useCallback((alt: boolean) => {
|
|
||||||
$alt.set(alt);
|
|
||||||
}, []);
|
|
||||||
const setMeta = useCallback((meta: boolean) => {
|
|
||||||
$meta.set(meta);
|
|
||||||
}, []);
|
|
||||||
return { setShift, setCtrl, setAlt, setMeta };
|
|
||||||
};
|
|
@ -1,6 +1,6 @@
|
|||||||
|
import { useShiftModifier } from '@invoke-ai/ui';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { $shift } from 'common/hooks/useGlobalModifiers';
|
|
||||||
import {
|
import {
|
||||||
roundDownToMultiple,
|
roundDownToMultiple,
|
||||||
roundDownToMultipleMin,
|
roundDownToMultipleMin,
|
||||||
@ -54,7 +54,7 @@ const IAICanvasBoundingBox = (props: IAICanvasBoundingBoxPreviewProps) => {
|
|||||||
const optimalDimension = useAppSelector(selectOptimalDimension);
|
const optimalDimension = useAppSelector(selectOptimalDimension);
|
||||||
const transformerRef = useRef<Konva.Transformer>(null);
|
const transformerRef = useRef<Konva.Transformer>(null);
|
||||||
const shapeRef = useRef<Konva.Rect>(null);
|
const shapeRef = useRef<Konva.Rect>(null);
|
||||||
const shift = useStore($shift);
|
const shift = useShiftModifier();
|
||||||
const tool = useStore($tool);
|
const tool = useStore($tool);
|
||||||
const isDrawing = useStore($isDrawing);
|
const isDrawing = useStore($isDrawing);
|
||||||
const isMovingBoundingBox = useStore($isMovingBoundingBox);
|
const isMovingBoundingBox = useStore($isMovingBoundingBox);
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import type { SystemStyleObject } from '@invoke-ai/ui';
|
import type { SystemStyleObject } from '@invoke-ai/ui';
|
||||||
import { Box, Flex } from '@invoke-ai/ui';
|
import { Box, Flex, useShiftModifier } from '@invoke-ai/ui';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
import { $customStarUI } from 'app/store/nanostores/customStarUI';
|
import { $customStarUI } from 'app/store/nanostores/customStarUI';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIDndImage from 'common/components/IAIDndImage';
|
import IAIDndImage from 'common/components/IAIDndImage';
|
||||||
import IAIDndImageIcon from 'common/components/IAIDndImageIcon';
|
import IAIDndImageIcon from 'common/components/IAIDndImageIcon';
|
||||||
import IAIFillSkeleton from 'common/components/IAIFillSkeleton';
|
import IAIFillSkeleton from 'common/components/IAIFillSkeleton';
|
||||||
import { $shift } from 'common/hooks/useGlobalModifiers';
|
|
||||||
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
|
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
|
||||||
import type {
|
import type {
|
||||||
GallerySelectionDraggableData,
|
GallerySelectionDraggableData,
|
||||||
@ -40,7 +39,7 @@ const GalleryImage = (props: HoverableImageProps) => {
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { imageName } = props;
|
const { imageName } = props;
|
||||||
const { currentData: imageDTO } = useGetImageDTOQuery(imageName);
|
const { currentData: imageDTO } = useGetImageDTOQuery(imageName);
|
||||||
const shift = useStore($shift);
|
const shift = useShiftModifier()
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const selectedBoardId = useAppSelector((s) => s.gallery.selectedBoardId);
|
const selectedBoardId = useAppSelector((s) => s.gallery.selectedBoardId);
|
||||||
const { handleClick, isSelected, areMultiplesSelected } =
|
const { handleClick, isSelected, areMultiplesSelected } =
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { useToken } from '@invoke-ai/ui';
|
import { useGlobalMenuClose, useToken } from '@invoke-ai/ui';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { useGlobalMenuClose } from 'common/hooks/useGlobalMenuClose';
|
|
||||||
import { useIsValidConnection } from 'features/nodes/hooks/useIsValidConnection';
|
import { useIsValidConnection } from 'features/nodes/hooks/useIsValidConnection';
|
||||||
import { $mouseOverNode } from 'features/nodes/hooks/useMouseOverNode';
|
import { $mouseOverNode } from 'features/nodes/hooks/useMouseOverNode';
|
||||||
import { useWorkflowWatcher } from 'features/nodes/hooks/useWorkflowWatcher';
|
import { useWorkflowWatcher } from 'features/nodes/hooks/useWorkflowWatcher';
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import type { ChakraProps } from '@invoke-ai/ui';
|
import type { ChakraProps } from '@invoke-ai/ui';
|
||||||
import { Box, useToken } from '@invoke-ai/ui';
|
import { Box, useGlobalMenuClose, useToken } from '@invoke-ai/ui';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import NodeSelectionOverlay from 'common/components/NodeSelectionOverlay';
|
import NodeSelectionOverlay from 'common/components/NodeSelectionOverlay';
|
||||||
import { useGlobalMenuClose } from 'common/hooks/useGlobalMenuClose';
|
|
||||||
import { useMouseOverNode } from 'features/nodes/hooks/useMouseOverNode';
|
import { useMouseOverNode } from 'features/nodes/hooks/useMouseOverNode';
|
||||||
import {
|
import {
|
||||||
nodeExclusivelySelected,
|
nodeExclusivelySelected,
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import type { IconButtonProps } from '@invoke-ai/ui';
|
import type { IconButtonProps } from '@invoke-ai/ui';
|
||||||
import { IconButton, useDisclosure } from '@invoke-ai/ui';
|
import { IconButton, useDisclosure, useShiftModifier } from '@invoke-ai/ui';
|
||||||
import { useStore } from '@nanostores/react';
|
|
||||||
import { $shift } from 'common/hooks/useGlobalModifiers';
|
|
||||||
import ClearQueueConfirmationAlertDialog from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
import ClearQueueConfirmationAlertDialog from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
||||||
import { useCancelCurrentQueueItem } from 'features/queue/hooks/useCancelCurrentQueueItem';
|
import { useCancelCurrentQueueItem } from 'features/queue/hooks/useCancelCurrentQueueItem';
|
||||||
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
|
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
|
||||||
@ -59,7 +57,7 @@ const ClearSingleQueueItemIconButton = (props: ClearQueueButtonProps) => {
|
|||||||
export const ClearQueueIconButton = (props: ClearQueueButtonProps) => {
|
export const ClearQueueIconButton = (props: ClearQueueButtonProps) => {
|
||||||
// Show the single item clear button when shift is pressed
|
// Show the single item clear button when shift is pressed
|
||||||
// Otherwise show the clear queue button
|
// Otherwise show the clear queue button
|
||||||
const shift = useStore($shift);
|
const shift = useShiftModifier()
|
||||||
const disclosure = useDisclosure();
|
const disclosure = useDisclosure();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -6,8 +6,8 @@ import {
|
|||||||
MenuItem,
|
MenuItem,
|
||||||
MenuList,
|
MenuList,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
|
useGlobalMenuClose,
|
||||||
} from '@invoke-ai/ui';
|
} from '@invoke-ai/ui';
|
||||||
import { useGlobalMenuClose } from 'common/hooks/useGlobalMenuClose';
|
|
||||||
import AboutModal from 'features/system/components/AboutModal/AboutModal';
|
import AboutModal from 'features/system/components/AboutModal/AboutModal';
|
||||||
import HotkeysModal from 'features/system/components/HotkeysModal/HotkeysModal';
|
import HotkeysModal from 'features/system/components/HotkeysModal/HotkeysModal';
|
||||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||||
|
@ -5,8 +5,8 @@ import {
|
|||||||
MenuDivider,
|
MenuDivider,
|
||||||
MenuList,
|
MenuList,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
|
useGlobalMenuClose,
|
||||||
} from '@invoke-ai/ui';
|
} from '@invoke-ai/ui';
|
||||||
import { useGlobalMenuClose } from 'common/hooks/useGlobalMenuClose';
|
|
||||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||||
import DownloadWorkflowMenuItem from 'features/workflowLibrary/components/WorkflowLibraryMenu/DownloadWorkflowMenuItem';
|
import DownloadWorkflowMenuItem from 'features/workflowLibrary/components/WorkflowLibraryMenu/DownloadWorkflowMenuItem';
|
||||||
import NewWorkflowMenuItem from 'features/workflowLibrary/components/WorkflowLibraryMenu/NewWorkflowMenuItem';
|
import NewWorkflowMenuItem from 'features/workflowLibrary/components/WorkflowLibraryMenu/NewWorkflowMenuItem';
|
||||||
|
Loading…
Reference in New Issue
Block a user