feat(ui): revised focus handling (attempt 3, wip)

This commit is contained in:
psychedelicious
2024-09-30 17:10:41 +10:00
parent 48311f38ba
commit 8cf0d8c8d3
12 changed files with 145 additions and 124 deletions

View File

@@ -10,7 +10,7 @@ import { memo, useRef } from 'react';
export const CanvasLayersPanelContent = memo(() => {
const hasEntities = useAppSelector(selectHasEntities);
const layersPanelFocusRef = useRef<HTMLDivElement>(null);
useFocusRegion('layersPanel', layersPanelFocusRef);
useFocusRegion('layers', layersPanelFocusRef);
return (
<Flex ref={layersPanelFocusRef} flexDir="column" gap={2} w="full" h="full">

View File

@@ -1,7 +1,7 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { FOCUS_REGIONS } from 'common/hooks/interactionScopes';
import { useIsRegionFocused } from 'common/hooks/interactionScopes';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { rasterLayerAdded } from 'features/controlLayers/store/canvasSlice';
import {
@@ -25,7 +25,7 @@ export const StagingAreaToolbarAcceptButton = memo(() => {
const selectedEntityIdentifier = useAppSelector(selectSelectedEntityIdentifier);
const imageCount = useAppSelector(selectImageCount);
const shouldShowStagedImage = useStore(canvasManager.stagingArea.$shouldShowStagedImage);
const canvasFocus = useStore(FOCUS_REGIONS.$canvas);
const isCanvasFocused = useIsRegionFocused('canvas');
const { t } = useTranslation();
@@ -50,9 +50,9 @@ export const StagingAreaToolbarAcceptButton = memo(() => {
acceptSelected,
{
preventDefault: true,
enabled: canvasFocus.isFocused && shouldShowStagedImage && imageCount > 1,
enabled: isCanvasFocused && shouldShowStagedImage && imageCount > 1,
},
[canvasFocus, shouldShowStagedImage, imageCount]
[isCanvasFocused, shouldShowStagedImage, imageCount]
);
return (

View File

@@ -1,7 +1,7 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { FOCUS_REGIONS } from 'common/hooks/interactionScopes';
import { useIsRegionFocused } from 'common/hooks/interactionScopes';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import {
selectImageCount,
@@ -17,7 +17,7 @@ export const StagingAreaToolbarNextButton = memo(() => {
const canvasManager = useCanvasManager();
const imageCount = useAppSelector(selectImageCount);
const shouldShowStagedImage = useStore(canvasManager.stagingArea.$shouldShowStagedImage);
const canvasScope = useStore(FOCUS_REGIONS.$canvas);
const isCanvasFocused = useIsRegionFocused('canvas');
const { t } = useTranslation();
@@ -30,9 +30,9 @@ export const StagingAreaToolbarNextButton = memo(() => {
selectNext,
{
preventDefault: true,
enabled: canvasScope.isFocused && shouldShowStagedImage && imageCount > 1,
enabled: isCanvasFocused && shouldShowStagedImage && imageCount > 1,
},
[canvasScope, shouldShowStagedImage, imageCount]
[isCanvasFocused, shouldShowStagedImage, imageCount]
);
return (

View File

@@ -1,7 +1,7 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { FOCUS_REGIONS } from 'common/hooks/interactionScopes';
import { useIsRegionFocused } from 'common/hooks/interactionScopes';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import {
selectImageCount,
@@ -17,7 +17,7 @@ export const StagingAreaToolbarPrevButton = memo(() => {
const canvasManager = useCanvasManager();
const imageCount = useAppSelector(selectImageCount);
const shouldShowStagedImage = useStore(canvasManager.stagingArea.$shouldShowStagedImage);
const canvasScope = useStore(FOCUS_REGIONS.$canvas);
const isCanvasFocused = useIsRegionFocused('canvas');
const { t } = useTranslation();
@@ -30,9 +30,9 @@ export const StagingAreaToolbarPrevButton = memo(() => {
selectPrev,
{
preventDefault: true,
enabled: canvasScope.isFocused && shouldShowStagedImage && imageCount > 1,
enabled: isCanvasFocused && shouldShowStagedImage && imageCount > 1,
},
[canvasScope, shouldShowStagedImage, imageCount]
[isCanvasFocused, shouldShowStagedImage, imageCount]
);
return (

View File

@@ -1,6 +1,5 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { FOCUS_REGIONS } from 'common/hooks/interactionScopes';
import { useIsRegionFocused } from 'common/hooks/interactionScopes';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
@@ -11,50 +10,50 @@ import { PiArrowsOutBold } from 'react-icons/pi';
export const CanvasToolbarResetViewButton = memo(() => {
const { t } = useTranslation();
const canvasManager = useCanvasManager();
const canvasScope = useStore(FOCUS_REGIONS.$canvas);
const isCanvasFocused = useIsRegionFocused('canvas');
const imageViewer = useImageViewer();
useRegisteredHotkeys({
id: 'fitLayersToCanvas',
category: 'canvas',
callback: canvasManager.stage.fitLayersToStage,
options: { enabled: canvasScope.isFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [canvasScope, imageViewer.isOpen],
options: { enabled: isCanvasFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [isCanvasFocused, imageViewer.isOpen],
});
useRegisteredHotkeys({
id: 'fitBboxToCanvas',
category: 'canvas',
callback: canvasManager.stage.fitBboxToStage,
options: { enabled: canvasScope.isFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [canvasScope, imageViewer.isOpen],
options: { enabled: isCanvasFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [isCanvasFocused, imageViewer.isOpen],
});
useRegisteredHotkeys({
id: 'setZoomTo100Percent',
category: 'canvas',
callback: () => canvasManager.stage.setScale(1),
options: { enabled: canvasScope.isFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [canvasScope, imageViewer.isOpen],
options: { enabled: isCanvasFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [isCanvasFocused, imageViewer.isOpen],
});
useRegisteredHotkeys({
id: 'setZoomTo200Percent',
category: 'canvas',
callback: () => canvasManager.stage.setScale(2),
options: { enabled: canvasScope.isFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [canvasScope, imageViewer.isOpen],
options: { enabled: isCanvasFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [isCanvasFocused, imageViewer.isOpen],
});
useRegisteredHotkeys({
id: 'setZoomTo400Percent',
category: 'canvas',
callback: () => canvasManager.stage.setScale(4),
options: { enabled: canvasScope.isFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [canvasScope, imageViewer.isOpen],
options: { enabled: isCanvasFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [isCanvasFocused, imageViewer.isOpen],
});
useRegisteredHotkeys({
id: 'setZoomTo800Percent',
category: 'canvas',
callback: () => canvasManager.stage.setScale(8),
options: { enabled: canvasScope.isFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [canvasScope, imageViewer.isOpen],
options: { enabled: isCanvasFocused && !imageViewer.isOpen, preventDefault: true },
dependencies: [isCanvasFocused, imageViewer.isOpen],
});
return (