mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): staging area image visibility toggle
This commit is contained in:
parent
788bad61d0
commit
cb19c1c370
@ -1,6 +1,8 @@
|
||||
import { Button, ButtonGroup, IconButton } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
$shouldShowStagedImage,
|
||||
stagingAreaImageAccepted,
|
||||
stagingAreaImageDiscarded,
|
||||
stagingAreaNextImageSelected,
|
||||
@ -11,7 +13,16 @@ import type { CanvasV2State } from 'features/controlLayers/store/types';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiArrowLeftBold, PiArrowRightBold, PiCheckBold, PiTrashSimpleBold, PiXBold } from 'react-icons/pi';
|
||||
import {
|
||||
PiArrowLeftBold,
|
||||
PiArrowRightBold,
|
||||
PiCheckBold,
|
||||
PiEyeBold,
|
||||
PiEyeSlashBold,
|
||||
PiFloppyDiskBold,
|
||||
PiTrashSimpleBold,
|
||||
PiXBold,
|
||||
} from 'react-icons/pi';
|
||||
|
||||
export const StagingAreaToolbar = memo(() => {
|
||||
const stagingArea = useAppSelector((s) => s.canvasV2.stagingArea);
|
||||
@ -31,6 +42,7 @@ type Props = {
|
||||
|
||||
export const StagingAreaToolbarContent = memo(({ stagingArea }: Props) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const shouldShowStagedImage = useStore($shouldShowStagedImage);
|
||||
const images = useMemo(() => stagingArea.images, [stagingArea]);
|
||||
const imageDTO = useMemo(() => {
|
||||
if (stagingArea.selectedImageIndex === null) {
|
||||
@ -74,6 +86,12 @@ export const StagingAreaToolbarContent = memo(({ stagingArea }: Props) => {
|
||||
dispatch(stagingAreaReset());
|
||||
}, [dispatch, stagingArea]);
|
||||
|
||||
const onToggleShouldShowStagedImage = useCallback(() => {
|
||||
$shouldShowStagedImage.set(!shouldShowStagedImage);
|
||||
}, [shouldShowStagedImage]);
|
||||
|
||||
const onSaveStagingImage = useCallback(() => {}, []);
|
||||
|
||||
useHotkeys(['left'], onPrev, {
|
||||
preventDefault: true,
|
||||
});
|
||||
@ -95,6 +113,7 @@ export const StagingAreaToolbarContent = memo(({ stagingArea }: Props) => {
|
||||
icon={<PiArrowLeftBold />}
|
||||
onClick={onPrev}
|
||||
colorScheme="invokeBlue"
|
||||
isDisabled={images.length <= 1 || !shouldShowStagedImage}
|
||||
/>
|
||||
<Button
|
||||
colorScheme="base"
|
||||
@ -107,6 +126,7 @@ export const StagingAreaToolbarContent = memo(({ stagingArea }: Props) => {
|
||||
icon={<PiArrowRightBold />}
|
||||
onClick={onNext}
|
||||
colorScheme="invokeBlue"
|
||||
isDisabled={images.length <= 1 || !shouldShowStagedImage}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
<ButtonGroup borderRadius="base" shadow="dark-lg">
|
||||
@ -117,14 +137,22 @@ export const StagingAreaToolbarContent = memo(({ stagingArea }: Props) => {
|
||||
onClick={onAccept}
|
||||
colorScheme="invokeBlue"
|
||||
/>
|
||||
{/* <IconButton
|
||||
<IconButton
|
||||
tooltip={shouldShowStagedImage ? t('unifiedCanvas.showResultsOn') : t('unifiedCanvas.showResultsOff')}
|
||||
aria-label={shouldShowStagedImage ? t('unifiedCanvas.showResultsOn') : t('unifiedCanvas.showResultsOff')}
|
||||
data-alert={!shouldShowStagedImage}
|
||||
icon={shouldShowStagedImage ? <PiEyeBold /> : <PiEyeSlashBold />}
|
||||
onClick={onToggleShouldShowStagedImage}
|
||||
colorScheme="invokeBlue"
|
||||
/>
|
||||
<IconButton
|
||||
tooltip={`${t('unifiedCanvas.saveToGallery')} (Shift+S)`}
|
||||
aria-label={t('unifiedCanvas.saveToGallery')}
|
||||
isDisabled={!imageDTO || !imageDTO.is_intermediate}
|
||||
icon={<PiFloppyDiskBold />}
|
||||
onClick={handleSaveToGallery}
|
||||
onClick={onSaveStagingImage}
|
||||
colorScheme="invokeBlue"
|
||||
/> */}
|
||||
/>
|
||||
<IconButton
|
||||
tooltip={`${t('unifiedCanvas.discardCurrent')}`}
|
||||
aria-label={t('unifiedCanvas.discardCurrent')}
|
||||
|
@ -52,6 +52,7 @@ export type StateApi = {
|
||||
getSelectedEntity: () => CanvasEntity | null;
|
||||
getSpaceKey: () => boolean;
|
||||
setSpaceKey: (val: boolean) => void;
|
||||
getShouldShowStagedImage: () => boolean;
|
||||
getBbox: () => CanvasV2State['bbox'];
|
||||
getSettings: () => CanvasV2State['settings'];
|
||||
onBrushLineAdded: (arg: BrushLineAddedArg, entityType: CanvasEntity['type']) => void;
|
||||
@ -275,7 +276,7 @@ export class KonvaNodeManager {
|
||||
}
|
||||
|
||||
renderStagingArea() {
|
||||
this.preview.stagingArea.render(this.stateApi.getStagingAreaState());
|
||||
this.preview.stagingArea.render(this.stateApi.getStagingAreaState(), this.stateApi.getShouldShowStagedImage());
|
||||
}
|
||||
|
||||
fitDocument() {
|
||||
|
@ -7,6 +7,7 @@ import { setStageEventHandlers } from 'features/controlLayers/konva/events';
|
||||
import { KonvaNodeManager, setNodeManager } from 'features/controlLayers/konva/nodeManager';
|
||||
import { updateBboxes } from 'features/controlLayers/konva/renderers/entityBbox';
|
||||
import {
|
||||
$shouldShowStagedImage,
|
||||
$stageAttrs,
|
||||
bboxChanged,
|
||||
brushWidthChanged,
|
||||
@ -303,6 +304,7 @@ export const initializeRenderer = (
|
||||
getMaskOpacity,
|
||||
getInpaintMaskState,
|
||||
getStagingAreaState,
|
||||
getShouldShowStagedImage: $shouldShowStagedImage.get,
|
||||
|
||||
// Read-write state
|
||||
setTool,
|
||||
@ -443,6 +445,9 @@ export const initializeRenderer = (
|
||||
|
||||
const unsubscribeRenderer = subscribe(renderCanvas);
|
||||
|
||||
// When we this flag, we need to render the staging area
|
||||
$shouldShowStagedImage.subscribe(manager.renderStagingArea.bind(manager));
|
||||
|
||||
logIfDebugging('First render of konva stage');
|
||||
// On first render, the document should be fit to the stage.
|
||||
manager.renderDocumentSizeOverlay();
|
||||
@ -454,6 +459,7 @@ export const initializeRenderer = (
|
||||
logIfDebugging('Cleaning up konva renderer');
|
||||
unsubscribeRenderer();
|
||||
cleanupListeners();
|
||||
$shouldShowStagedImage.off();
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
};
|
||||
|
@ -3,7 +3,6 @@ import type { CanvasV2State } from 'features/controlLayers/store/types';
|
||||
import Konva from 'konva';
|
||||
import { assert } from 'tsafe';
|
||||
|
||||
|
||||
export class CanvasStagingArea {
|
||||
group: Konva.Group;
|
||||
image: KonvaImage | null;
|
||||
@ -13,7 +12,7 @@ export class CanvasStagingArea {
|
||||
this.image = null;
|
||||
}
|
||||
|
||||
async render(stagingArea: CanvasV2State['stagingArea']) {
|
||||
async render(stagingArea: CanvasV2State['stagingArea'], shouldShowStagedImage: boolean) {
|
||||
if (!stagingArea || stagingArea.selectedImageIndex === null) {
|
||||
if (this.image) {
|
||||
this.image.destroy();
|
||||
@ -29,6 +28,7 @@ export class CanvasStagingArea {
|
||||
if (!this.image.isLoading && !this.image.isError && this.image.imageName !== imageDTO.image_name) {
|
||||
await this.image.updateImageSource(imageDTO.image_name);
|
||||
}
|
||||
this.image.konvaImageGroup.visible(shouldShowStagedImage);
|
||||
} else {
|
||||
const { image_name, width, height } = imageDTO;
|
||||
this.image = new KonvaImage({
|
||||
@ -49,6 +49,7 @@ export class CanvasStagingArea {
|
||||
});
|
||||
this.group.add(this.image.konvaImageGroup);
|
||||
await this.image.updateImageSource(imageDTO.image_name);
|
||||
this.image.konvaImageGroup.visible(shouldShowStagedImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -357,6 +357,7 @@ export const $stageAttrs = atom<StageAttrs>({
|
||||
height: 0,
|
||||
scale: 0,
|
||||
});
|
||||
export const $shouldShowStagedImage = atom(true);
|
||||
|
||||
export const canvasV2PersistConfig: PersistConfig<CanvasV2State> = {
|
||||
name: canvasV2Slice.name,
|
||||
|
Loading…
Reference in New Issue
Block a user