Files
InvokeAI/invokeai/frontend/web/src/features/controlLayers/hooks/useNextPrevEntity.ts

77 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useAssertSingleton } from 'common/hooks/useAssertSingleton';
import { entitySelected } from 'features/controlLayers/store/canvasSlice';
import { selectAllEntities, selectCanvasSlice } from 'features/controlLayers/store/selectors';
import type { CanvasEntityState } from 'features/controlLayers/store/types';
import { getEntityIdentifier } from 'features/controlLayers/store/types';
import { useCallback } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
const selectNextEntityIdentifier = createMemoizedSelector(selectCanvasSlice, (canvas) => {
const selectedEntityIdentifier = canvas.selectedEntityIdentifier;
const allEntities = selectAllEntities(canvas);
let nextEntity: CanvasEntityState | null = null;
if (!selectedEntityIdentifier) {
nextEntity = allEntities[0] ?? null;
} else {
const selectedEntityIndex = allEntities.findIndex((entity) => entity.id === selectedEntityIdentifier.id);
nextEntity = allEntities[(selectedEntityIndex + 1) % allEntities.length] ?? null;
}
if (!nextEntity) {
return null;
}
return getEntityIdentifier(nextEntity);
});
const selectPrevEntityIdentifier = createMemoizedSelector(selectCanvasSlice, (canvas) => {
const selectedEntityIdentifier = canvas.selectedEntityIdentifier;
const allEntities = selectAllEntities(canvas);
let prevEntity: CanvasEntityState | null = null;
if (!selectedEntityIdentifier) {
prevEntity = allEntities[0] ?? null;
} else {
const selectedEntityIndex = allEntities.findIndex((entity) => entity.id === selectedEntityIdentifier.id);
prevEntity = allEntities[(selectedEntityIndex - 1 + allEntities.length) % allEntities.length] ?? null;
}
if (!prevEntity) {
return null;
}
return getEntityIdentifier(prevEntity);
});
export const useNextPrevEntityHotkeys = () => {
useAssertSingleton('useNextPrevEntityHotkeys');
const dispatch = useAppDispatch();
const nextEntityIdentifier = useAppSelector(selectNextEntityIdentifier);
const prevEntityIdentifier = useAppSelector(selectPrevEntityIdentifier);
const selectNextEntity = useCallback(() => {
if (nextEntityIdentifier) {
dispatch(entitySelected({ entityIdentifier: nextEntityIdentifier }));
}
}, [dispatch, nextEntityIdentifier]);
const selectPrevEntity = useCallback(() => {
if (prevEntityIdentifier) {
dispatch(entitySelected({ entityIdentifier: prevEntityIdentifier }));
}
}, [dispatch, prevEntityIdentifier]);
useHotkeys(
// “ === alt+[
['alt+[', '“'],
selectPrevEntity,
{ preventDefault: true, ignoreModifiers: true },
[selectPrevEntity]
);
useHotkeys(
// === alt+]
['alt+]', ''],
selectNextEntity,
{ preventDefault: true, ignoreModifiers: true },
[selectNextEntity]
);
};