fix(ui): disable canvas hotkeys when viewer is open

This commit is contained in:
psychedelicious
2024-09-19 11:51:56 +10:00
parent aa9fbcd37c
commit 227b984e3b
14 changed files with 66 additions and 42 deletions

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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],
});
}

View File

@@ -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],
});
};

View File

@@ -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],
});
}

View File

@@ -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],
});
};