diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addCommitStagingAreaImageListener.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addCommitStagingAreaImageListener.ts index f1501b9533..85fbac41ec 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addCommitStagingAreaImageListener.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addCommitStagingAreaImageListener.ts @@ -1,6 +1,7 @@ import { logger } from 'app/logging/logger'; import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'; import { + $lastProgressEvent, layerAddedFromStagingArea, sessionStagingAreaImageAccepted, sessionStagingAreaReset, @@ -25,6 +26,9 @@ export const addStagingListeners = (startAppListening: AppStartListening) => { ); const { canceled } = await req.unwrap(); req.reset(); + + $lastProgressEvent.set(null); + if (canceled > 0) { log.debug(`Canceled ${canceled} canvas batches`); toast({ diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasControlAdapter.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasControlAdapter.ts index a69f4f3283..8b4208a6a6 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasControlAdapter.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasControlAdapter.ts @@ -76,11 +76,8 @@ export class CanvasControlAdapter { didDraw = true; } } else if (!this.image) { - this.image = await new CanvasImage(imageObject, { - onLoad: () => { - this.updateGroup(true); - }, - }); + this.image = await new CanvasImage(imageObject); + this.updateGroup(true); this.objectsGroup.add(this.image.konvaImageGroup); await this.image.updateImageSource(imageObject.image.name); } else if (!this.image.isLoading && !this.image.isError) { diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasImage.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasImage.ts index 9bc9f0778a..cb38a7136e 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasImage.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasImage.ts @@ -3,8 +3,7 @@ import { loadImage } from 'features/controlLayers/konva/util'; import type { ImageObject } from 'features/controlLayers/store/types'; import { t } from 'i18next'; import Konva from 'konva'; -import { getImageDTO as defaultGetImageDTO } from 'services/api/endpoints/images'; -import type { ImageDTO } from 'services/api/types'; +import { getImageDTO } from 'services/api/endpoints/images'; import { assert } from 'tsafe'; export class CanvasImage { @@ -17,23 +16,10 @@ export class CanvasImage { konvaImage: Konva.Image | null; // The image is loaded asynchronously, so it may not be available immediately isLoading: boolean; isError: boolean; - getImageDTO: (imageName: string) => Promise; - onLoading: () => void; - onLoad: (imageName: string, imageEl: HTMLImageElement) => void; - onError: () => void; lastImageObject: ImageObject; - constructor( - imageObject: ImageObject, - options?: { - getImageDTO?: (imageName: string) => Promise; - onLoading?: () => void; - onLoad?: (konvaImage: Konva.Image) => void; - onError?: () => void; - } - ) { - const { getImageDTO, onLoading, onLoad, onError } = options ?? {}; - const { id, width, height, x, y, filters } = imageObject; + constructor(imageObject: ImageObject) { + const { id, width, height, x, y } = imageObject; this.konvaImageGroup = new Konva.Group({ id, listening: false, x, y }); this.konvaPlaceholderGroup = new Konva.Group({ listening: false }); this.konvaPlaceholderRect = new Konva.Rect({ @@ -64,19 +50,23 @@ export class CanvasImage { this.konvaImage = null; this.isLoading = false; this.isError = false; - this.getImageDTO = getImageDTO ?? defaultGetImageDTO; - this.onLoading = function () { + this.lastImageObject = imageObject; + } + + async updateImageSource(imageName: string) { + try { this.isLoading = true; + this.konvaImageGroup.visible(true); + if (!this.konvaImage) { this.konvaPlaceholderGroup.visible(true); this.konvaPlaceholderText.text(t('common.loadingImage', 'Loading Image')); } - this.konvaImageGroup.visible(true); - if (onLoading) { - onLoading(); - } - }; - this.onLoad = function (imageName: string, imageEl: HTMLImageElement) { + + const imageDTO = await getImageDTO(imageName); + assert(imageDTO !== null, 'imageDTO is null'); + const imageEl = await loadImage(imageDTO.image_url); + if (this.konvaImage) { this.konvaImage.setAttrs({ image: imageEl, @@ -86,52 +76,31 @@ export class CanvasImage { id: this.id, listening: false, image: imageEl, - width, - height, + width: this.lastImageObject.width, + height: this.lastImageObject.height, }); this.konvaImageGroup.add(this.konvaImage); } - if (filters.length > 0) { + + if (this.lastImageObject.filters.length > 0) { this.konvaImage.cache(); - this.konvaImage.filters(filters.map((f) => FILTER_MAP[f])); + this.konvaImage.filters(this.lastImageObject.filters.map((f) => FILTER_MAP[f])); } else { this.konvaImage.clearCache(); this.konvaImage.filters([]); } + this.imageName = imageName; this.isLoading = false; this.isError = false; this.konvaPlaceholderGroup.visible(false); - this.konvaImageGroup.visible(true); - - if (onLoad) { - onLoad(this.konvaImage); - } - }; - this.onError = function () { + } catch { + this.konvaImage?.visible(false); this.imageName = null; this.isLoading = false; this.isError = true; - this.konvaPlaceholderGroup.visible(true); this.konvaPlaceholderText.text(t('common.imageFailedToLoad', 'Image Failed to Load')); - this.konvaImageGroup.visible(true); - - if (onError) { - onError(); - } - }; - this.lastImageObject = imageObject; - } - - async updateImageSource(imageName: string) { - try { - this.onLoading(); - const imageDTO = await this.getImageDTO(imageName); - assert(imageDTO !== null, 'imageDTO is null'); - const imageEl = await loadImage(imageDTO.image_url); - this.onLoad(imageName, imageEl); - } catch { - this.onError(); + this.konvaPlaceholderGroup.visible(true); } } diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts index 8c89e07c67..8d2d5b198c 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts @@ -352,9 +352,6 @@ export class CanvasManager { if (lastProgressEvent !== prevLastProgressEvent) { log.debug('Rendering progress image'); await this.preview.progressPreview.render(lastProgressEvent); - if (this.stateApi.getSession().isActive) { - this.preview.stagingArea.render(); - } } }); diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasProgressPreview.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasProgressPreview.ts index a37622da68..f2e814cefa 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasProgressPreview.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasProgressPreview.ts @@ -17,8 +17,9 @@ export class CanvasProgressPreview { async render(lastProgressEvent: InvocationDenoiseProgressEvent | null) { const bboxRect = this.manager.stateApi.getBbox().rect; + const session = this.manager.stateApi.getSession(); - if (lastProgressEvent) { + if (lastProgressEvent && session.isStaging) { const { invocation, step, progress_image } = lastProgressEvent; const { dataURL } = progress_image; const { x, y, width, height } = bboxRect; diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStagingArea.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStagingArea.ts index 4bee9409a5..eada1fadcb 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStagingArea.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStagingArea.ts @@ -25,16 +25,8 @@ export class CanvasStagingArea { if (this.selectedImage) { const { imageDTO, offsetX, offsetY } = this.selectedImage; - if (this.image) { - if (!this.image.isLoading && !this.image.isError && this.image.imageName !== imageDTO.image_name) { - this.image.konvaImageGroup.visible(false); - this.image.konvaImage?.width(imageDTO.width); - this.image.konvaImage?.height(imageDTO.height); - this.image.konvaImageGroup.x(bboxRect.x + offsetX); - this.image.konvaImageGroup.y(bboxRect.y + offsetY); - await this.image.updateImageSource(imageDTO.image_name); - } - } else { + + if (!this.image) { const { image_name, width, height } = imageDTO; this.image = new CanvasImage({ id: 'staging-area-image', @@ -51,13 +43,16 @@ export class CanvasStagingArea { }, }); this.group.add(this.image.konvaImageGroup); + } + + if (!this.image.isLoading && !this.image.isError && this.image.imageName !== imageDTO.image_name) { this.image.konvaImage?.width(imageDTO.width); this.image.konvaImage?.height(imageDTO.height); this.image.konvaImageGroup.x(bboxRect.x + offsetX); this.image.konvaImageGroup.y(bboxRect.y + offsetY); await this.image.updateImageSource(imageDTO.image_name); + this.manager.stateApi.resetLastProgressEvent(); } - this.manager.stateApi.resetLastProgressEvent(); this.image.konvaImageGroup.visible(shouldShowStagedImage); } else { this.image?.konvaImageGroup.visible(false);