mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat(ui): allow send-image-to-canvas to work when canvas is uninitialized
Add `useCanvasIsBusySafe()` hook. This is like `useCanvasIsBusy()`, but when the canvas is not initialized, it gracefully falls back to false instead of raising. Because app tabs are lazy-loaded, the canvas is not initialized until the user visits that tab. If the page loads up on the workflows tab, the canvas will be uninitialized until the user clicks on it. This graceful fallback behaviour allows actions like sending an image to canvas to work even when the canvas is not yet initialized. These actions are exposed in the image context menu, and previously were hidden when the canvas was not initialized. We can now show these actions and use them even when the canvas is uninitialized. - Add `useCanvasIsBusySafe()` hook - Use the new hook in the image context menu for send to canvas actions - Do not use `<CanvasManagerProviderGate />` in the image context menu (this was hiding the actions when canvas was uninitialized)
This commit is contained in:
@@ -1,16 +1,35 @@
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
|
||||
import { $false } from 'app/store/nanostores/util';
|
||||
import { useCanvasManager, useCanvasManagerSafe } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
|
||||
|
||||
/**
|
||||
* Returns a boolena indicating whether the canvas is busy:
|
||||
* - While staging
|
||||
* - While an entity is transforming
|
||||
* - While an entity is filtering
|
||||
* - While the canvas is doing some other long-running operation, like rasterizing a layer
|
||||
*
|
||||
* This hook will throw an error if the canvas manager is not initialized.
|
||||
*/
|
||||
export const useCanvasIsBusy = () => {
|
||||
const canvasManager = useCanvasManager();
|
||||
/**
|
||||
* Whether the canvas is busy:
|
||||
* - While staging
|
||||
* - While an entity is transforming
|
||||
* - While an entity is filtering
|
||||
* - While the canvas is doing some other long-running operation, like rasterizing a layer
|
||||
*/
|
||||
const isBusy = useStore(canvasManager.$isBusy);
|
||||
|
||||
return isBusy;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a boolena indicating whether the canvas is busy:
|
||||
* - While staging
|
||||
* - While an entity is transforming
|
||||
* - While an entity is filtering
|
||||
* - While the canvas is doing some other long-running operation, like rasterizing a layer
|
||||
*
|
||||
* This hook will fall back to false if the canvas manager is not initialized.
|
||||
*/
|
||||
export const useCanvasIsBusySafe = () => {
|
||||
const canvasManager = useCanvasManagerSafe();
|
||||
const isBusy = useStore(canvasManager?.$isBusy ?? $false);
|
||||
|
||||
return isBusy;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Menu, MenuButton, MenuItem, MenuList } from '@invoke-ai/ui-library';
|
||||
import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { SubMenuButtonContent, useSubMenu } from 'common/hooks/useSubMenu';
|
||||
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
|
||||
import { useCanvasIsBusySafe } from 'features/controlLayers/hooks/useCanvasIsBusy';
|
||||
import { selectIsSD3 } from 'features/controlLayers/store/paramsSlice';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useImageDTOContext } from 'features/gallery/contexts/ImageDTOContext';
|
||||
@@ -19,7 +19,7 @@ export const ImageMenuItemNewCanvasFromImageSubMenu = memo(() => {
|
||||
const store = useAppStore();
|
||||
const imageDTO = useImageDTOContext();
|
||||
const imageViewer = useImageViewer();
|
||||
const isBusy = useCanvasIsBusy();
|
||||
const isBusy = useCanvasIsBusySafe();
|
||||
const isSD3 = useAppSelector(selectIsSD3);
|
||||
|
||||
const onClickNewCanvasWithRasterLayerFromImage = useCallback(() => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { SubMenuButtonContent, useSubMenu } from 'common/hooks/useSubMenu';
|
||||
import { NewLayerIcon } from 'features/controlLayers/components/common/icons';
|
||||
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
|
||||
import { useCanvasIsBusySafe } from 'features/controlLayers/hooks/useCanvasIsBusy';
|
||||
import { selectIsFLUX, selectIsSD3 } from 'features/controlLayers/store/paramsSlice';
|
||||
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
|
||||
import { useImageDTOContext } from 'features/gallery/contexts/ImageDTOContext';
|
||||
@@ -21,7 +21,7 @@ export const ImageMenuItemNewLayerFromImageSubMenu = memo(() => {
|
||||
const store = useAppStore();
|
||||
const imageDTO = useImageDTOContext();
|
||||
const imageViewer = useImageViewer();
|
||||
const isBusy = useCanvasIsBusy();
|
||||
const isBusy = useCanvasIsBusySafe();
|
||||
const isFLUX = useAppSelector(selectIsFLUX);
|
||||
const isSD3 = useAppSelector(selectIsSD3);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { MenuDivider } from '@invoke-ai/ui-library';
|
||||
import { IconMenuItemGroup } from 'common/components/IconMenuItem';
|
||||
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
|
||||
import { ImageMenuItemChangeBoard } from 'features/gallery/components/ImageContextMenu/ImageMenuItemChangeBoard';
|
||||
import { ImageMenuItemCopy } from 'features/gallery/components/ImageContextMenu/ImageMenuItemCopy';
|
||||
import { ImageMenuItemDelete } from 'features/gallery/components/ImageContextMenu/ImageMenuItemDelete';
|
||||
@@ -38,10 +37,8 @@ const SingleSelectionMenuItems = ({ imageDTO }: SingleSelectionMenuItemsProps) =
|
||||
<ImageMenuItemMetadataRecallActions />
|
||||
<MenuDivider />
|
||||
<ImageMenuItemSendToUpscale />
|
||||
<CanvasManagerProviderGate>
|
||||
<ImageMenuItemNewCanvasFromImageSubMenu />
|
||||
<ImageMenuItemNewLayerFromImageSubMenu />
|
||||
</CanvasManagerProviderGate>
|
||||
<ImageMenuItemNewCanvasFromImageSubMenu />
|
||||
<ImageMenuItemNewLayerFromImageSubMenu />
|
||||
<MenuDivider />
|
||||
<ImageMenuItemChangeBoard />
|
||||
<ImageMenuItemStarUnstar />
|
||||
|
||||
Reference in New Issue
Block a user