mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
fix(ui): disable canvas hotkeys when viewer is open
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -9,13 +10,14 @@ export const ToolBboxButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const selectBbox = useSelectTool('bbox');
|
||||
const isSelected = useToolIsSelected('bbox');
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
useRegisteredHotkeys({
|
||||
id: 'selectBboxTool',
|
||||
category: 'canvas',
|
||||
callback: selectBbox,
|
||||
options: { enabled: !isSelected },
|
||||
dependencies: [selectBbox, isSelected],
|
||||
options: { enabled: !isSelected && !imageViewer.isOpen },
|
||||
dependencies: [selectBbox, isSelected, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -9,13 +10,14 @@ export const ToolBrushButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isSelected = useToolIsSelected('brush');
|
||||
const selectBrush = useSelectTool('brush');
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
useRegisteredHotkeys({
|
||||
id: 'selectBrushTool',
|
||||
category: 'canvas',
|
||||
callback: selectBrush,
|
||||
options: { enabled: !isSelected },
|
||||
dependencies: [isSelected, selectBrush],
|
||||
options: { enabled: !isSelected && !imageViewer.isOpen },
|
||||
dependencies: [isSelected, selectBrush, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -16,6 +16,7 @@ import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { selectCanvasSettingsSlice, settingsBrushWidthChanged } from 'features/controlLayers/store/canvasSettingsSlice';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { clamp } from 'lodash-es';
|
||||
import type { KeyboardEvent } from 'react';
|
||||
@@ -68,6 +69,7 @@ const sliderDefaultValue = mapRawValueToSliderValue(50);
|
||||
export const ToolBrushWidth = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
const imageViewer = useImageViewer();
|
||||
const isSelected = useToolIsSelected('brush');
|
||||
const width = useAppSelector(selectBrushWidth);
|
||||
const [localValue, setLocalValue] = useState(width);
|
||||
@@ -131,15 +133,15 @@ export const ToolBrushWidth = memo(() => {
|
||||
id: 'incrementToolWidth',
|
||||
category: 'canvas',
|
||||
callback: decrement,
|
||||
options: { enabled: isSelected },
|
||||
dependencies: [decrement, isSelected],
|
||||
options: { enabled: isSelected && !imageViewer.isOpen },
|
||||
dependencies: [decrement, isSelected, imageViewer.isOpen],
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
id: 'incrementToolWidth',
|
||||
category: 'canvas',
|
||||
callback: increment,
|
||||
options: { enabled: isSelected },
|
||||
dependencies: [increment, isSelected],
|
||||
options: { enabled: isSelected && !imageViewer.isOpen },
|
||||
dependencies: [increment, isSelected, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -9,13 +10,14 @@ export const ToolColorPickerButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isSelected = useToolIsSelected('colorPicker');
|
||||
const selectColorPicker = useSelectTool('colorPicker');
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
useRegisteredHotkeys({
|
||||
id: 'selectColorPickerTool',
|
||||
category: 'canvas',
|
||||
callback: selectColorPicker,
|
||||
options: { enabled: !isSelected },
|
||||
dependencies: [selectColorPicker, isSelected],
|
||||
options: { enabled: !isSelected && !imageViewer.isOpen },
|
||||
dependencies: [selectColorPicker, isSelected, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -9,13 +10,14 @@ export const ToolEraserButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isSelected = useToolIsSelected('eraser');
|
||||
const selectEraser = useSelectTool('eraser');
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
useRegisteredHotkeys({
|
||||
id: 'selectEraserTool',
|
||||
category: 'canvas',
|
||||
callback: selectEraser,
|
||||
options: { enabled: !isSelected },
|
||||
dependencies: [isSelected, selectEraser],
|
||||
options: { enabled: !isSelected && !imageViewer.isOpen },
|
||||
dependencies: [isSelected, selectEraser, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
selectCanvasSettingsSlice,
|
||||
settingsEraserWidthChanged,
|
||||
} from 'features/controlLayers/store/canvasSettingsSlice';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { clamp } from 'lodash-es';
|
||||
import type { KeyboardEvent } from 'react';
|
||||
@@ -71,6 +72,7 @@ const sliderDefaultValue = mapRawValueToSliderValue(50);
|
||||
export const ToolEraserWidth = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
const imageViewer = useImageViewer();
|
||||
const isSelected = useToolIsSelected('eraser');
|
||||
const width = useAppSelector(selectEraserWidth);
|
||||
const [localValue, setLocalValue] = useState(width);
|
||||
@@ -134,15 +136,15 @@ export const ToolEraserWidth = memo(() => {
|
||||
id: 'incrementToolWidth',
|
||||
category: 'canvas',
|
||||
callback: decrement,
|
||||
options: { enabled: isSelected },
|
||||
dependencies: [decrement, isSelected],
|
||||
options: { enabled: isSelected && !imageViewer.isOpen },
|
||||
dependencies: [decrement, isSelected, imageViewer.isOpen],
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
id: 'incrementToolWidth',
|
||||
category: 'canvas',
|
||||
callback: increment,
|
||||
options: { enabled: isSelected },
|
||||
dependencies: [increment, isSelected],
|
||||
options: { enabled: isSelected && !imageViewer.isOpen },
|
||||
dependencies: [increment, isSelected, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -9,13 +10,14 @@ export const ToolMoveButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isSelected = useToolIsSelected('move');
|
||||
const selectMove = useSelectTool('move');
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
useRegisteredHotkeys({
|
||||
id: 'selectMoveTool',
|
||||
category: 'canvas',
|
||||
callback: selectMove,
|
||||
options: { enabled: !isSelected },
|
||||
dependencies: [isSelected, selectMove],
|
||||
options: { enabled: !isSelected && !imageViewer.isOpen },
|
||||
dependencies: [isSelected, selectMove, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -9,13 +10,14 @@ export const ToolRectButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isSelected = useToolIsSelected('rect');
|
||||
const selectRect = useSelectTool('rect');
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
useRegisteredHotkeys({
|
||||
id: 'selectRectTool',
|
||||
category: 'canvas',
|
||||
callback: selectRect,
|
||||
options: { enabled: !isSelected },
|
||||
dependencies: [isSelected, selectRect],
|
||||
options: { enabled: !isSelected && !imageViewer.isOpen },
|
||||
dependencies: [isSelected, selectRect, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { useSelectTool, useToolIsSelected } from 'features/controlLayers/components/Tool/hooks';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -9,13 +10,14 @@ export const ToolViewButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isSelected = useToolIsSelected('view');
|
||||
const selectView = useSelectTool('view');
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
useRegisteredHotkeys({
|
||||
id: 'selectViewTool',
|
||||
category: 'canvas',
|
||||
callback: selectView,
|
||||
options: { enabled: !isSelected },
|
||||
dependencies: [selectView, isSelected],
|
||||
options: { enabled: !isSelected && !imageViewer.isOpen },
|
||||
dependencies: [selectView, isSelected, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,6 +2,7 @@ import { $alt, IconButton } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { INTERACTION_SCOPES } from 'common/hooks/interactionScopes';
|
||||
import { $canvasManager } from 'features/controlLayers/store/ephemeral';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -11,6 +12,7 @@ export const CanvasToolbarResetViewButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const canvasManager = useStore($canvasManager);
|
||||
const isCanvasActive = useStore(INTERACTION_SCOPES.canvas.$isActive);
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
const resetZoom = useCallback(() => {
|
||||
if (!canvasManager) {
|
||||
@@ -38,15 +40,15 @@ export const CanvasToolbarResetViewButton = memo(() => {
|
||||
id: 'fitLayersToCanvas',
|
||||
category: 'canvas',
|
||||
callback: resetView,
|
||||
options: { enabled: isCanvasActive },
|
||||
dependencies: [isCanvasActive],
|
||||
options: { enabled: isCanvasActive && !imageViewer.isOpen },
|
||||
dependencies: [isCanvasActive, imageViewer.isOpen],
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
id: 'setZoomTo100Percent',
|
||||
category: 'canvas',
|
||||
callback: resetZoom,
|
||||
options: { enabled: isCanvasActive },
|
||||
dependencies: [isCanvasActive],
|
||||
options: { enabled: isCanvasActive && !imageViewer.isOpen },
|
||||
dependencies: [isCanvasActive, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
|
||||
import { entityDeleted } from 'features/controlLayers/store/canvasSlice';
|
||||
import { $canvasRightPanelTab } from 'features/controlLayers/store/ephemeral';
|
||||
import { selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { selectActiveTab } from 'features/ui/store/uiSelectors';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
@@ -17,6 +18,8 @@ export function useCanvasDeleteLayerHotkey() {
|
||||
const canvasRightPanelTab = useStore($canvasRightPanelTab);
|
||||
const appTab = useAppSelector(selectActiveTab);
|
||||
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
const deleteSelectedLayer = useCallback(() => {
|
||||
if (selectedEntityIdentifier === null) {
|
||||
return;
|
||||
@@ -33,7 +36,7 @@ export function useCanvasDeleteLayerHotkey() {
|
||||
id: 'deleteSelected',
|
||||
category: 'canvas',
|
||||
callback: deleteSelectedLayer,
|
||||
options: { enabled: isDeleteEnabled },
|
||||
dependencies: [isDeleteEnabled, deleteSelectedLayer],
|
||||
options: { enabled: isDeleteEnabled && !imageViewer.isOpen },
|
||||
dependencies: [isDeleteEnabled, deleteSelectedLayer, imageViewer.isOpen],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
selectSelectedEntityIdentifier,
|
||||
} from 'features/controlLayers/store/selectors';
|
||||
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
@@ -14,6 +15,7 @@ export const useCanvasEntityQuickSwitchHotkey = () => {
|
||||
const [current, setCurrent] = useState<CanvasEntityIdentifier | null>(null);
|
||||
const selected = useAppSelector(selectSelectedEntityIdentifier);
|
||||
const bookmarked = useAppSelector(selectBookmarkedEntityIdentifier);
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
// Update prev and current when selected entity changes
|
||||
useEffect(() => {
|
||||
@@ -47,6 +49,7 @@ export const useCanvasEntityQuickSwitchHotkey = () => {
|
||||
id: 'quickSwitch',
|
||||
category: 'canvas',
|
||||
callback: onQuickSwitch,
|
||||
dependencies: [onQuickSwitch],
|
||||
options: { enabled: !imageViewer.isOpen },
|
||||
dependencies: [onQuickSwitch, imageViewer.isOpen],
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { $false } from 'app/store/nanostores/util';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useAssertSingleton } from 'common/hooks/useAssertSingleton';
|
||||
import { useEntityAdapterSafe } from 'features/controlLayers/contexts/EntityAdapterContext';
|
||||
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
|
||||
import { entityReset } from 'features/controlLayers/store/canvasSlice';
|
||||
import { selectCanvasSlice } from 'features/controlLayers/store/selectors';
|
||||
import { selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors';
|
||||
import { isMaskEntityIdentifier } from 'features/controlLayers/store/types';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
const selectSelectedEntityIdentifier = createMemoizedSelector(
|
||||
selectCanvasSlice,
|
||||
(canvasState) => canvasState.selectedEntityIdentifier
|
||||
);
|
||||
|
||||
export function useCanvasResetLayerHotkey() {
|
||||
useAssertSingleton(useCanvasResetLayerHotkey.name);
|
||||
const dispatch = useAppDispatch();
|
||||
@@ -23,6 +18,7 @@ export function useCanvasResetLayerHotkey() {
|
||||
const isBusy = useCanvasIsBusy();
|
||||
const adapter = useEntityAdapterSafe(selectedEntityIdentifier);
|
||||
const isInteractable = useStore(adapter?.$isInteractable ?? $false);
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
const resetSelectedLayer = useCallback(() => {
|
||||
if (selectedEntityIdentifier === null || adapter === null) {
|
||||
@@ -41,7 +37,7 @@ export function useCanvasResetLayerHotkey() {
|
||||
id: 'resetSelected',
|
||||
category: 'canvas',
|
||||
callback: resetSelectedLayer,
|
||||
options: { enabled: isResetEnabled && !isBusy && isInteractable },
|
||||
dependencies: [isResetEnabled, isBusy, isInteractable, resetSelectedLayer],
|
||||
options: { enabled: isResetEnabled && !isBusy && isInteractable && !imageViewer.isOpen },
|
||||
dependencies: [isResetEnabled, isBusy, isInteractable, resetSelectedLayer, imageViewer.isOpen],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useAssertSingleton } from 'common/hooks/useAssertSingleton';
|
||||
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
|
||||
import { canvasRedo, canvasUndo } from 'features/controlLayers/store/canvasSlice';
|
||||
import { selectCanvasMayRedo, selectCanvasMayUndo } from 'features/controlLayers/store/selectors';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
@@ -11,6 +12,7 @@ export const useCanvasUndoRedoHotkeys = () => {
|
||||
useAssertSingleton('useCanvasUndoRedo');
|
||||
const dispatch = useDispatch();
|
||||
const isBusy = useCanvasIsBusy();
|
||||
const imageViewer = useImageViewer();
|
||||
|
||||
const mayUndo = useAppSelector(selectCanvasMayUndo);
|
||||
const handleUndo = useCallback(() => {
|
||||
@@ -20,8 +22,8 @@ export const useCanvasUndoRedoHotkeys = () => {
|
||||
id: 'undo',
|
||||
category: 'canvas',
|
||||
callback: handleUndo,
|
||||
options: { enabled: mayUndo && !isBusy, preventDefault: true },
|
||||
dependencies: [mayUndo, isBusy, handleUndo],
|
||||
options: { enabled: mayUndo && !isBusy && !imageViewer.isOpen, preventDefault: true },
|
||||
dependencies: [mayUndo, isBusy, handleUndo, imageViewer.isOpen],
|
||||
});
|
||||
|
||||
const mayRedo = useAppSelector(selectCanvasMayRedo);
|
||||
@@ -32,7 +34,7 @@ export const useCanvasUndoRedoHotkeys = () => {
|
||||
id: 'redo',
|
||||
category: 'canvas',
|
||||
callback: handleRedo,
|
||||
options: { enabled: mayRedo && !isBusy, preventDefault: true },
|
||||
dependencies: [mayRedo, handleRedo, isBusy],
|
||||
options: { enabled: mayRedo && !isBusy && !imageViewer.isOpen, preventDefault: true },
|
||||
dependencies: [mayRedo, handleRedo, isBusy, imageViewer.isOpen],
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user