mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): de-jank staging area and progress images
This commit is contained in:
parent
ef4d6c26f6
commit
af815cf7eb
@ -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({
|
||||
|
@ -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) {
|
||||
|
@ -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<ImageDTO | null>;
|
||||
onLoading: () => void;
|
||||
onLoad: (imageName: string, imageEl: HTMLImageElement) => void;
|
||||
onError: () => void;
|
||||
lastImageObject: ImageObject;
|
||||
|
||||
constructor(
|
||||
imageObject: ImageObject,
|
||||
options?: {
|
||||
getImageDTO?: (imageName: string) => Promise<ImageDTO | null>;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user