mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
ui: pay back tech debt (#3896)
## What type of PR is this? (check all applicable) - [x] Refactor - [ ] Feature - [ ] Bug Fix - [ ] Optimization - [ ] Documentation Update - [ ] Community Node Submission ## Have you discussed this change with the InvokeAI team? - [ ] Yes - [x] No, because: n/a ## Have you updated all relevant documentation? - [ ] Yes - [x] No n/a ## Description Big cleanup: - improve & simplify the app logging - resolve all TS issues - resolve all circular dependencies - fix all lint/format issues ## QA Instructions, Screenshots, Recordings `yarn lint` passes: ![image](https://github.com/invoke-ai/InvokeAI/assets/4822129/7b763922-f00c-4b17-be23-2432da50f816) <!-- Please provide steps on how to test changes, any hardware or software specifications as well as any other pertinent information. --> ## Added/updated tests? - [ ] Yes - [x] No : n/a ## [optional] Are there any post deployment tasks we need to perform? bask in the glory of what *should* be a fully-passing frontend lint on this PR
This commit is contained in:
commit
075f9b3a7a
@ -5,6 +5,10 @@ patches/
|
|||||||
stats.html
|
stats.html
|
||||||
index.html
|
index.html
|
||||||
.yarn/
|
.yarn/
|
||||||
|
.yalc/
|
||||||
*.scss
|
*.scss
|
||||||
src/services/api/
|
src/services/api/
|
||||||
src/services/fixtures/*
|
src/services/fixtures/*
|
||||||
|
docs/
|
||||||
|
static/
|
||||||
|
src/theme/css/overlayscrollbars.css
|
||||||
|
@ -69,6 +69,7 @@
|
|||||||
"@mantine/core": "^6.0.14",
|
"@mantine/core": "^6.0.14",
|
||||||
"@mantine/form": "^6.0.15",
|
"@mantine/form": "^6.0.15",
|
||||||
"@mantine/hooks": "^6.0.14",
|
"@mantine/hooks": "^6.0.14",
|
||||||
|
"@nanostores/react": "^0.7.1",
|
||||||
"@reduxjs/toolkit": "^1.9.5",
|
"@reduxjs/toolkit": "^1.9.5",
|
||||||
"@roarr/browser-log-writer": "^1.1.5",
|
"@roarr/browser-log-writer": "^1.1.5",
|
||||||
"chakra-ui-contextmenu": "^1.0.5",
|
"chakra-ui-contextmenu": "^1.0.5",
|
||||||
|
@ -10,7 +10,7 @@ async function main() {
|
|||||||
);
|
);
|
||||||
const types = await openapiTS(OPENAPI_URL, {
|
const types = await openapiTS(OPENAPI_URL, {
|
||||||
exportType: true,
|
exportType: true,
|
||||||
transform: (schemaObject, metadata) => {
|
transform: (schemaObject) => {
|
||||||
if ('format' in schemaObject && schemaObject.format === 'binary') {
|
if ('format' in schemaObject && schemaObject.format === 'binary') {
|
||||||
return schemaObject.nullable ? 'Blob | null' : 'Blob';
|
return schemaObject.nullable ? 'Blob | null' : 'Blob';
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import FloatingParametersPanelButtons from 'features/ui/components/FloatingParam
|
|||||||
import InvokeTabs from 'features/ui/components/InvokeTabs';
|
import InvokeTabs from 'features/ui/components/InvokeTabs';
|
||||||
import ParametersDrawer from 'features/ui/components/ParametersDrawer';
|
import ParametersDrawer from 'features/ui/components/ParametersDrawer';
|
||||||
import i18n from 'i18n';
|
import i18n from 'i18n';
|
||||||
|
import { size } from 'lodash-es';
|
||||||
import { ReactNode, memo, useEffect } from 'react';
|
import { ReactNode, memo, useEffect } from 'react';
|
||||||
import UpdateImageBoardModal from '../../features/gallery/components/Boards/UpdateImageBoardModal';
|
import UpdateImageBoardModal from '../../features/gallery/components/Boards/UpdateImageBoardModal';
|
||||||
import GlobalHotkeys from './GlobalHotkeys';
|
import GlobalHotkeys from './GlobalHotkeys';
|
||||||
@ -29,8 +30,7 @@ interface Props {
|
|||||||
const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => {
|
const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => {
|
||||||
const language = useAppSelector(languageSelector);
|
const language = useAppSelector(languageSelector);
|
||||||
|
|
||||||
const log = useLogger();
|
const logger = useLogger();
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -38,9 +38,11 @@ const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => {
|
|||||||
}, [language]);
|
}, [language]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
log.info({ namespace: 'App', data: config }, 'Received config');
|
if (size(config)) {
|
||||||
dispatch(configChanged(config));
|
logger.info({ namespace: 'App', config }, 'Received config');
|
||||||
}, [dispatch, config, log]);
|
dispatch(configChanged(config));
|
||||||
|
}
|
||||||
|
}, [dispatch, config, logger]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(appStarted());
|
dispatch(appStarted());
|
||||||
|
@ -27,7 +27,7 @@ const STYLES: ChakraProps['sx'] = {
|
|||||||
|
|
||||||
const DragPreview = (props: OverlayDragImageProps) => {
|
const DragPreview = (props: OverlayDragImageProps) => {
|
||||||
if (!props.dragData) {
|
if (!props.dragData) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.dragData.payloadType === 'IMAGE_DTO') {
|
if (props.dragData.payloadType === 'IMAGE_DTO') {
|
||||||
|
@ -39,7 +39,6 @@ const ImageDndContext = (props: ImageDndContextProps) => {
|
|||||||
const handleDragEnd = useCallback(
|
const handleDragEnd = useCallback(
|
||||||
(event: DragEndEvent) => {
|
(event: DragEndEvent) => {
|
||||||
console.log('dragEnd', event.active.data.current);
|
console.log('dragEnd', event.active.data.current);
|
||||||
const activeData = event.active.data.current;
|
|
||||||
const overData = event.over?.data.current;
|
const overData = event.over?.data.current;
|
||||||
if (!activeDragData || !overData) {
|
if (!activeDragData || !overData) {
|
||||||
return;
|
return;
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
useDraggable as useOriginalDraggable,
|
useDraggable as useOriginalDraggable,
|
||||||
useDroppable as useOriginalDroppable,
|
useDroppable as useOriginalDroppable,
|
||||||
} from '@dnd-kit/core';
|
} from '@dnd-kit/core';
|
||||||
import { BoardId } from 'features/gallery/store/gallerySlice';
|
import { BoardId } from 'features/gallery/store/types';
|
||||||
import { ImageDTO } from 'services/api/types';
|
import { ImageDTO } from 'services/api/types';
|
||||||
|
|
||||||
type BaseDropData = {
|
type BaseDropData = {
|
||||||
|
@ -1,28 +1,10 @@
|
|||||||
import { useToast, UseToastOptions } from '@chakra-ui/react';
|
import { useToast } from '@chakra-ui/react';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { toastQueueSelector } from 'features/system/store/systemSelectors';
|
import { toastQueueSelector } from 'features/system/store/systemSelectors';
|
||||||
import { addToast, clearToastQueue } from 'features/system/store/systemSlice';
|
import { addToast, clearToastQueue } from 'features/system/store/systemSlice';
|
||||||
|
import { MakeToastArg, makeToast } from 'features/system/util/makeToast';
|
||||||
import { useCallback, useEffect } from 'react';
|
import { useCallback, useEffect } from 'react';
|
||||||
|
|
||||||
export type MakeToastArg = string | UseToastOptions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a toast from a string or a UseToastOptions object.
|
|
||||||
* If a string is passed, the toast will have the status 'info' and will be closable with a duration of 2500ms.
|
|
||||||
*/
|
|
||||||
export const makeToast = (arg: MakeToastArg): UseToastOptions => {
|
|
||||||
if (typeof arg === 'string') {
|
|
||||||
return {
|
|
||||||
title: arg,
|
|
||||||
status: 'info',
|
|
||||||
isClosable: true,
|
|
||||||
duration: 2500,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return { status: 'info', isClosable: true, duration: 2500, ...arg };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logical component. Watches the toast queue and makes toasts when the queue is not empty.
|
* Logical component. Watches the toast queue and makes toasts when the queue is not empty.
|
||||||
* @returns null
|
* @returns null
|
||||||
|
@ -1,66 +1,2 @@
|
|||||||
// zod needs the array to be `as const` to infer the type correctly
|
|
||||||
|
|
||||||
import { SchedulerParam } from 'features/parameters/types/parameterSchemas';
|
|
||||||
|
|
||||||
// this is the source of the `SchedulerParam` type, which is generated by zod
|
|
||||||
export const SCHEDULER_NAMES_AS_CONST = [
|
|
||||||
'euler',
|
|
||||||
'deis',
|
|
||||||
'ddim',
|
|
||||||
'ddpm',
|
|
||||||
'dpmpp_2s',
|
|
||||||
'dpmpp_2m',
|
|
||||||
'dpmpp_2m_sde',
|
|
||||||
'dpmpp_sde',
|
|
||||||
'heun',
|
|
||||||
'kdpm_2',
|
|
||||||
'lms',
|
|
||||||
'pndm',
|
|
||||||
'unipc',
|
|
||||||
'euler_k',
|
|
||||||
'dpmpp_2s_k',
|
|
||||||
'dpmpp_2m_k',
|
|
||||||
'dpmpp_2m_sde_k',
|
|
||||||
'dpmpp_sde_k',
|
|
||||||
'heun_k',
|
|
||||||
'lms_k',
|
|
||||||
'euler_a',
|
|
||||||
'kdpm_2_a',
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export const DEFAULT_SCHEDULER_NAME = 'euler';
|
|
||||||
|
|
||||||
export const SCHEDULER_NAMES: SchedulerParam[] = [...SCHEDULER_NAMES_AS_CONST];
|
|
||||||
|
|
||||||
export const SCHEDULER_LABEL_MAP: Record<SchedulerParam, string> = {
|
|
||||||
euler: 'Euler',
|
|
||||||
deis: 'DEIS',
|
|
||||||
ddim: 'DDIM',
|
|
||||||
ddpm: 'DDPM',
|
|
||||||
dpmpp_sde: 'DPM++ SDE',
|
|
||||||
dpmpp_2s: 'DPM++ 2S',
|
|
||||||
dpmpp_2m: 'DPM++ 2M',
|
|
||||||
dpmpp_2m_sde: 'DPM++ 2M SDE',
|
|
||||||
heun: 'Heun',
|
|
||||||
kdpm_2: 'KDPM 2',
|
|
||||||
lms: 'LMS',
|
|
||||||
pndm: 'PNDM',
|
|
||||||
unipc: 'UniPC',
|
|
||||||
euler_k: 'Euler Karras',
|
|
||||||
dpmpp_sde_k: 'DPM++ SDE Karras',
|
|
||||||
dpmpp_2s_k: 'DPM++ 2S Karras',
|
|
||||||
dpmpp_2m_k: 'DPM++ 2M Karras',
|
|
||||||
dpmpp_2m_sde_k: 'DPM++ 2M SDE Karras',
|
|
||||||
heun_k: 'Heun Karras',
|
|
||||||
lms_k: 'LMS Karras',
|
|
||||||
euler_a: 'Euler Ancestral',
|
|
||||||
kdpm_2_a: 'KDPM 2 Ancestral',
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Scheduler = (typeof SCHEDULER_NAMES)[number];
|
|
||||||
|
|
||||||
export const NUMPY_RAND_MIN = 0;
|
export const NUMPY_RAND_MIN = 0;
|
||||||
|
|
||||||
export const NUMPY_RAND_MAX = 2147483647;
|
export const NUMPY_RAND_MAX = 2147483647;
|
||||||
|
|
||||||
export const NODE_MIN_WIDTH = 250;
|
|
||||||
|
46
invokeai/frontend/web/src/app/logging/logger.ts
Normal file
46
invokeai/frontend/web/src/app/logging/logger.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { createLogWriter } from '@roarr/browser-log-writer';
|
||||||
|
import { atom } from 'nanostores';
|
||||||
|
import { Logger, ROARR, Roarr } from 'roarr';
|
||||||
|
|
||||||
|
ROARR.write = createLogWriter();
|
||||||
|
|
||||||
|
export const BASE_CONTEXT = {};
|
||||||
|
export const log = Roarr.child(BASE_CONTEXT);
|
||||||
|
|
||||||
|
export const $logger = atom<Logger>(Roarr.child(BASE_CONTEXT));
|
||||||
|
|
||||||
|
type LoggerNamespace =
|
||||||
|
| 'images'
|
||||||
|
| 'models'
|
||||||
|
| 'config'
|
||||||
|
| 'canvas'
|
||||||
|
| 'txt2img'
|
||||||
|
| 'img2img'
|
||||||
|
| 'nodes'
|
||||||
|
| 'system'
|
||||||
|
| 'socketio'
|
||||||
|
| 'session';
|
||||||
|
|
||||||
|
export const logger = (namespace: LoggerNamespace) =>
|
||||||
|
$logger.get().child({ namespace });
|
||||||
|
|
||||||
|
export const VALID_LOG_LEVELS = [
|
||||||
|
'trace',
|
||||||
|
'debug',
|
||||||
|
'info',
|
||||||
|
'warn',
|
||||||
|
'error',
|
||||||
|
'fatal',
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number];
|
||||||
|
|
||||||
|
// Translate human-readable log levels to numbers, used for log filtering
|
||||||
|
export const LOG_LEVEL_MAP: Record<InvokeLogLevel, number> = {
|
||||||
|
trace: 10,
|
||||||
|
debug: 20,
|
||||||
|
info: 30,
|
||||||
|
warn: 40,
|
||||||
|
error: 50,
|
||||||
|
fatal: 60,
|
||||||
|
};
|
@ -1,48 +1,19 @@
|
|||||||
|
import { useStore } from '@nanostores/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { createLogWriter } from '@roarr/browser-log-writer';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { LogLevelName, ROARR, Roarr } from 'roarr';
|
import { ROARR, Roarr } from 'roarr';
|
||||||
import { createLogWriter } from '@roarr/browser-log-writer';
|
import { $logger, BASE_CONTEXT, LOG_LEVEL_MAP } from './logger';
|
||||||
|
|
||||||
// Base logging context includes only the package name
|
|
||||||
const baseContext = { package: '@invoke-ai/invoke-ai-ui' };
|
|
||||||
|
|
||||||
// Create browser log writer
|
|
||||||
ROARR.write = createLogWriter();
|
|
||||||
|
|
||||||
// Module-scoped logger - can be imported and used anywhere
|
|
||||||
export let log = Roarr.child(baseContext);
|
|
||||||
|
|
||||||
// Translate human-readable log levels to numbers, used for log filtering
|
|
||||||
export const LOG_LEVEL_MAP: Record<LogLevelName, number> = {
|
|
||||||
trace: 10,
|
|
||||||
debug: 20,
|
|
||||||
info: 30,
|
|
||||||
warn: 40,
|
|
||||||
error: 50,
|
|
||||||
fatal: 60,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const VALID_LOG_LEVELS = [
|
|
||||||
'trace',
|
|
||||||
'debug',
|
|
||||||
'info',
|
|
||||||
'warn',
|
|
||||||
'error',
|
|
||||||
'fatal',
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number];
|
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
systemSelector,
|
systemSelector,
|
||||||
(system) => {
|
(system) => {
|
||||||
const { app_version, consoleLogLevel, shouldLogToConsole } = system;
|
const { consoleLogLevel, shouldLogToConsole } = system;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
version: app_version,
|
|
||||||
consoleLogLevel,
|
consoleLogLevel,
|
||||||
shouldLogToConsole,
|
shouldLogToConsole,
|
||||||
};
|
};
|
||||||
@ -55,8 +26,7 @@ const selector = createSelector(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const useLogger = () => {
|
export const useLogger = () => {
|
||||||
const { version, consoleLogLevel, shouldLogToConsole } =
|
const { consoleLogLevel, shouldLogToConsole } = useAppSelector(selector);
|
||||||
useAppSelector(selector);
|
|
||||||
|
|
||||||
// The provided Roarr browser log writer uses localStorage to config logging to console
|
// The provided Roarr browser log writer uses localStorage to config logging to console
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -78,17 +48,16 @@ export const useLogger = () => {
|
|||||||
|
|
||||||
// Update the module-scoped logger context as needed
|
// Update the module-scoped logger context as needed
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// TODO: type this properly
|
||||||
|
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const newContext: Record<string, any> = {
|
const newContext: Record<string, any> = {
|
||||||
...baseContext,
|
...BASE_CONTEXT,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (version) {
|
$logger.set(Roarr.child(newContext));
|
||||||
newContext.version = version;
|
}, []);
|
||||||
}
|
|
||||||
|
|
||||||
log = Roarr.child(newContext);
|
const logger = useStore($logger);
|
||||||
}, [version]);
|
|
||||||
|
|
||||||
// Use the logger within components - no different than just importing it directly
|
return logger;
|
||||||
return log;
|
|
||||||
};
|
};
|
||||||
|
@ -12,7 +12,7 @@ import { defaultsDeep } from 'lodash-es';
|
|||||||
import { UnserializeFunction } from 'redux-remember';
|
import { UnserializeFunction } from 'redux-remember';
|
||||||
|
|
||||||
const initialStates: {
|
const initialStates: {
|
||||||
[key: string]: any;
|
[key: string]: object; // TODO: type this properly
|
||||||
} = {
|
} = {
|
||||||
canvas: initialCanvasState,
|
canvas: initialCanvasState,
|
||||||
gallery: initialGalleryState,
|
gallery: initialGalleryState,
|
||||||
|
@ -8,10 +8,11 @@ import {
|
|||||||
|
|
||||||
import type { AppDispatch, RootState } from '../../store';
|
import type { AppDispatch, RootState } from '../../store';
|
||||||
import { addCommitStagingAreaImageListener } from './listeners/addCommitStagingAreaImageListener';
|
import { addCommitStagingAreaImageListener } from './listeners/addCommitStagingAreaImageListener';
|
||||||
|
import { addFirstListImagesListener } from './listeners/addFirstListImagesListener.ts';
|
||||||
import { addAppConfigReceivedListener } from './listeners/appConfigReceived';
|
import { addAppConfigReceivedListener } from './listeners/appConfigReceived';
|
||||||
import { addAppStartedListener } from './listeners/appStarted';
|
import { addAppStartedListener } from './listeners/appStarted';
|
||||||
import { addBoardIdSelectedListener } from './listeners/boardIdSelected';
|
|
||||||
import { addDeleteBoardAndImagesFulfilledListener } from './listeners/boardAndImagesDeleted';
|
import { addDeleteBoardAndImagesFulfilledListener } from './listeners/boardAndImagesDeleted';
|
||||||
|
import { addBoardIdSelectedListener } from './listeners/boardIdSelected';
|
||||||
import { addCanvasCopiedToClipboardListener } from './listeners/canvasCopiedToClipboard';
|
import { addCanvasCopiedToClipboardListener } from './listeners/canvasCopiedToClipboard';
|
||||||
import { addCanvasDownloadedAsImageListener } from './listeners/canvasDownloadedAsImage';
|
import { addCanvasDownloadedAsImageListener } from './listeners/canvasDownloadedAsImage';
|
||||||
import { addCanvasMergedListener } from './listeners/canvasMerged';
|
import { addCanvasMergedListener } from './listeners/canvasMerged';
|
||||||
@ -34,10 +35,6 @@ import {
|
|||||||
addImageRemovedFromBoardRejectedListener,
|
addImageRemovedFromBoardRejectedListener,
|
||||||
} from './listeners/imageRemovedFromBoard';
|
} from './listeners/imageRemovedFromBoard';
|
||||||
import { addImageToDeleteSelectedListener } from './listeners/imageToDeleteSelected';
|
import { addImageToDeleteSelectedListener } from './listeners/imageToDeleteSelected';
|
||||||
import {
|
|
||||||
addImageUpdatedFulfilledListener,
|
|
||||||
addImageUpdatedRejectedListener,
|
|
||||||
} from './listeners/imageUpdated';
|
|
||||||
import {
|
import {
|
||||||
addImageUploadedFulfilledListener,
|
addImageUploadedFulfilledListener,
|
||||||
addImageUploadedRejectedListener,
|
addImageUploadedRejectedListener,
|
||||||
@ -69,17 +66,15 @@ import { addGraphExecutionStateCompleteEventListener as addGraphExecutionStateCo
|
|||||||
import { addInvocationCompleteEventListener as addInvocationCompleteListener } from './listeners/socketio/socketInvocationComplete';
|
import { addInvocationCompleteEventListener as addInvocationCompleteListener } from './listeners/socketio/socketInvocationComplete';
|
||||||
import { addInvocationErrorEventListener as addInvocationErrorListener } from './listeners/socketio/socketInvocationError';
|
import { addInvocationErrorEventListener as addInvocationErrorListener } from './listeners/socketio/socketInvocationError';
|
||||||
import { addInvocationStartedEventListener as addInvocationStartedListener } from './listeners/socketio/socketInvocationStarted';
|
import { addInvocationStartedEventListener as addInvocationStartedListener } from './listeners/socketio/socketInvocationStarted';
|
||||||
|
import { addModelLoadEventListener } from './listeners/socketio/socketModelLoad';
|
||||||
import { addSocketSubscribedEventListener as addSocketSubscribedListener } from './listeners/socketio/socketSubscribed';
|
import { addSocketSubscribedEventListener as addSocketSubscribedListener } from './listeners/socketio/socketSubscribed';
|
||||||
import { addSocketUnsubscribedEventListener as addSocketUnsubscribedListener } from './listeners/socketio/socketUnsubscribed';
|
import { addSocketUnsubscribedEventListener as addSocketUnsubscribedListener } from './listeners/socketio/socketUnsubscribed';
|
||||||
import { addStagingAreaImageSavedListener } from './listeners/stagingAreaImageSaved';
|
import { addStagingAreaImageSavedListener } from './listeners/stagingAreaImageSaved';
|
||||||
|
import { addUpscaleRequestedListener } from './listeners/upscaleRequested';
|
||||||
import { addUserInvokedCanvasListener } from './listeners/userInvokedCanvas';
|
import { addUserInvokedCanvasListener } from './listeners/userInvokedCanvas';
|
||||||
import { addUserInvokedImageToImageListener } from './listeners/userInvokedImageToImage';
|
import { addUserInvokedImageToImageListener } from './listeners/userInvokedImageToImage';
|
||||||
import { addUserInvokedNodesListener } from './listeners/userInvokedNodes';
|
import { addUserInvokedNodesListener } from './listeners/userInvokedNodes';
|
||||||
import { addUserInvokedTextToImageListener } from './listeners/userInvokedTextToImage';
|
import { addUserInvokedTextToImageListener } from './listeners/userInvokedTextToImage';
|
||||||
import { addModelLoadStartedEventListener } from './listeners/socketio/socketModelLoadStarted';
|
|
||||||
import { addModelLoadCompletedEventListener } from './listeners/socketio/socketModelLoadCompleted';
|
|
||||||
import { addUpscaleRequestedListener } from './listeners/upscaleRequested';
|
|
||||||
import { addFirstListImagesListener } from './listeners/addFirstListImagesListener.ts';
|
|
||||||
|
|
||||||
export const listenerMiddleware = createListenerMiddleware();
|
export const listenerMiddleware = createListenerMiddleware();
|
||||||
|
|
||||||
@ -109,10 +104,6 @@ export type AppListenerEffect = ListenerEffect<
|
|||||||
addImageUploadedFulfilledListener();
|
addImageUploadedFulfilledListener();
|
||||||
addImageUploadedRejectedListener();
|
addImageUploadedRejectedListener();
|
||||||
|
|
||||||
// Image updated
|
|
||||||
addImageUpdatedFulfilledListener();
|
|
||||||
addImageUpdatedRejectedListener();
|
|
||||||
|
|
||||||
// Image selected
|
// Image selected
|
||||||
addInitialImageSelectedListener();
|
addInitialImageSelectedListener();
|
||||||
|
|
||||||
@ -161,8 +152,7 @@ addSocketConnectedListener();
|
|||||||
addSocketDisconnectedListener();
|
addSocketDisconnectedListener();
|
||||||
addSocketSubscribedListener();
|
addSocketSubscribedListener();
|
||||||
addSocketUnsubscribedListener();
|
addSocketUnsubscribedListener();
|
||||||
addModelLoadStartedEventListener();
|
addModelLoadEventListener();
|
||||||
addModelLoadCompletedEventListener();
|
|
||||||
|
|
||||||
// Session Created
|
// Session Created
|
||||||
addSessionCreatedPendingListener();
|
addSessionCreatedPendingListener();
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import { startAppListening } from '..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import { commitStagingAreaImage } from 'features/canvas/store/canvasSlice';
|
import { commitStagingAreaImage } from 'features/canvas/store/canvasSlice';
|
||||||
import { sessionCanceled } from 'services/api/thunks/session';
|
import { sessionCanceled } from 'services/api/thunks/session';
|
||||||
|
import { startAppListening } from '..';
|
||||||
const moduleLog = log.child({ namespace: 'canvas' });
|
|
||||||
|
|
||||||
export const addCommitStagingAreaImageListener = () => {
|
export const addCommitStagingAreaImageListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: commitStagingAreaImage,
|
actionCreator: commitStagingAreaImage,
|
||||||
effect: async (action, { dispatch, getState }) => {
|
effect: async (action, { dispatch, getState }) => {
|
||||||
|
const log = logger('canvas');
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { sessionId: session_id, isProcessing } = state.system;
|
const { sessionId: session_id, isProcessing } = state.system;
|
||||||
const canvasSessionId = action.payload;
|
const canvasSessionId = action.payload;
|
||||||
@ -19,17 +18,15 @@ export const addCommitStagingAreaImageListener = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!canvasSessionId) {
|
if (!canvasSessionId) {
|
||||||
moduleLog.debug('No canvas session, skipping cancel');
|
log.debug('No canvas session, skipping cancel');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canvasSessionId !== session_id) {
|
if (canvasSessionId !== session_id) {
|
||||||
moduleLog.debug(
|
log.debug(
|
||||||
{
|
{
|
||||||
data: {
|
canvasSessionId,
|
||||||
canvasSessionId,
|
session_id,
|
||||||
session_id,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
'Canvas session does not match global session, skipping cancel'
|
'Canvas session does not match global session, skipping cancel'
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { createAction } from '@reduxjs/toolkit';
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
import {
|
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
||||||
IMAGE_CATEGORIES,
|
import { IMAGE_CATEGORIES } from 'features/gallery/store/types';
|
||||||
imageSelected,
|
|
||||||
} from 'features/gallery/store/gallerySlice';
|
|
||||||
import {
|
import {
|
||||||
ImageCache,
|
ImageCache,
|
||||||
getListImagesUrl,
|
getListImagesUrl,
|
||||||
@ -17,7 +15,7 @@ export const addFirstListImagesListener = () => {
|
|||||||
matcher: imagesApi.endpoints.listImages.matchFulfilled,
|
matcher: imagesApi.endpoints.listImages.matchFulfilled,
|
||||||
effect: async (
|
effect: async (
|
||||||
action,
|
action,
|
||||||
{ getState, dispatch, unsubscribe, cancelActiveListeners }
|
{ dispatch, unsubscribe, cancelActiveListeners }
|
||||||
) => {
|
) => {
|
||||||
// Only run this listener on the first listImages request for no-board images
|
// Only run this listener on the first listImages request for no-board images
|
||||||
if (
|
if (
|
||||||
|
@ -6,10 +6,7 @@ export const appStarted = createAction('app/appStarted');
|
|||||||
export const addAppStartedListener = () => {
|
export const addAppStartedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: appStarted,
|
actionCreator: appStarted,
|
||||||
effect: async (
|
effect: async (action, { unsubscribe, cancelActiveListeners }) => {
|
||||||
action,
|
|
||||||
{ getState, dispatch, unsubscribe, cancelActiveListeners }
|
|
||||||
) => {
|
|
||||||
// this should only run once
|
// this should only run once
|
||||||
cancelActiveListeners();
|
cancelActiveListeners();
|
||||||
unsubscribe();
|
unsubscribe();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { resetCanvas } from 'features/canvas/store/canvasSlice';
|
import { resetCanvas } from 'features/canvas/store/canvasSlice';
|
||||||
import { controlNetReset } from 'features/controlNet/store/controlNetSlice';
|
import { controlNetReset } from 'features/controlNet/store/controlNetSlice';
|
||||||
import { getImageUsage } from 'features/imageDeletion/store/imageDeletionSlice';
|
import { getImageUsage } from 'features/imageDeletion/store/imageDeletionSelectors';
|
||||||
import { nodeEditorReset } from 'features/nodes/store/nodesSlice';
|
import { nodeEditorReset } from 'features/nodes/store/nodesSlice';
|
||||||
import { clearInitialImage } from 'features/parameters/store/generationSlice';
|
import { clearInitialImage } from 'features/parameters/store/generationSlice';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
@ -9,8 +9,8 @@ import { boardsApi } from '../../../../../services/api/endpoints/boards';
|
|||||||
export const addDeleteBoardAndImagesFulfilledListener = () => {
|
export const addDeleteBoardAndImagesFulfilledListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: boardsApi.endpoints.deleteBoardAndImages.matchFulfilled,
|
matcher: boardsApi.endpoints.deleteBoardAndImages.matchFulfilled,
|
||||||
effect: async (action, { dispatch, getState, condition }) => {
|
effect: async (action, { dispatch, getState }) => {
|
||||||
const { board_id, deleted_board_images, deleted_images } = action.payload;
|
const { deleted_images } = action.payload;
|
||||||
|
|
||||||
// Remove all deleted images from the UI
|
// Remove all deleted images from the UI
|
||||||
|
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { isAnyOf } from '@reduxjs/toolkit';
|
||||||
import {
|
import {
|
||||||
ASSETS_CATEGORIES,
|
|
||||||
IMAGE_CATEGORIES,
|
|
||||||
boardIdSelected,
|
boardIdSelected,
|
||||||
galleryViewChanged,
|
galleryViewChanged,
|
||||||
imageSelected,
|
imageSelected,
|
||||||
} from 'features/gallery/store/gallerySlice';
|
} from 'features/gallery/store/gallerySlice';
|
||||||
|
import {
|
||||||
|
ASSETS_CATEGORIES,
|
||||||
|
IMAGE_CATEGORIES,
|
||||||
|
} from 'features/gallery/store/types';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
import { isAnyOf } from '@reduxjs/toolkit';
|
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'boards' });
|
|
||||||
|
|
||||||
export const addBoardIdSelectedListener = () => {
|
export const addBoardIdSelectedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
import { canvasCopiedToClipboard } from 'features/canvas/store/actions';
|
import { canvasCopiedToClipboard } from 'features/canvas/store/actions';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
import { log } from 'app/logging/useLogger';
|
import { $logger } from 'app/logging/logger';
|
||||||
import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob';
|
import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob';
|
||||||
import { addToast } from 'features/system/store/systemSlice';
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
import { copyBlobToClipboard } from 'features/canvas/util/copyBlobToClipboard';
|
import { copyBlobToClipboard } from 'features/canvas/util/copyBlobToClipboard';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'canvasCopiedToClipboardListener' });
|
|
||||||
|
|
||||||
export const addCanvasCopiedToClipboardListener = () => {
|
export const addCanvasCopiedToClipboardListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: canvasCopiedToClipboard,
|
actionCreator: canvasCopiedToClipboard,
|
||||||
effect: async (action, { dispatch, getState }) => {
|
effect: async (action, { dispatch, getState }) => {
|
||||||
|
const moduleLog = $logger
|
||||||
|
.get()
|
||||||
|
.child({ namespace: 'canvasCopiedToClipboardListener' });
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
const blob = await getBaseLayerBlob(state);
|
const blob = await getBaseLayerBlob(state);
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
import { canvasDownloadedAsImage } from 'features/canvas/store/actions';
|
import { canvasDownloadedAsImage } from 'features/canvas/store/actions';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
import { log } from 'app/logging/useLogger';
|
import { $logger } from 'app/logging/logger';
|
||||||
import { downloadBlob } from 'features/canvas/util/downloadBlob';
|
import { downloadBlob } from 'features/canvas/util/downloadBlob';
|
||||||
import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob';
|
import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob';
|
||||||
import { addToast } from 'features/system/store/systemSlice';
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'canvasSavedToGalleryListener' });
|
|
||||||
|
|
||||||
export const addCanvasDownloadedAsImageListener = () => {
|
export const addCanvasDownloadedAsImageListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: canvasDownloadedAsImage,
|
actionCreator: canvasDownloadedAsImage,
|
||||||
effect: async (action, { dispatch, getState }) => {
|
effect: async (action, { dispatch, getState }) => {
|
||||||
|
const moduleLog = $logger
|
||||||
|
.get()
|
||||||
|
.child({ namespace: 'canvasSavedToGalleryListener' });
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
const blob = await getBaseLayerBlob(state);
|
const blob = await getBaseLayerBlob(state);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { $logger } from 'app/logging/logger';
|
||||||
import { canvasMerged } from 'features/canvas/store/actions';
|
import { canvasMerged } from 'features/canvas/store/actions';
|
||||||
import { setMergedCanvas } from 'features/canvas/store/canvasSlice';
|
import { setMergedCanvas } from 'features/canvas/store/canvasSlice';
|
||||||
import { getFullBaseLayerBlob } from 'features/canvas/util/getFullBaseLayerBlob';
|
import { getFullBaseLayerBlob } from 'features/canvas/util/getFullBaseLayerBlob';
|
||||||
@ -7,12 +7,13 @@ import { addToast } from 'features/system/store/systemSlice';
|
|||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'canvasCopiedToClipboardListener' });
|
|
||||||
|
|
||||||
export const addCanvasMergedListener = () => {
|
export const addCanvasMergedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: canvasMerged,
|
actionCreator: canvasMerged,
|
||||||
effect: async (action, { dispatch, getState, take }) => {
|
effect: async (action, { dispatch }) => {
|
||||||
|
const moduleLog = $logger
|
||||||
|
.get()
|
||||||
|
.child({ namespace: 'canvasCopiedToClipboardListener' });
|
||||||
const blob = await getFullBaseLayerBlob();
|
const blob = await getFullBaseLayerBlob();
|
||||||
|
|
||||||
if (!blob) {
|
if (!blob) {
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { canvasSavedToGallery } from 'features/canvas/store/actions';
|
import { canvasSavedToGallery } from 'features/canvas/store/actions';
|
||||||
import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob';
|
import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob';
|
||||||
import { addToast } from 'features/system/store/systemSlice';
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'canvasSavedToGalleryListener' });
|
|
||||||
|
|
||||||
export const addCanvasSavedToGalleryListener = () => {
|
export const addCanvasSavedToGalleryListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: canvasSavedToGallery,
|
actionCreator: canvasSavedToGallery,
|
||||||
effect: async (action, { dispatch, getState, take }) => {
|
effect: async (action, { dispatch, getState }) => {
|
||||||
|
const log = logger('canvas');
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
const blob = await getBaseLayerBlob(state);
|
const blob = await getBaseLayerBlob(state);
|
||||||
|
|
||||||
if (!blob) {
|
if (!blob) {
|
||||||
moduleLog.error('Problem getting base layer blob');
|
log.error('Problem getting base layer blob');
|
||||||
dispatch(
|
dispatch(
|
||||||
addToast({
|
addToast({
|
||||||
title: 'Problem Saving Canvas',
|
title: 'Problem Saving Canvas',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { AnyListenerPredicate } from '@reduxjs/toolkit';
|
import { AnyListenerPredicate } from '@reduxjs/toolkit';
|
||||||
import { startAppListening } from '..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { log } from 'app/logging/useLogger';
|
import { RootState } from 'app/store/store';
|
||||||
import { controlNetImageProcessed } from 'features/controlNet/store/actions';
|
import { controlNetImageProcessed } from 'features/controlNet/store/actions';
|
||||||
import {
|
import {
|
||||||
controlNetAutoConfigToggled,
|
controlNetAutoConfigToggled,
|
||||||
@ -9,9 +9,7 @@ import {
|
|||||||
controlNetProcessorParamsChanged,
|
controlNetProcessorParamsChanged,
|
||||||
controlNetProcessorTypeChanged,
|
controlNetProcessorTypeChanged,
|
||||||
} from 'features/controlNet/store/controlNetSlice';
|
} from 'features/controlNet/store/controlNetSlice';
|
||||||
import { RootState } from 'app/store/store';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'controlNet' });
|
|
||||||
|
|
||||||
const predicate: AnyListenerPredicate<RootState> = (
|
const predicate: AnyListenerPredicate<RootState> = (
|
||||||
action,
|
action,
|
||||||
@ -64,18 +62,13 @@ const predicate: AnyListenerPredicate<RootState> = (
|
|||||||
export const addControlNetAutoProcessListener = () => {
|
export const addControlNetAutoProcessListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
predicate,
|
predicate,
|
||||||
effect: async (
|
effect: async (action, { dispatch, cancelActiveListeners, delay }) => {
|
||||||
action,
|
const log = logger('session');
|
||||||
{ dispatch, getState, cancelActiveListeners, delay }
|
|
||||||
) => {
|
|
||||||
const { controlNetId } = action.payload;
|
const { controlNetId } = action.payload;
|
||||||
|
|
||||||
// Cancel any in-progress instances of this listener
|
// Cancel any in-progress instances of this listener
|
||||||
cancelActiveListeners();
|
cancelActiveListeners();
|
||||||
moduleLog.trace(
|
log.trace('ControlNet auto-process triggered');
|
||||||
{ data: action.payload },
|
|
||||||
'ControlNet auto-process triggered'
|
|
||||||
);
|
|
||||||
// Delay before starting actual work
|
// Delay before starting actual work
|
||||||
await delay(300);
|
await delay(300);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { controlNetImageProcessed } from 'features/controlNet/store/actions';
|
import { controlNetImageProcessed } from 'features/controlNet/store/actions';
|
||||||
import { controlNetProcessedImageChanged } from 'features/controlNet/store/controlNetSlice';
|
import { controlNetProcessedImageChanged } from 'features/controlNet/store/controlNetSlice';
|
||||||
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
||||||
@ -9,20 +9,16 @@ import { Graph, ImageDTO } from 'services/api/types';
|
|||||||
import { socketInvocationComplete } from 'services/events/actions';
|
import { socketInvocationComplete } from 'services/events/actions';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'controlNet' });
|
|
||||||
|
|
||||||
export const addControlNetImageProcessedListener = () => {
|
export const addControlNetImageProcessedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: controlNetImageProcessed,
|
actionCreator: controlNetImageProcessed,
|
||||||
effect: async (
|
effect: async (action, { dispatch, getState, take }) => {
|
||||||
action,
|
const log = logger('session');
|
||||||
{ dispatch, getState, take, unsubscribe, subscribe }
|
|
||||||
) => {
|
|
||||||
const { controlNetId } = action.payload;
|
const { controlNetId } = action.payload;
|
||||||
const controlNet = getState().controlNet.controlNets[controlNetId];
|
const controlNet = getState().controlNet.controlNets[controlNetId];
|
||||||
|
|
||||||
if (!controlNet.controlImage) {
|
if (!controlNet.controlImage) {
|
||||||
moduleLog.error('Unable to process ControlNet image');
|
log.error('Unable to process ControlNet image');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,8 +66,8 @@ export const addControlNetImageProcessedListener = () => {
|
|||||||
|
|
||||||
const processedControlImage = payload as ImageDTO;
|
const processedControlImage = payload as ImageDTO;
|
||||||
|
|
||||||
moduleLog.debug(
|
log.debug(
|
||||||
{ data: { arg: action.payload, processedControlImage } },
|
{ controlNetId: action.payload, processedControlImage },
|
||||||
'ControlNet image processed'
|
'ControlNet image processed'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'boards' });
|
|
||||||
|
|
||||||
export const addImageAddedToBoardFulfilledListener = () => {
|
export const addImageAddedToBoardFulfilledListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.addImageToBoard.matchFulfilled,
|
matcher: imagesApi.endpoints.addImageToBoard.matchFulfilled,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action) => {
|
||||||
|
const log = logger('images');
|
||||||
const { board_id, imageDTO } = action.meta.arg.originalArgs;
|
const { board_id, imageDTO } = action.meta.arg.originalArgs;
|
||||||
|
|
||||||
// TODO: update listImages cache for this board
|
// TODO: update listImages cache for this board
|
||||||
|
|
||||||
moduleLog.debug({ data: { board_id, imageDTO } }, 'Image added to board');
|
log.debug({ board_id, imageDTO }, 'Image added to board');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -20,13 +19,11 @@ export const addImageAddedToBoardFulfilledListener = () => {
|
|||||||
export const addImageAddedToBoardRejectedListener = () => {
|
export const addImageAddedToBoardRejectedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.addImageToBoard.matchRejected,
|
matcher: imagesApi.endpoints.addImageToBoard.matchRejected,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action) => {
|
||||||
|
const log = logger('images');
|
||||||
const { board_id, imageDTO } = action.meta.arg.originalArgs;
|
const { board_id, imageDTO } = action.meta.arg.originalArgs;
|
||||||
|
|
||||||
moduleLog.debug(
|
log.debug({ board_id, imageDTO }, 'Problem adding image to board');
|
||||||
{ data: { board_id, imageDTO } },
|
|
||||||
'Problem adding image to board'
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { resetCanvas } from 'features/canvas/store/canvasSlice';
|
import { resetCanvas } from 'features/canvas/store/canvasSlice';
|
||||||
import { controlNetReset } from 'features/controlNet/store/controlNetSlice';
|
import { controlNetReset } from 'features/controlNet/store/controlNetSlice';
|
||||||
import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors';
|
import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors';
|
||||||
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
||||||
import {
|
import { imageDeletionConfirmed } from 'features/imageDeletion/store/actions';
|
||||||
imageDeletionConfirmed,
|
import { isModalOpenChanged } from 'features/imageDeletion/store/imageDeletionSlice';
|
||||||
isModalOpenChanged,
|
|
||||||
} from 'features/imageDeletion/store/imageDeletionSlice';
|
|
||||||
import { nodeEditorReset } from 'features/nodes/store/nodesSlice';
|
import { nodeEditorReset } from 'features/nodes/store/nodesSlice';
|
||||||
import { clearInitialImage } from 'features/parameters/store/generationSlice';
|
import { clearInitialImage } from 'features/parameters/store/generationSlice';
|
||||||
import { clamp } from 'lodash-es';
|
import { clamp } from 'lodash-es';
|
||||||
@ -14,8 +12,6 @@ import { api } from 'services/api';
|
|||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'image' });
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the user requests an image deletion
|
* Called when the user requests an image deletion
|
||||||
*/
|
*/
|
||||||
@ -107,7 +103,7 @@ export const addRequestedImageDeletionListener = () => {
|
|||||||
export const addImageDeletedPendingListener = () => {
|
export const addImageDeletedPendingListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.deleteImage.matchPending,
|
matcher: imagesApi.endpoints.deleteImage.matchPending,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: () => {
|
||||||
//
|
//
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -119,11 +115,9 @@ export const addImageDeletedPendingListener = () => {
|
|||||||
export const addImageDeletedFulfilledListener = () => {
|
export const addImageDeletedFulfilledListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.deleteImage.matchFulfilled,
|
matcher: imagesApi.endpoints.deleteImage.matchFulfilled,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action) => {
|
||||||
moduleLog.debug(
|
const log = logger('images');
|
||||||
{ data: { image: action.meta.arg.originalArgs } },
|
log.debug({ imageDTO: action.meta.arg.originalArgs }, 'Image deleted');
|
||||||
'Image deleted'
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -134,9 +128,10 @@ export const addImageDeletedFulfilledListener = () => {
|
|||||||
export const addImageDeletedRejectedListener = () => {
|
export const addImageDeletedRejectedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.deleteImage.matchRejected,
|
matcher: imagesApi.endpoints.deleteImage.matchRejected,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action) => {
|
||||||
moduleLog.debug(
|
const log = logger('images');
|
||||||
{ data: { image: action.meta.arg.originalArgs } },
|
log.debug(
|
||||||
|
{ imageDTO: action.meta.arg.originalArgs },
|
||||||
'Unable to delete image'
|
'Unable to delete image'
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
TypesafeDraggableData,
|
TypesafeDraggableData,
|
||||||
TypesafeDroppableData,
|
TypesafeDroppableData,
|
||||||
} from 'app/components/ImageDnd/typesafeDnd';
|
} from 'app/components/ImageDnd/typesafeDnd';
|
||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
||||||
import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice';
|
import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice';
|
||||||
import {
|
import {
|
||||||
@ -15,8 +15,6 @@ import { initialImageChanged } from 'features/parameters/store/generationSlice';
|
|||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
import { startAppListening } from '../';
|
import { startAppListening } from '../';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'dnd' });
|
|
||||||
|
|
||||||
export const dndDropped = createAction<{
|
export const dndDropped = createAction<{
|
||||||
overData: TypesafeDroppableData;
|
overData: TypesafeDroppableData;
|
||||||
activeData: TypesafeDraggableData;
|
activeData: TypesafeDraggableData;
|
||||||
@ -25,14 +23,11 @@ export const dndDropped = createAction<{
|
|||||||
export const addImageDroppedListener = () => {
|
export const addImageDroppedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: dndDropped,
|
actionCreator: dndDropped,
|
||||||
effect: async (action, { dispatch, getState, take }) => {
|
effect: async (action, { dispatch }) => {
|
||||||
|
const log = logger('images');
|
||||||
const { activeData, overData } = action.payload;
|
const { activeData, overData } = action.payload;
|
||||||
const state = getState();
|
|
||||||
|
|
||||||
moduleLog.debug(
|
log.debug({ activeData, overData }, 'Image or selection dropped');
|
||||||
{ data: { activeData, overData } },
|
|
||||||
'Image or selection dropped'
|
|
||||||
);
|
|
||||||
|
|
||||||
// set current image
|
// set current image
|
||||||
if (
|
if (
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'boards' });
|
|
||||||
|
|
||||||
export const addImageRemovedFromBoardFulfilledListener = () => {
|
export const addImageRemovedFromBoardFulfilledListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.removeImageFromBoard.matchFulfilled,
|
matcher: imagesApi.endpoints.removeImageFromBoard.matchFulfilled,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action) => {
|
||||||
const { board_id, image_name } = action.meta.arg.originalArgs;
|
const log = logger('images');
|
||||||
|
const imageDTO = action.meta.arg.originalArgs;
|
||||||
|
|
||||||
moduleLog.debug(
|
log.debug({ imageDTO }, 'Image removed from board');
|
||||||
{ data: { board_id, image_name } },
|
|
||||||
'Image added to board'
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -21,13 +17,11 @@ export const addImageRemovedFromBoardFulfilledListener = () => {
|
|||||||
export const addImageRemovedFromBoardRejectedListener = () => {
|
export const addImageRemovedFromBoardRejectedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.removeImageFromBoard.matchRejected,
|
matcher: imagesApi.endpoints.removeImageFromBoard.matchRejected,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action) => {
|
||||||
const { board_id, image_name } = action.meta.arg.originalArgs;
|
const log = logger('images');
|
||||||
|
const imageDTO = action.meta.arg.originalArgs;
|
||||||
|
|
||||||
moduleLog.debug(
|
log.debug({ imageDTO }, 'Problem removing image from board');
|
||||||
{ data: { board_id, image_name } },
|
|
||||||
'Problem adding image to board'
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
import { startAppListening } from '..';
|
import { imageDeletionConfirmed } from 'features/imageDeletion/store/actions';
|
||||||
import { log } from 'app/logging/useLogger';
|
import { selectImageUsage } from 'features/imageDeletion/store/imageDeletionSelectors';
|
||||||
import {
|
import {
|
||||||
imageDeletionConfirmed,
|
|
||||||
imageToDeleteSelected,
|
imageToDeleteSelected,
|
||||||
isModalOpenChanged,
|
isModalOpenChanged,
|
||||||
selectImageUsage,
|
|
||||||
} from 'features/imageDeletion/store/imageDeletionSlice';
|
} from 'features/imageDeletion/store/imageDeletionSlice';
|
||||||
|
import { startAppListening } from '..';
|
||||||
const moduleLog = log.child({ namespace: 'image' });
|
|
||||||
|
|
||||||
export const addImageToDeleteSelectedListener = () => {
|
export const addImageToDeleteSelectedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: imageToDeleteSelected,
|
actionCreator: imageToDeleteSelected,
|
||||||
effect: async (action, { dispatch, getState, condition }) => {
|
effect: async (action, { dispatch, getState }) => {
|
||||||
const imageDTO = action.payload;
|
const imageDTO = action.payload;
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { shouldConfirmOnDelete } = state.system;
|
const { shouldConfirmOnDelete } = state.system;
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
|
||||||
import { startAppListening } from '..';
|
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'image' });
|
|
||||||
|
|
||||||
export const addImageUpdatedFulfilledListener = () => {
|
|
||||||
// startAppListening({
|
|
||||||
// matcher: imagesApi.endpoints.updateImage.matchFulfilled,
|
|
||||||
// effect: (action, { dispatch, getState }) => {
|
|
||||||
// moduleLog.debug(
|
|
||||||
// {
|
|
||||||
// data: {
|
|
||||||
// oldImage: action.meta.arg.originalArgs,
|
|
||||||
// updatedImage: action.payload,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// 'Image updated'
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
};
|
|
||||||
|
|
||||||
export const addImageUpdatedRejectedListener = () => {
|
|
||||||
// startAppListening({
|
|
||||||
// matcher: imagesApi.endpoints.updateImage.matchRejected,
|
|
||||||
// effect: (action, { dispatch }) => {
|
|
||||||
// moduleLog.debug(
|
|
||||||
// { data: action.meta.arg.originalArgs },
|
|
||||||
// 'Image update failed'
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
};
|
|
@ -1,5 +1,5 @@
|
|||||||
import { UseToastOptions } from '@chakra-ui/react';
|
import { UseToastOptions } from '@chakra-ui/react';
|
||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
||||||
import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice';
|
import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice';
|
||||||
import { imagesAddedToBatch } from 'features/gallery/store/gallerySlice';
|
import { imagesAddedToBatch } from 'features/gallery/store/gallerySlice';
|
||||||
@ -9,8 +9,7 @@ import { addToast } from 'features/system/store/systemSlice';
|
|||||||
import { boardsApi } from 'services/api/endpoints/boards';
|
import { boardsApi } from 'services/api/endpoints/boards';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
import { imagesApi } from '../../../../../services/api/endpoints/images';
|
import { imagesApi } from '../../../../../services/api/endpoints/images';
|
||||||
|
import { omit } from 'lodash-es';
|
||||||
const moduleLog = log.child({ namespace: 'image' });
|
|
||||||
|
|
||||||
const DEFAULT_UPLOADED_TOAST: UseToastOptions = {
|
const DEFAULT_UPLOADED_TOAST: UseToastOptions = {
|
||||||
title: 'Image Uploaded',
|
title: 'Image Uploaded',
|
||||||
@ -21,11 +20,12 @@ export const addImageUploadedFulfilledListener = () => {
|
|||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.uploadImage.matchFulfilled,
|
matcher: imagesApi.endpoints.uploadImage.matchFulfilled,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch, getState }) => {
|
||||||
|
const log = logger('images');
|
||||||
const imageDTO = action.payload;
|
const imageDTO = action.payload;
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { selectedBoardId, autoAddBoardId } = state.gallery;
|
const { autoAddBoardId } = state.gallery;
|
||||||
|
|
||||||
moduleLog.debug({ arg: '<Blob>', imageDTO }, 'Image uploaded');
|
log.debug({ imageDTO }, 'Image uploaded');
|
||||||
|
|
||||||
const { postUploadAction } = action.meta.arg.originalArgs;
|
const { postUploadAction } = action.meta.arg.originalArgs;
|
||||||
|
|
||||||
@ -140,9 +140,14 @@ export const addImageUploadedRejectedListener = () => {
|
|||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.uploadImage.matchRejected,
|
matcher: imagesApi.endpoints.uploadImage.matchRejected,
|
||||||
effect: (action, { dispatch }) => {
|
effect: (action, { dispatch }) => {
|
||||||
const { file, postUploadAction, ...rest } = action.meta.arg.originalArgs;
|
const log = logger('images');
|
||||||
const sanitizedData = { arg: { ...rest, file: '<Blob>' } };
|
const sanitizedData = {
|
||||||
moduleLog.error({ data: sanitizedData }, 'Image upload failed');
|
arg: {
|
||||||
|
...omit(action.meta.arg.originalArgs, ['file', 'postUploadAction']),
|
||||||
|
file: '<Blob>',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
log.error({ ...sanitizedData }, 'Image upload failed');
|
||||||
dispatch(
|
dispatch(
|
||||||
addToast({
|
addToast({
|
||||||
title: 'Image Upload Failed',
|
title: 'Image Upload Failed',
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { makeToast } from 'app/components/Toaster';
|
|
||||||
import { initialImageSelected } from 'features/parameters/store/actions';
|
import { initialImageSelected } from 'features/parameters/store/actions';
|
||||||
import { initialImageChanged } from 'features/parameters/store/generationSlice';
|
import { initialImageChanged } from 'features/parameters/store/generationSlice';
|
||||||
import { addToast } from 'features/system/store/systemSlice';
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
|
import { makeToast } from 'features/system/util/makeToast';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
export const addInitialImageSelectedListener = () => {
|
export const addInitialImageSelectedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: initialImageSelected,
|
actionCreator: initialImageSelected,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action, { dispatch }) => {
|
||||||
if (!action.payload) {
|
if (!action.payload) {
|
||||||
dispatch(
|
dispatch(
|
||||||
addToast(
|
addToast(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { makeToast } from 'app/components/Toaster';
|
import { logger } from 'app/logging/logger';
|
||||||
import { log } from 'app/logging/useLogger';
|
import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice';
|
||||||
import { loraRemoved } from 'features/lora/store/loraSlice';
|
import { loraRemoved } from 'features/lora/store/loraSlice';
|
||||||
import { modelSelected } from 'features/parameters/store/actions';
|
import { modelSelected } from 'features/parameters/store/actions';
|
||||||
import {
|
import {
|
||||||
@ -8,21 +8,21 @@ import {
|
|||||||
} from 'features/parameters/store/generationSlice';
|
} from 'features/parameters/store/generationSlice';
|
||||||
import { zMainModel } from 'features/parameters/types/parameterSchemas';
|
import { zMainModel } from 'features/parameters/types/parameterSchemas';
|
||||||
import { addToast } from 'features/system/store/systemSlice';
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
|
import { makeToast } from 'features/system/util/makeToast';
|
||||||
import { forEach } from 'lodash-es';
|
import { forEach } from 'lodash-es';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice';
|
|
||||||
|
|
||||||
const moduleLog = log.child({ module: 'models' });
|
|
||||||
|
|
||||||
export const addModelSelectedListener = () => {
|
export const addModelSelectedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: modelSelected,
|
actionCreator: modelSelected,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action, { getState, dispatch }) => {
|
||||||
|
const log = logger('models');
|
||||||
|
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const result = zMainModel.safeParse(action.payload);
|
const result = zMainModel.safeParse(action.payload);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
moduleLog.error(
|
log.error(
|
||||||
{ error: result.error.format() },
|
{ error: result.error.format() },
|
||||||
'Failed to parse main model'
|
'Failed to parse main model'
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
|
import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice';
|
||||||
import { loraRemoved } from 'features/lora/store/loraSlice';
|
import { loraRemoved } from 'features/lora/store/loraSlice';
|
||||||
import {
|
import {
|
||||||
modelChanged,
|
modelChanged,
|
||||||
@ -11,15 +12,17 @@ import {
|
|||||||
import { forEach, some } from 'lodash-es';
|
import { forEach, some } from 'lodash-es';
|
||||||
import { modelsApi } from 'services/api/endpoints/models';
|
import { modelsApi } from 'services/api/endpoints/models';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice';
|
|
||||||
|
|
||||||
const moduleLog = log.child({ module: 'models' });
|
|
||||||
|
|
||||||
export const addModelsLoadedListener = () => {
|
export const addModelsLoadedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: modelsApi.endpoints.getMainModels.matchFulfilled,
|
matcher: modelsApi.endpoints.getMainModels.matchFulfilled,
|
||||||
effect: async (action, { getState, dispatch }) => {
|
effect: async (action, { getState, dispatch }) => {
|
||||||
// models loaded, we need to ensure the selected model is available and if not, select the first one
|
// models loaded, we need to ensure the selected model is available and if not, select the first one
|
||||||
|
const log = logger('models');
|
||||||
|
log.info(
|
||||||
|
{ models: action.payload.entities },
|
||||||
|
`Main models loaded (${action.payload.ids.length})`
|
||||||
|
);
|
||||||
|
|
||||||
const currentModel = getState().generation.model;
|
const currentModel = getState().generation.model;
|
||||||
|
|
||||||
@ -46,7 +49,7 @@ export const addModelsLoadedListener = () => {
|
|||||||
const result = zMainModel.safeParse(firstModel);
|
const result = zMainModel.safeParse(firstModel);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
moduleLog.error(
|
log.error(
|
||||||
{ error: result.error.format() },
|
{ error: result.error.format() },
|
||||||
'Failed to parse main model'
|
'Failed to parse main model'
|
||||||
);
|
);
|
||||||
@ -60,6 +63,11 @@ export const addModelsLoadedListener = () => {
|
|||||||
matcher: modelsApi.endpoints.getVaeModels.matchFulfilled,
|
matcher: modelsApi.endpoints.getVaeModels.matchFulfilled,
|
||||||
effect: async (action, { getState, dispatch }) => {
|
effect: async (action, { getState, dispatch }) => {
|
||||||
// VAEs loaded, need to reset the VAE is it's no longer available
|
// VAEs loaded, need to reset the VAE is it's no longer available
|
||||||
|
const log = logger('models');
|
||||||
|
log.info(
|
||||||
|
{ models: action.payload.entities },
|
||||||
|
`VAEs loaded (${action.payload.ids.length})`
|
||||||
|
);
|
||||||
|
|
||||||
const currentVae = getState().generation.vae;
|
const currentVae = getState().generation.vae;
|
||||||
|
|
||||||
@ -91,7 +99,7 @@ export const addModelsLoadedListener = () => {
|
|||||||
const result = zVaeModel.safeParse(firstModel);
|
const result = zVaeModel.safeParse(firstModel);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
moduleLog.error(
|
log.error(
|
||||||
{ error: result.error.format() },
|
{ error: result.error.format() },
|
||||||
'Failed to parse VAE model'
|
'Failed to parse VAE model'
|
||||||
);
|
);
|
||||||
@ -105,6 +113,11 @@ export const addModelsLoadedListener = () => {
|
|||||||
matcher: modelsApi.endpoints.getLoRAModels.matchFulfilled,
|
matcher: modelsApi.endpoints.getLoRAModels.matchFulfilled,
|
||||||
effect: async (action, { getState, dispatch }) => {
|
effect: async (action, { getState, dispatch }) => {
|
||||||
// LoRA models loaded - need to remove missing LoRAs from state
|
// LoRA models loaded - need to remove missing LoRAs from state
|
||||||
|
const log = logger('models');
|
||||||
|
log.info(
|
||||||
|
{ models: action.payload.entities },
|
||||||
|
`LoRAs loaded (${action.payload.ids.length})`
|
||||||
|
);
|
||||||
|
|
||||||
const loras = getState().lora.loras;
|
const loras = getState().lora.loras;
|
||||||
|
|
||||||
@ -128,6 +141,12 @@ export const addModelsLoadedListener = () => {
|
|||||||
matcher: modelsApi.endpoints.getControlNetModels.matchFulfilled,
|
matcher: modelsApi.endpoints.getControlNetModels.matchFulfilled,
|
||||||
effect: async (action, { getState, dispatch }) => {
|
effect: async (action, { getState, dispatch }) => {
|
||||||
// ControlNet models loaded - need to remove missing ControlNets from state
|
// ControlNet models loaded - need to remove missing ControlNets from state
|
||||||
|
const log = logger('models');
|
||||||
|
log.info(
|
||||||
|
{ models: action.payload.entities },
|
||||||
|
`ControlNet models loaded (${action.payload.ids.length})`
|
||||||
|
);
|
||||||
|
|
||||||
const controlNets = getState().controlNet.controlNets;
|
const controlNets = getState().controlNet.controlNets;
|
||||||
|
|
||||||
forEach(controlNets, (controlNet, controlNetId) => {
|
forEach(controlNets, (controlNet, controlNetId) => {
|
||||||
@ -146,4 +165,14 @@ export const addModelsLoadedListener = () => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
startAppListening({
|
||||||
|
matcher: modelsApi.endpoints.getTextualInversionModels.matchFulfilled,
|
||||||
|
effect: async (action) => {
|
||||||
|
const log = logger('models');
|
||||||
|
log.info(
|
||||||
|
{ models: action.payload.entities },
|
||||||
|
`Embeddings loaded (${action.payload.ids.length})`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
|
import { logger } from 'app/logging/logger';
|
||||||
|
import { parseify } from 'common/util/serialize';
|
||||||
|
import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice';
|
||||||
|
import { parseSchema } from 'features/nodes/util/parseSchema';
|
||||||
|
import { size } from 'lodash-es';
|
||||||
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
|
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import { parseSchema } from 'features/nodes/util/parseSchema';
|
|
||||||
import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice';
|
|
||||||
import { size } from 'lodash-es';
|
|
||||||
|
|
||||||
const schemaLog = log.child({ namespace: 'schema' });
|
|
||||||
|
|
||||||
export const addReceivedOpenAPISchemaListener = () => {
|
export const addReceivedOpenAPISchemaListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: receivedOpenAPISchema.fulfilled,
|
actionCreator: receivedOpenAPISchema.fulfilled,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch }) => {
|
||||||
|
const log = logger('system');
|
||||||
const schemaJSON = action.payload;
|
const schemaJSON = action.payload;
|
||||||
|
|
||||||
schemaLog.info({ data: { schemaJSON } }, 'Dereferenced OpenAPI schema');
|
log.debug({ schemaJSON }, 'Dereferenced OpenAPI schema');
|
||||||
|
|
||||||
const nodeTemplates = parseSchema(schemaJSON);
|
const nodeTemplates = parseSchema(schemaJSON);
|
||||||
|
|
||||||
schemaLog.info(
|
log.debug(
|
||||||
{ data: { nodeTemplates } },
|
{ nodeTemplates: parseify(nodeTemplates) },
|
||||||
`Built ${size(nodeTemplates)} node templates`
|
`Built ${size(nodeTemplates)} node templates`
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -28,8 +28,9 @@ export const addReceivedOpenAPISchemaListener = () => {
|
|||||||
|
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: receivedOpenAPISchema.rejected,
|
actionCreator: receivedOpenAPISchema.rejected,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: () => {
|
||||||
schemaLog.error('Problem dereferencing OpenAPI Schema');
|
const log = logger('system');
|
||||||
|
log.error('Problem dereferencing OpenAPI Schema');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { startAppListening } from '..';
|
|
||||||
import { sessionCanceled } from 'services/api/thunks/session';
|
|
||||||
import { serializeError } from 'serialize-error';
|
import { serializeError } from 'serialize-error';
|
||||||
|
import { sessionCanceled } from 'services/api/thunks/session';
|
||||||
const moduleLog = log.child({ namespace: 'session' });
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
export const addSessionCanceledPendingListener = () => {
|
export const addSessionCanceledPendingListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionCanceled.pending,
|
actionCreator: sessionCanceled.pending,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: () => {
|
||||||
//
|
//
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -17,12 +15,10 @@ export const addSessionCanceledPendingListener = () => {
|
|||||||
export const addSessionCanceledFulfilledListener = () => {
|
export const addSessionCanceledFulfilledListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionCanceled.fulfilled,
|
actionCreator: sessionCanceled.fulfilled,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action) => {
|
||||||
|
const log = logger('session');
|
||||||
const { session_id } = action.meta.arg;
|
const { session_id } = action.meta.arg;
|
||||||
moduleLog.debug(
|
log.debug({ session_id }, `Session canceled (${session_id})`);
|
||||||
{ data: { session_id } },
|
|
||||||
`Session canceled (${session_id})`
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -30,15 +26,15 @@ export const addSessionCanceledFulfilledListener = () => {
|
|||||||
export const addSessionCanceledRejectedListener = () => {
|
export const addSessionCanceledRejectedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionCanceled.rejected,
|
actionCreator: sessionCanceled.rejected,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action) => {
|
||||||
|
const log = logger('session');
|
||||||
|
const { session_id } = action.meta.arg;
|
||||||
if (action.payload) {
|
if (action.payload) {
|
||||||
const { arg, error } = action.payload;
|
const { error } = action.payload;
|
||||||
moduleLog.error(
|
log.error(
|
||||||
{
|
{
|
||||||
data: {
|
session_id,
|
||||||
arg,
|
error: serializeError(error),
|
||||||
error: serializeError(error),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
`Problem canceling session`
|
`Problem canceling session`
|
||||||
);
|
);
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
|
import { parseify } from 'common/util/serialize';
|
||||||
import { serializeError } from 'serialize-error';
|
import { serializeError } from 'serialize-error';
|
||||||
import { sessionCreated } from 'services/api/thunks/session';
|
import { sessionCreated } from 'services/api/thunks/session';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'session' });
|
|
||||||
|
|
||||||
export const addSessionCreatedPendingListener = () => {
|
export const addSessionCreatedPendingListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionCreated.pending,
|
actionCreator: sessionCreated.pending,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: () => {
|
||||||
//
|
//
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -17,9 +16,13 @@ export const addSessionCreatedPendingListener = () => {
|
|||||||
export const addSessionCreatedFulfilledListener = () => {
|
export const addSessionCreatedFulfilledListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionCreated.fulfilled,
|
actionCreator: sessionCreated.fulfilled,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action) => {
|
||||||
|
const log = logger('session');
|
||||||
const session = action.payload;
|
const session = action.payload;
|
||||||
moduleLog.debug({ data: { session } }, `Session created (${session.id})`);
|
log.debug(
|
||||||
|
{ session: parseify(session) },
|
||||||
|
`Session created (${session.id})`
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -27,17 +30,14 @@ export const addSessionCreatedFulfilledListener = () => {
|
|||||||
export const addSessionCreatedRejectedListener = () => {
|
export const addSessionCreatedRejectedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionCreated.rejected,
|
actionCreator: sessionCreated.rejected,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action) => {
|
||||||
|
const log = logger('session');
|
||||||
if (action.payload) {
|
if (action.payload) {
|
||||||
const { arg, error } = action.payload;
|
const { error } = action.payload;
|
||||||
|
const graph = parseify(action.meta.arg);
|
||||||
const stringifiedError = JSON.stringify(error);
|
const stringifiedError = JSON.stringify(error);
|
||||||
moduleLog.error(
|
log.error(
|
||||||
{
|
{ graph, error: serializeError(error) },
|
||||||
data: {
|
|
||||||
arg,
|
|
||||||
error: serializeError(error),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
`Problem creating session: ${stringifiedError}`
|
`Problem creating session: ${stringifiedError}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { startAppListening } from '..';
|
|
||||||
import { sessionInvoked } from 'services/api/thunks/session';
|
|
||||||
import { serializeError } from 'serialize-error';
|
import { serializeError } from 'serialize-error';
|
||||||
|
import { sessionInvoked } from 'services/api/thunks/session';
|
||||||
const moduleLog = log.child({ namespace: 'session' });
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
export const addSessionInvokedPendingListener = () => {
|
export const addSessionInvokedPendingListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionInvoked.pending,
|
actionCreator: sessionInvoked.pending,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: () => {
|
||||||
//
|
//
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -17,12 +15,10 @@ export const addSessionInvokedPendingListener = () => {
|
|||||||
export const addSessionInvokedFulfilledListener = () => {
|
export const addSessionInvokedFulfilledListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionInvoked.fulfilled,
|
actionCreator: sessionInvoked.fulfilled,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action) => {
|
||||||
|
const log = logger('session');
|
||||||
const { session_id } = action.meta.arg;
|
const { session_id } = action.meta.arg;
|
||||||
moduleLog.debug(
|
log.debug({ session_id }, `Session invoked (${session_id})`);
|
||||||
{ data: { session_id } },
|
|
||||||
`Session invoked (${session_id})`
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -30,16 +26,16 @@ export const addSessionInvokedFulfilledListener = () => {
|
|||||||
export const addSessionInvokedRejectedListener = () => {
|
export const addSessionInvokedRejectedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionInvoked.rejected,
|
actionCreator: sessionInvoked.rejected,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action) => {
|
||||||
|
const log = logger('session');
|
||||||
|
const { session_id } = action.meta.arg;
|
||||||
if (action.payload) {
|
if (action.payload) {
|
||||||
const { arg, error } = action.payload;
|
const { error } = action.payload;
|
||||||
const stringifiedError = JSON.stringify(error);
|
const stringifiedError = JSON.stringify(error);
|
||||||
moduleLog.error(
|
log.error(
|
||||||
{
|
{
|
||||||
data: {
|
session_id,
|
||||||
arg,
|
error: serializeError(error),
|
||||||
error: serializeError(error),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
`Problem invoking session: ${stringifiedError}`
|
`Problem invoking session: ${stringifiedError}`
|
||||||
);
|
);
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
import { startAppListening } from '..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { sessionInvoked } from 'services/api/thunks/session';
|
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
||||||
|
import { sessionInvoked } from 'services/api/thunks/session';
|
||||||
const moduleLog = log.child({ namespace: 'session' });
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
export const addSessionReadyToInvokeListener = () => {
|
export const addSessionReadyToInvokeListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionReadyToInvoke,
|
actionCreator: sessionReadyToInvoke,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (action, { getState, dispatch }) => {
|
||||||
|
const log = logger('session');
|
||||||
const { sessionId: session_id } = getState().system;
|
const { sessionId: session_id } = getState().system;
|
||||||
if (session_id) {
|
if (session_id) {
|
||||||
moduleLog.debug(
|
log.debug({ session_id }, `Session ready to invoke (${session_id})})`);
|
||||||
{ session_id },
|
|
||||||
`Session ready to invoke (${session_id})})`
|
|
||||||
);
|
|
||||||
dispatch(sessionInvoked({ session_id }));
|
dispatch(sessionInvoked({ session_id }));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { modelsApi } from 'services/api/endpoints/models';
|
import { modelsApi } from 'services/api/endpoints/models';
|
||||||
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
|
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
|
||||||
import { appSocketConnected, socketConnected } from 'services/events/actions';
|
import { appSocketConnected, socketConnected } from 'services/events/actions';
|
||||||
import { startAppListening } from '../..';
|
import { startAppListening } from '../..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
|
|
||||||
export const addSocketConnectedEventListener = () => {
|
export const addSocketConnectedEventListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: socketConnected,
|
actionCreator: socketConnected,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch, getState }) => {
|
||||||
const { timestamp } = action.payload;
|
const log = logger('socketio');
|
||||||
|
|
||||||
moduleLog.debug({ timestamp }, 'Connected');
|
log.debug('Connected');
|
||||||
|
|
||||||
const { nodes, config } = getState();
|
const { nodes, config } = getState();
|
||||||
|
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
import { startAppListening } from '../..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import {
|
import {
|
||||||
socketDisconnected,
|
|
||||||
appSocketDisconnected,
|
appSocketDisconnected,
|
||||||
|
socketDisconnected,
|
||||||
} from 'services/events/actions';
|
} from 'services/events/actions';
|
||||||
|
import { startAppListening } from '../..';
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
|
|
||||||
export const addSocketDisconnectedEventListener = () => {
|
export const addSocketDisconnectedEventListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: socketDisconnected,
|
actionCreator: socketDisconnected,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch }) => {
|
||||||
moduleLog.debug(action.payload, 'Disconnected');
|
const log = logger('socketio');
|
||||||
|
log.debug('Disconnected');
|
||||||
// pass along the socket event as an application action
|
// pass along the socket event as an application action
|
||||||
dispatch(appSocketDisconnected(action.payload));
|
dispatch(appSocketDisconnected(action.payload));
|
||||||
},
|
},
|
||||||
|
@ -1,28 +1,27 @@
|
|||||||
import { startAppListening } from '../..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import {
|
import {
|
||||||
appSocketGeneratorProgress,
|
appSocketGeneratorProgress,
|
||||||
socketGeneratorProgress,
|
socketGeneratorProgress,
|
||||||
} from 'services/events/actions';
|
} from 'services/events/actions';
|
||||||
|
import { startAppListening } from '../..';
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
|
|
||||||
export const addGeneratorProgressEventListener = () => {
|
export const addGeneratorProgressEventListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: socketGeneratorProgress,
|
actionCreator: socketGeneratorProgress,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch, getState }) => {
|
||||||
|
const log = logger('socketio');
|
||||||
if (
|
if (
|
||||||
getState().system.canceledSession ===
|
getState().system.canceledSession ===
|
||||||
action.payload.data.graph_execution_state_id
|
action.payload.data.graph_execution_state_id
|
||||||
) {
|
) {
|
||||||
moduleLog.trace(
|
log.trace(
|
||||||
action.payload,
|
action.payload,
|
||||||
'Ignored generator progress for canceled session'
|
'Ignored generator progress for canceled session'
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
moduleLog.trace(
|
log.trace(
|
||||||
action.payload,
|
action.payload,
|
||||||
`Generator progress (${action.payload.data.node.type})`
|
`Generator progress (${action.payload.data.node.type})`
|
||||||
);
|
);
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import {
|
import {
|
||||||
appSocketGraphExecutionStateComplete,
|
appSocketGraphExecutionStateComplete,
|
||||||
socketGraphExecutionStateComplete,
|
socketGraphExecutionStateComplete,
|
||||||
} from 'services/events/actions';
|
} from 'services/events/actions';
|
||||||
import { startAppListening } from '../..';
|
import { startAppListening } from '../..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
|
|
||||||
export const addGraphExecutionStateCompleteEventListener = () => {
|
export const addGraphExecutionStateCompleteEventListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: socketGraphExecutionStateComplete,
|
actionCreator: socketGraphExecutionStateComplete,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch }) => {
|
||||||
moduleLog.debug(
|
const log = logger('socketio');
|
||||||
action.payload,
|
log.debug(action.payload, 'Session complete');
|
||||||
`Session invocation complete (${action.payload.data.graph_execution_state_id})`
|
|
||||||
);
|
|
||||||
// pass along the socket event as an application action
|
// pass along the socket event as an application action
|
||||||
dispatch(appSocketGraphExecutionStateComplete(action.payload));
|
dispatch(appSocketGraphExecutionStateComplete(action.payload));
|
||||||
},
|
},
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
|
import { parseify } from 'common/util/serialize';
|
||||||
import { addImageToStagingArea } from 'features/canvas/store/canvasSlice';
|
import { addImageToStagingArea } from 'features/canvas/store/canvasSlice';
|
||||||
import {
|
import {
|
||||||
IMAGE_CATEGORIES,
|
|
||||||
boardIdSelected,
|
boardIdSelected,
|
||||||
galleryViewChanged,
|
galleryViewChanged,
|
||||||
imageSelected,
|
imageSelected,
|
||||||
} from 'features/gallery/store/gallerySlice';
|
} from 'features/gallery/store/gallerySlice';
|
||||||
|
import { IMAGE_CATEGORIES } from 'features/gallery/store/types';
|
||||||
import { progressImageSet } from 'features/system/store/systemSlice';
|
import { progressImageSet } from 'features/system/store/systemSlice';
|
||||||
import { imagesAdapter, imagesApi } from 'services/api/endpoints/images';
|
import { imagesAdapter, imagesApi } from 'services/api/endpoints/images';
|
||||||
import { isImageOutput } from 'services/api/guards';
|
import { isImageOutput } from 'services/api/guards';
|
||||||
@ -16,15 +17,16 @@ import {
|
|||||||
} from 'services/events/actions';
|
} from 'services/events/actions';
|
||||||
import { startAppListening } from '../..';
|
import { startAppListening } from '../..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
const nodeDenylist = ['dataURL_image'];
|
const nodeDenylist = ['dataURL_image'];
|
||||||
|
|
||||||
export const addInvocationCompleteEventListener = () => {
|
export const addInvocationCompleteEventListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: socketInvocationComplete,
|
actionCreator: socketInvocationComplete,
|
||||||
effect: async (action, { dispatch, getState, take }) => {
|
effect: async (action, { dispatch, getState }) => {
|
||||||
moduleLog.debug(
|
const log = logger('socketio');
|
||||||
{ data: action.payload },
|
const { data } = action.payload;
|
||||||
|
log.debug(
|
||||||
|
{ data: parseify(data) },
|
||||||
`Invocation complete (${action.payload.data.node.type})`
|
`Invocation complete (${action.payload.data.node.type})`
|
||||||
);
|
);
|
||||||
const session_id = action.payload.data.graph_execution_state_id;
|
const session_id = action.payload.data.graph_execution_state_id;
|
||||||
@ -36,7 +38,6 @@ export const addInvocationCompleteEventListener = () => {
|
|||||||
dispatch(sessionCanceled({ session_id }));
|
dispatch(sessionCanceled({ session_id }));
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = action.payload;
|
|
||||||
const { result, node, graph_execution_state_id } = data;
|
const { result, node, graph_execution_state_id } = data;
|
||||||
|
|
||||||
// This complete event has an associated image output
|
// This complete event has an associated image output
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
import { startAppListening } from '../..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import {
|
import {
|
||||||
appSocketInvocationError,
|
appSocketInvocationError,
|
||||||
socketInvocationError,
|
socketInvocationError,
|
||||||
} from 'services/events/actions';
|
} from 'services/events/actions';
|
||||||
|
import { startAppListening } from '../..';
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
|
|
||||||
export const addInvocationErrorEventListener = () => {
|
export const addInvocationErrorEventListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: socketInvocationError,
|
actionCreator: socketInvocationError,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch }) => {
|
||||||
moduleLog.error(
|
const log = logger('socketio');
|
||||||
|
log.error(
|
||||||
action.payload,
|
action.payload,
|
||||||
`Invocation error (${action.payload.data.node.type}): ${action.payload.data.error}`
|
`Invocation error (${action.payload.data.node.type})`
|
||||||
);
|
);
|
||||||
dispatch(appSocketInvocationError(action.payload));
|
dispatch(appSocketInvocationError(action.payload));
|
||||||
},
|
},
|
||||||
|
@ -1,31 +1,27 @@
|
|||||||
import { startAppListening } from '../..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import {
|
import {
|
||||||
appSocketInvocationStarted,
|
appSocketInvocationStarted,
|
||||||
socketInvocationStarted,
|
socketInvocationStarted,
|
||||||
} from 'services/events/actions';
|
} from 'services/events/actions';
|
||||||
|
import { startAppListening } from '../..';
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
|
|
||||||
export const addInvocationStartedEventListener = () => {
|
export const addInvocationStartedEventListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: socketInvocationStarted,
|
actionCreator: socketInvocationStarted,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch, getState }) => {
|
||||||
|
const log = logger('socketio');
|
||||||
if (
|
if (
|
||||||
getState().system.canceledSession ===
|
getState().system.canceledSession ===
|
||||||
action.payload.data.graph_execution_state_id
|
action.payload.data.graph_execution_state_id
|
||||||
) {
|
) {
|
||||||
moduleLog.trace(
|
log.trace(
|
||||||
action.payload,
|
action.payload,
|
||||||
'Ignored invocation started for canceled session'
|
'Ignored invocation started for canceled session'
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
moduleLog.debug(
|
log.debug(action.payload, 'Invocation started');
|
||||||
action.payload,
|
|
||||||
`Invocation started (${action.payload.data.node.type})`
|
|
||||||
);
|
|
||||||
dispatch(appSocketInvocationStarted(action.payload));
|
dispatch(appSocketInvocationStarted(action.payload));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
import { logger } from 'app/logging/logger';
|
||||||
|
import {
|
||||||
|
appSocketModelLoadCompleted,
|
||||||
|
appSocketModelLoadStarted,
|
||||||
|
socketModelLoadCompleted,
|
||||||
|
socketModelLoadStarted,
|
||||||
|
} from 'services/events/actions';
|
||||||
|
import { startAppListening } from '../..';
|
||||||
|
|
||||||
|
export const addModelLoadEventListener = () => {
|
||||||
|
startAppListening({
|
||||||
|
actionCreator: socketModelLoadStarted,
|
||||||
|
effect: (action, { dispatch }) => {
|
||||||
|
const log = logger('socketio');
|
||||||
|
const { base_model, model_name, model_type, submodel } =
|
||||||
|
action.payload.data;
|
||||||
|
|
||||||
|
let message = `Model load started: ${base_model}/${model_type}/${model_name}`;
|
||||||
|
|
||||||
|
if (submodel) {
|
||||||
|
message = message.concat(`/${submodel}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(action.payload, message);
|
||||||
|
|
||||||
|
// pass along the socket event as an application action
|
||||||
|
dispatch(appSocketModelLoadStarted(action.payload));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
startAppListening({
|
||||||
|
actionCreator: socketModelLoadCompleted,
|
||||||
|
effect: (action, { dispatch }) => {
|
||||||
|
const log = logger('socketio');
|
||||||
|
const { base_model, model_name, model_type, submodel } =
|
||||||
|
action.payload.data;
|
||||||
|
|
||||||
|
let message = `Model load complete: ${base_model}/${model_type}/${model_name}`;
|
||||||
|
|
||||||
|
if (submodel) {
|
||||||
|
message = message.concat(`/${submodel}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(action.payload, message);
|
||||||
|
// pass along the socket event as an application action
|
||||||
|
dispatch(appSocketModelLoadCompleted(action.payload));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
@ -1,28 +0,0 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import {
|
|
||||||
appSocketModelLoadCompleted,
|
|
||||||
socketModelLoadCompleted,
|
|
||||||
} from 'services/events/actions';
|
|
||||||
import { startAppListening } from '../..';
|
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
|
|
||||||
export const addModelLoadCompletedEventListener = () => {
|
|
||||||
startAppListening({
|
|
||||||
actionCreator: socketModelLoadCompleted,
|
|
||||||
effect: (action, { dispatch, getState }) => {
|
|
||||||
const { model_name, model_type, submodel } = action.payload.data;
|
|
||||||
|
|
||||||
let modelString = `${model_type} model: ${model_name}`;
|
|
||||||
|
|
||||||
if (submodel) {
|
|
||||||
modelString = modelString.concat(`, submodel: ${submodel}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleLog.debug(action.payload, `Model load completed (${modelString})`);
|
|
||||||
|
|
||||||
// pass along the socket event as an application action
|
|
||||||
dispatch(appSocketModelLoadCompleted(action.payload));
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
@ -1,28 +0,0 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import {
|
|
||||||
appSocketModelLoadStarted,
|
|
||||||
socketModelLoadStarted,
|
|
||||||
} from 'services/events/actions';
|
|
||||||
import { startAppListening } from '../..';
|
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
|
|
||||||
export const addModelLoadStartedEventListener = () => {
|
|
||||||
startAppListening({
|
|
||||||
actionCreator: socketModelLoadStarted,
|
|
||||||
effect: (action, { dispatch, getState }) => {
|
|
||||||
const { model_name, model_type, submodel } = action.payload.data;
|
|
||||||
|
|
||||||
let modelString = `${model_type} model: ${model_name}`;
|
|
||||||
|
|
||||||
if (submodel) {
|
|
||||||
modelString = modelString.concat(`, submodel: ${submodel}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleLog.debug(action.payload, `Model load started (${modelString})`);
|
|
||||||
|
|
||||||
// pass along the socket event as an application action
|
|
||||||
dispatch(appSocketModelLoadStarted(action.payload));
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
@ -1,17 +1,13 @@
|
|||||||
import { startAppListening } from '../..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import { appSocketSubscribed, socketSubscribed } from 'services/events/actions';
|
import { appSocketSubscribed, socketSubscribed } from 'services/events/actions';
|
||||||
|
import { startAppListening } from '../..';
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
|
|
||||||
export const addSocketSubscribedEventListener = () => {
|
export const addSocketSubscribedEventListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: socketSubscribed,
|
actionCreator: socketSubscribed,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch }) => {
|
||||||
moduleLog.debug(
|
const log = logger('socketio');
|
||||||
action.payload,
|
log.debug(action.payload, 'Subscribed');
|
||||||
`Subscribed (${action.payload.sessionId}))`
|
|
||||||
);
|
|
||||||
dispatch(appSocketSubscribed(action.payload));
|
dispatch(appSocketSubscribed(action.payload));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
import { startAppListening } from '../..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import {
|
import {
|
||||||
appSocketUnsubscribed,
|
appSocketUnsubscribed,
|
||||||
socketUnsubscribed,
|
socketUnsubscribed,
|
||||||
} from 'services/events/actions';
|
} from 'services/events/actions';
|
||||||
|
import { startAppListening } from '../..';
|
||||||
const moduleLog = log.child({ namespace: 'socketio' });
|
|
||||||
|
|
||||||
export const addSocketUnsubscribedEventListener = () => {
|
export const addSocketUnsubscribedEventListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: socketUnsubscribed,
|
actionCreator: socketUnsubscribed,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch }) => {
|
||||||
moduleLog.debug(
|
const log = logger('socketio');
|
||||||
action.payload,
|
log.debug(action.payload, 'Unsubscribed');
|
||||||
`Unsubscribed (${action.payload.sessionId})`
|
|
||||||
);
|
|
||||||
dispatch(appSocketUnsubscribed(action.payload));
|
dispatch(appSocketUnsubscribed(action.payload));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import { stagingAreaImageSaved } from 'features/canvas/store/actions';
|
import { stagingAreaImageSaved } from 'features/canvas/store/actions';
|
||||||
import { addToast } from 'features/system/store/systemSlice';
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'canvas' });
|
|
||||||
|
|
||||||
export const addStagingAreaImageSavedListener = () => {
|
export const addStagingAreaImageSavedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: stagingAreaImageSaved,
|
actionCreator: stagingAreaImageSaved,
|
||||||
effect: async (action, { dispatch, getState, take }) => {
|
effect: async (action, { dispatch, getState }) => {
|
||||||
const { imageDTO } = action.payload;
|
const { imageDTO } = action.payload;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import { createAction } from '@reduxjs/toolkit';
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import { buildAdHocUpscaleGraph } from 'features/nodes/util/graphBuilders/buildAdHocUpscaleGraph';
|
import { buildAdHocUpscaleGraph } from 'features/nodes/util/graphBuilders/buildAdHocUpscaleGraph';
|
||||||
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
||||||
import { sessionCreated } from 'services/api/thunks/session';
|
import { sessionCreated } from 'services/api/thunks/session';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
const moduleLog = log.child({ namespace: 'upscale' });
|
|
||||||
|
|
||||||
export const upscaleRequested = createAction<{ image_name: string }>(
|
export const upscaleRequested = createAction<{ image_name: string }>(
|
||||||
`upscale/upscaleRequested`
|
`upscale/upscaleRequested`
|
||||||
);
|
);
|
||||||
@ -14,10 +11,7 @@ export const upscaleRequested = createAction<{ image_name: string }>(
|
|||||||
export const addUpscaleRequestedListener = () => {
|
export const addUpscaleRequestedListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: upscaleRequested,
|
actionCreator: upscaleRequested,
|
||||||
effect: async (
|
effect: async (action, { dispatch, getState, take }) => {
|
||||||
action,
|
|
||||||
{ dispatch, getState, take, unsubscribe, subscribe }
|
|
||||||
) => {
|
|
||||||
const { image_name } = action.payload;
|
const { image_name } = action.payload;
|
||||||
const { esrganModelName } = getState().postprocessing;
|
const { esrganModelName } = getState().postprocessing;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { log } from 'app/logging/useLogger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { userInvoked } from 'app/store/actions';
|
import { userInvoked } from 'app/store/actions';
|
||||||
import openBase64ImageInTab from 'common/util/openBase64ImageInTab';
|
import openBase64ImageInTab from 'common/util/openBase64ImageInTab';
|
||||||
import {
|
import {
|
||||||
@ -15,8 +15,7 @@ import { imagesApi } from 'services/api/endpoints/images';
|
|||||||
import { sessionCreated } from 'services/api/thunks/session';
|
import { sessionCreated } from 'services/api/thunks/session';
|
||||||
import { ImageDTO } from 'services/api/types';
|
import { ImageDTO } from 'services/api/types';
|
||||||
import { startAppListening } from '..';
|
import { startAppListening } from '..';
|
||||||
|
import { parseify } from 'common/util/serialize';
|
||||||
const moduleLog = log.child({ namespace: 'invoke' });
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This listener is responsible invoking the canvas. This involves a number of steps:
|
* This listener is responsible invoking the canvas. This involves a number of steps:
|
||||||
@ -36,13 +35,15 @@ export const addUserInvokedCanvasListener = () => {
|
|||||||
predicate: (action): action is ReturnType<typeof userInvoked> =>
|
predicate: (action): action is ReturnType<typeof userInvoked> =>
|
||||||
userInvoked.match(action) && action.payload === 'unifiedCanvas',
|
userInvoked.match(action) && action.payload === 'unifiedCanvas',
|
||||||
effect: async (action, { getState, dispatch, take }) => {
|
effect: async (action, { getState, dispatch, take }) => {
|
||||||
|
const log = logger('session');
|
||||||
|
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
// Build canvas blobs
|
// Build canvas blobs
|
||||||
const canvasBlobsAndImageData = await getCanvasData(state);
|
const canvasBlobsAndImageData = await getCanvasData(state);
|
||||||
|
|
||||||
if (!canvasBlobsAndImageData) {
|
if (!canvasBlobsAndImageData) {
|
||||||
moduleLog.error('Unable to create canvas data');
|
log.error('Unable to create canvas data');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ export const addUserInvokedCanvasListener = () => {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
moduleLog.debug(`Generation mode: ${generationMode}`);
|
log.debug(`Generation mode: ${generationMode}`);
|
||||||
|
|
||||||
// Temp placeholders for the init and mask images
|
// Temp placeholders for the init and mask images
|
||||||
let canvasInitImage: ImageDTO | undefined;
|
let canvasInitImage: ImageDTO | undefined;
|
||||||
@ -105,7 +106,7 @@ export const addUserInvokedCanvasListener = () => {
|
|||||||
canvasMaskImage
|
canvasMaskImage
|
||||||
);
|
);
|
||||||
|
|
||||||
moduleLog.debug({ graph }, `Canvas graph built`);
|
log.debug({ graph: parseify(graph) }, `Canvas graph built`);
|
||||||
|
|
||||||
// currently this action is just listened to for logging
|
// currently this action is just listened to for logging
|
||||||
dispatch(canvasGraphBuilt(graph));
|
dispatch(canvasGraphBuilt(graph));
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
import { startAppListening } from '..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { sessionCreated } from 'services/api/thunks/session';
|
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import { imageToImageGraphBuilt } from 'features/nodes/store/actions';
|
|
||||||
import { userInvoked } from 'app/store/actions';
|
import { userInvoked } from 'app/store/actions';
|
||||||
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
import { parseify } from 'common/util/serialize';
|
||||||
|
import { imageToImageGraphBuilt } from 'features/nodes/store/actions';
|
||||||
import { buildLinearImageToImageGraph } from 'features/nodes/util/graphBuilders/buildLinearImageToImageGraph';
|
import { buildLinearImageToImageGraph } from 'features/nodes/util/graphBuilders/buildLinearImageToImageGraph';
|
||||||
|
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
||||||
const moduleLog = log.child({ namespace: 'invoke' });
|
import { sessionCreated } from 'services/api/thunks/session';
|
||||||
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
export const addUserInvokedImageToImageListener = () => {
|
export const addUserInvokedImageToImageListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
predicate: (action): action is ReturnType<typeof userInvoked> =>
|
predicate: (action): action is ReturnType<typeof userInvoked> =>
|
||||||
userInvoked.match(action) && action.payload === 'img2img',
|
userInvoked.match(action) && action.payload === 'img2img',
|
||||||
effect: async (action, { getState, dispatch, take }) => {
|
effect: async (action, { getState, dispatch, take }) => {
|
||||||
|
const log = logger('session');
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
const graph = buildLinearImageToImageGraph(state);
|
const graph = buildLinearImageToImageGraph(state);
|
||||||
dispatch(imageToImageGraphBuilt(graph));
|
dispatch(imageToImageGraphBuilt(graph));
|
||||||
moduleLog.debug({ data: graph }, 'Image to Image graph built');
|
log.debug({ graph: parseify(graph) }, 'Image to Image graph built');
|
||||||
|
|
||||||
dispatch(sessionCreated({ graph }));
|
dispatch(sessionCreated({ graph }));
|
||||||
|
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
import { startAppListening } from '..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { sessionCreated } from 'services/api/thunks/session';
|
|
||||||
import { buildNodesGraph } from 'features/nodes/util/graphBuilders/buildNodesGraph';
|
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import { nodesGraphBuilt } from 'features/nodes/store/actions';
|
|
||||||
import { userInvoked } from 'app/store/actions';
|
import { userInvoked } from 'app/store/actions';
|
||||||
|
import { parseify } from 'common/util/serialize';
|
||||||
|
import { nodesGraphBuilt } from 'features/nodes/store/actions';
|
||||||
|
import { buildNodesGraph } from 'features/nodes/util/graphBuilders/buildNodesGraph';
|
||||||
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
||||||
|
import { sessionCreated } from 'services/api/thunks/session';
|
||||||
const moduleLog = log.child({ namespace: 'invoke' });
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
export const addUserInvokedNodesListener = () => {
|
export const addUserInvokedNodesListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
predicate: (action): action is ReturnType<typeof userInvoked> =>
|
predicate: (action): action is ReturnType<typeof userInvoked> =>
|
||||||
userInvoked.match(action) && action.payload === 'nodes',
|
userInvoked.match(action) && action.payload === 'nodes',
|
||||||
effect: async (action, { getState, dispatch, take }) => {
|
effect: async (action, { getState, dispatch, take }) => {
|
||||||
|
const log = logger('session');
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
const graph = buildNodesGraph(state);
|
const graph = buildNodesGraph(state);
|
||||||
dispatch(nodesGraphBuilt(graph));
|
dispatch(nodesGraphBuilt(graph));
|
||||||
moduleLog.debug({ data: graph }, 'Nodes graph built');
|
log.debug({ graph: parseify(graph) }, 'Nodes graph built');
|
||||||
|
|
||||||
dispatch(sessionCreated({ graph }));
|
dispatch(sessionCreated({ graph }));
|
||||||
|
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
import { startAppListening } from '..';
|
import { logger } from 'app/logging/logger';
|
||||||
import { sessionCreated } from 'services/api/thunks/session';
|
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import { textToImageGraphBuilt } from 'features/nodes/store/actions';
|
|
||||||
import { userInvoked } from 'app/store/actions';
|
import { userInvoked } from 'app/store/actions';
|
||||||
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
import { parseify } from 'common/util/serialize';
|
||||||
|
import { textToImageGraphBuilt } from 'features/nodes/store/actions';
|
||||||
import { buildLinearTextToImageGraph } from 'features/nodes/util/graphBuilders/buildLinearTextToImageGraph';
|
import { buildLinearTextToImageGraph } from 'features/nodes/util/graphBuilders/buildLinearTextToImageGraph';
|
||||||
|
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
||||||
const moduleLog = log.child({ namespace: 'invoke' });
|
import { sessionCreated } from 'services/api/thunks/session';
|
||||||
|
import { startAppListening } from '..';
|
||||||
|
|
||||||
export const addUserInvokedTextToImageListener = () => {
|
export const addUserInvokedTextToImageListener = () => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
predicate: (action): action is ReturnType<typeof userInvoked> =>
|
predicate: (action): action is ReturnType<typeof userInvoked> =>
|
||||||
userInvoked.match(action) && action.payload === 'txt2img',
|
userInvoked.match(action) && action.payload === 'txt2img',
|
||||||
effect: async (action, { getState, dispatch, take }) => {
|
effect: async (action, { getState, dispatch, take }) => {
|
||||||
|
const log = logger('session');
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
const graph = buildLinearTextToImageGraph(state);
|
const graph = buildLinearTextToImageGraph(state);
|
||||||
|
|
||||||
dispatch(textToImageGraphBuilt(graph));
|
dispatch(textToImageGraphBuilt(graph));
|
||||||
|
|
||||||
moduleLog.debug({ data: graph }, 'Text to Image graph built');
|
log.debug({ graph: parseify(graph) }, 'Text to Image graph built');
|
||||||
|
|
||||||
dispatch(sessionCreated({ graph }));
|
dispatch(sessionCreated({ graph }));
|
||||||
|
|
||||||
|
@ -5,13 +5,9 @@ import {
|
|||||||
combineReducers,
|
combineReducers,
|
||||||
configureStore,
|
configureStore,
|
||||||
} from '@reduxjs/toolkit';
|
} from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import dynamicMiddlewares from 'redux-dynamic-middlewares';
|
|
||||||
import { rememberEnhancer, rememberReducer } from 'redux-remember';
|
|
||||||
|
|
||||||
import canvasReducer from 'features/canvas/store/canvasSlice';
|
import canvasReducer from 'features/canvas/store/canvasSlice';
|
||||||
import controlNetReducer from 'features/controlNet/store/controlNetSlice';
|
import controlNetReducer from 'features/controlNet/store/controlNetSlice';
|
||||||
import dynamicPromptsReducer from 'features/dynamicPrompts/store/slice';
|
import dynamicPromptsReducer from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||||
import boardsReducer from 'features/gallery/store/boardSlice';
|
import boardsReducer from 'features/gallery/store/boardSlice';
|
||||||
import galleryReducer from 'features/gallery/store/gallerySlice';
|
import galleryReducer from 'features/gallery/store/gallerySlice';
|
||||||
import imageDeletionReducer from 'features/imageDeletion/store/imageDeletionSlice';
|
import imageDeletionReducer from 'features/imageDeletion/store/imageDeletionSlice';
|
||||||
@ -24,9 +20,8 @@ import systemReducer from 'features/system/store/systemSlice';
|
|||||||
import modelmanagerReducer from 'features/ui/components/tabs/ModelManager/store/modelManagerSlice';
|
import modelmanagerReducer from 'features/ui/components/tabs/ModelManager/store/modelManagerSlice';
|
||||||
import hotkeysReducer from 'features/ui/store/hotkeysSlice';
|
import hotkeysReducer from 'features/ui/store/hotkeysSlice';
|
||||||
import uiReducer from 'features/ui/store/uiSlice';
|
import uiReducer from 'features/ui/store/uiSlice';
|
||||||
|
import dynamicMiddlewares from 'redux-dynamic-middlewares';
|
||||||
import { listenerMiddleware } from './middleware/listenerMiddleware';
|
import { rememberEnhancer, rememberReducer } from 'redux-remember';
|
||||||
|
|
||||||
import { api } from 'services/api';
|
import { api } from 'services/api';
|
||||||
import { LOCALSTORAGE_PREFIX } from './constants';
|
import { LOCALSTORAGE_PREFIX } from './constants';
|
||||||
import { serialize } from './enhancers/reduxRemember/serialize';
|
import { serialize } from './enhancers/reduxRemember/serialize';
|
||||||
@ -34,6 +29,7 @@ import { unserialize } from './enhancers/reduxRemember/unserialize';
|
|||||||
import { actionSanitizer } from './middleware/devtools/actionSanitizer';
|
import { actionSanitizer } from './middleware/devtools/actionSanitizer';
|
||||||
import { actionsDenylist } from './middleware/devtools/actionsDenylist';
|
import { actionsDenylist } from './middleware/devtools/actionsDenylist';
|
||||||
import { stateSanitizer } from './middleware/devtools/stateSanitizer';
|
import { stateSanitizer } from './middleware/devtools/stateSanitizer';
|
||||||
|
import { listenerMiddleware } from './middleware/listenerMiddleware';
|
||||||
|
|
||||||
const allReducers = {
|
const allReducers = {
|
||||||
canvas: canvasReducer,
|
canvas: canvasReducer,
|
||||||
@ -121,6 +117,7 @@ export const store = configureStore({
|
|||||||
|
|
||||||
export type AppGetState = typeof store.getState;
|
export type AppGetState = typeof store.getState;
|
||||||
export type RootState = ReturnType<typeof store.getState>;
|
export type RootState = ReturnType<typeof store.getState>;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export type AppThunkDispatch = ThunkDispatch<RootState, any, AnyAction>;
|
export type AppThunkDispatch = ThunkDispatch<RootState, any, AnyAction>;
|
||||||
export type AppDispatch = typeof store.dispatch;
|
export type AppDispatch = typeof store.dispatch;
|
||||||
export const stateSelector = (state: RootState) => state;
|
export const stateSelector = (state: RootState) => state;
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
|
||||||
import { AppDispatch, RootState } from 'app/store/store';
|
|
||||||
|
|
||||||
// https://redux-toolkit.js.org/usage/usage-with-typescript#defining-a-pre-typed-createasyncthunk
|
|
||||||
export const createAppAsyncThunk = createAsyncThunk.withTypes<{
|
|
||||||
state: RootState;
|
|
||||||
dispatch: AppDispatch;
|
|
||||||
}>();
|
|
@ -1,23 +0,0 @@
|
|||||||
import { Box, forwardRef, Icon } from '@chakra-ui/react';
|
|
||||||
import { Feature } from 'app/features';
|
|
||||||
import { memo } from 'react';
|
|
||||||
import { IconType } from 'react-icons';
|
|
||||||
import { MdHelp } from 'react-icons/md';
|
|
||||||
import GuidePopover from './GuidePopover';
|
|
||||||
|
|
||||||
type GuideIconProps = {
|
|
||||||
feature: Feature;
|
|
||||||
icon?: IconType;
|
|
||||||
};
|
|
||||||
|
|
||||||
const GuideIcon = forwardRef(
|
|
||||||
({ feature, icon = MdHelp }: GuideIconProps, ref) => (
|
|
||||||
<GuidePopover feature={feature}>
|
|
||||||
<Box ref={ref}>
|
|
||||||
<Icon marginBottom="-.15rem" as={icon} />
|
|
||||||
</Box>
|
|
||||||
</GuidePopover>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export default memo(GuideIcon);
|
|
@ -1,49 +0,0 @@
|
|||||||
import {
|
|
||||||
Box,
|
|
||||||
Popover,
|
|
||||||
PopoverArrow,
|
|
||||||
PopoverBody,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { Feature, useFeatureHelpInfo } from 'app/features';
|
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
|
||||||
import { SystemState } from 'features/system/store/systemSlice';
|
|
||||||
import { memo, ReactElement } from 'react';
|
|
||||||
|
|
||||||
type GuideProps = {
|
|
||||||
children: ReactElement;
|
|
||||||
feature: Feature;
|
|
||||||
};
|
|
||||||
|
|
||||||
const guidePopoverSelector = createSelector(
|
|
||||||
systemSelector,
|
|
||||||
(system: SystemState) => system.shouldDisplayGuides
|
|
||||||
);
|
|
||||||
|
|
||||||
const GuidePopover = ({ children, feature }: GuideProps) => {
|
|
||||||
const shouldDisplayGuides = useAppSelector(guidePopoverSelector);
|
|
||||||
const { text } = useFeatureHelpInfo(feature);
|
|
||||||
|
|
||||||
if (!shouldDisplayGuides) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Popover trigger="hover" isLazy>
|
|
||||||
<PopoverTrigger>
|
|
||||||
<Box>{children}</Box>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent
|
|
||||||
maxWidth="400px"
|
|
||||||
onClick={(e) => e.preventDefault()}
|
|
||||||
cursor="initial"
|
|
||||||
>
|
|
||||||
<PopoverArrow />
|
|
||||||
<PopoverBody>{text}</PopoverBody>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(GuidePopover);
|
|
@ -169,7 +169,9 @@ const IAIDndImage = (props: IAIDndImageProps) => {
|
|||||||
...imageSx,
|
...imageSx,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{withMetadataOverlay && <ImageMetadataOverlay image={imageDTO} />}
|
{withMetadataOverlay && (
|
||||||
|
<ImageMetadataOverlay imageDTO={imageDTO} />
|
||||||
|
)}
|
||||||
<SelectionOverlay
|
<SelectionOverlay
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
isHovered={withHoverOverlay ? isHovered : false}
|
isHovered={withHoverOverlay ? isHovered : false}
|
||||||
|
@ -13,11 +13,10 @@ type IAIDroppableProps = {
|
|||||||
dropLabel?: ReactNode;
|
dropLabel?: ReactNode;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
data?: TypesafeDroppableData;
|
data?: TypesafeDroppableData;
|
||||||
hoverRef?: React.Ref<HTMLDivElement>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const IAIDroppable = (props: IAIDroppableProps) => {
|
const IAIDroppable = (props: IAIDroppableProps) => {
|
||||||
const { dropLabel, data, disabled, hoverRef } = props;
|
const { dropLabel, data, disabled } = props;
|
||||||
const dndId = useRef(uuidv4());
|
const dndId = useRef(uuidv4());
|
||||||
|
|
||||||
const { isOver, setNodeRef, active } = useDroppable({
|
const { isOver, setNodeRef, active } = useDroppable({
|
||||||
|
@ -10,7 +10,10 @@ interface ItemProps extends React.ComponentPropsWithoutRef<'div'> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const IAIMantineSelectItemWithTooltip = forwardRef<HTMLDivElement, ItemProps>(
|
const IAIMantineSelectItemWithTooltip = forwardRef<HTMLDivElement, ItemProps>(
|
||||||
({ label, tooltip, description, disabled, ...others }: ItemProps, ref) => (
|
(
|
||||||
|
{ label, tooltip, description, disabled: _disabled, ...others }: ItemProps,
|
||||||
|
ref
|
||||||
|
) => (
|
||||||
<Tooltip label={tooltip} placement="top" hasArrow openDelay={500}>
|
<Tooltip label={tooltip} placement="top" hasArrow openDelay={500}>
|
||||||
<Box ref={ref} {...others}>
|
<Box ref={ref} {...others}>
|
||||||
<Box>
|
<Box>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
ChakraProps,
|
|
||||||
FormControl,
|
FormControl,
|
||||||
FormControlProps,
|
FormControlProps,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
@ -24,16 +23,15 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipProps,
|
TooltipProps,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { clamp } from 'lodash-es';
|
|
||||||
|
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import { roundDownToMultiple } from 'common/util/roundDownToMultiple';
|
import { roundDownToMultiple } from 'common/util/roundDownToMultiple';
|
||||||
import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
|
import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
|
||||||
|
import { clamp } from 'lodash-es';
|
||||||
import {
|
import {
|
||||||
FocusEvent,
|
FocusEvent,
|
||||||
KeyboardEvent,
|
KeyboardEvent,
|
||||||
memo,
|
|
||||||
MouseEvent,
|
MouseEvent,
|
||||||
|
memo,
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
|
@ -1,21 +1,11 @@
|
|||||||
import { Badge, Flex } from '@chakra-ui/react';
|
import { Badge, Flex } from '@chakra-ui/react';
|
||||||
import { isString } from 'lodash-es';
|
|
||||||
import { useMemo } from 'react';
|
|
||||||
import { ImageDTO } from 'services/api/types';
|
import { ImageDTO } from 'services/api/types';
|
||||||
|
|
||||||
type ImageMetadataOverlayProps = {
|
type ImageMetadataOverlayProps = {
|
||||||
image: ImageDTO;
|
imageDTO: ImageDTO;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ImageMetadataOverlay = ({ image }: ImageMetadataOverlayProps) => {
|
const ImageMetadataOverlay = ({ imageDTO }: ImageMetadataOverlayProps) => {
|
||||||
const model = useMemo(() => {
|
|
||||||
if (!isString(image.metadata?.model)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return image.metadata?.model;
|
|
||||||
}, [image.metadata]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
sx={{
|
sx={{
|
||||||
@ -30,13 +20,8 @@ const ImageMetadataOverlay = ({ image }: ImageMetadataOverlayProps) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Badge variant="solid" colorScheme="base">
|
<Badge variant="solid" colorScheme="base">
|
||||||
{image.width} × {image.height}
|
{imageDTO.width} × {imageDTO.height}
|
||||||
</Badge>
|
</Badge>
|
||||||
{model && (
|
|
||||||
<Badge variant="solid" colorScheme="base">
|
|
||||||
{model}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2,17 +2,16 @@ import { createSelector } from '@reduxjs/toolkit';
|
|||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import { validateSeedWeights } from 'common/util/seedWeightPairs';
|
// import { validateSeedWeights } from 'common/util/seedWeightPairs';
|
||||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||||
import { modelsApi } from '../../services/api/endpoints/models';
|
|
||||||
import { forEach } from 'lodash-es';
|
import { forEach } from 'lodash-es';
|
||||||
|
import { modelsApi } from '../../services/api/endpoints/models';
|
||||||
|
|
||||||
const readinessSelector = createSelector(
|
const readinessSelector = createSelector(
|
||||||
[stateSelector, activeTabNameSelector],
|
[stateSelector, activeTabNameSelector],
|
||||||
(state, activeTabName) => {
|
(state, activeTabName) => {
|
||||||
const { generation, system } = state;
|
const { generation, system } = state;
|
||||||
const { shouldGenerateVariations, seedWeights, initialImage, seed } =
|
const { initialImage } = generation;
|
||||||
generation;
|
|
||||||
|
|
||||||
const { isProcessing, isConnected } = system;
|
const { isProcessing, isConnected } = system;
|
||||||
|
|
||||||
@ -44,19 +43,19 @@ const readinessSelector = createSelector(
|
|||||||
reasonsWhyNotReady.push('System Disconnected');
|
reasonsWhyNotReady.push('System Disconnected');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot generate variations without valid seed weights
|
// // Cannot generate variations without valid seed weights
|
||||||
if (
|
// if (
|
||||||
shouldGenerateVariations &&
|
// shouldGenerateVariations &&
|
||||||
(!(validateSeedWeights(seedWeights) || seedWeights === '') || seed === -1)
|
// (!(validateSeedWeights(seedWeights) || seedWeights === '') || seed === -1)
|
||||||
) {
|
// ) {
|
||||||
isReady = false;
|
// isReady = false;
|
||||||
reasonsWhyNotReady.push('Seed-Weights badly formatted.');
|
// reasonsWhyNotReady.push('Seed-Weights badly formatted.');
|
||||||
}
|
// }
|
||||||
|
|
||||||
forEach(state.controlNet.controlNets, (controlNet, id) => {
|
forEach(state.controlNet.controlNets, (controlNet, id) => {
|
||||||
if (!controlNet.model) {
|
if (!controlNet.model) {
|
||||||
isReady = false;
|
isReady = false;
|
||||||
reasonsWhyNotReady.push('ControlNet ${id} has no model selected.');
|
reasonsWhyNotReady.push(`ControlNet ${id} has no model selected.`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
import * as InvokeAI from 'app/types/invokeai';
|
|
||||||
import promptToString from './promptToString';
|
|
||||||
|
|
||||||
export function getPromptAndNegative(inputPrompt: InvokeAI.Prompt) {
|
|
||||||
let prompt: string =
|
|
||||||
typeof inputPrompt === 'string' ? inputPrompt : promptToString(inputPrompt);
|
|
||||||
|
|
||||||
let negativePrompt = '';
|
|
||||||
|
|
||||||
// Matches all negative prompts, 1st capturing group is the prompt itself
|
|
||||||
const negativePromptRegExp = new RegExp(/\[([^\][]*)]/, 'gi');
|
|
||||||
|
|
||||||
// Grab the actual prompt matches (capturing group 1 is 1st index of match)
|
|
||||||
const negativePromptMatches = [...prompt.matchAll(negativePromptRegExp)].map(
|
|
||||||
(match) => match[1]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (negativePromptMatches.length) {
|
|
||||||
// Build the negative prompt itself
|
|
||||||
negativePrompt = negativePromptMatches.join(' ');
|
|
||||||
|
|
||||||
// Replace each match, including its surrounding brackets
|
|
||||||
// Remove each pair of empty brackets
|
|
||||||
// Trim whitespace
|
|
||||||
negativePromptMatches.forEach((match) => {
|
|
||||||
prompt = prompt.replace(`[${match}]`, '').replaceAll('[]', '').trim();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return [prompt, negativePrompt];
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import * as InvokeAI from 'app/types/invokeai';
|
|
||||||
|
|
||||||
const promptToString = (prompt: InvokeAI.Prompt): string => {
|
|
||||||
if (typeof prompt === 'string') {
|
|
||||||
return prompt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prompt.length === 1) {
|
|
||||||
return prompt[0].prompt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return prompt
|
|
||||||
.map(
|
|
||||||
(promptItem: InvokeAI.PromptItem): string =>
|
|
||||||
`${promptItem.prompt}:${promptItem.weight}`
|
|
||||||
)
|
|
||||||
.join(' ');
|
|
||||||
};
|
|
||||||
|
|
||||||
export default promptToString;
|
|
@ -1,68 +1,71 @@
|
|||||||
import * as InvokeAI from 'app/types/invokeai';
|
// TODO: Restore variations
|
||||||
|
// Support code from v2.3 in here.
|
||||||
|
|
||||||
export const stringToSeedWeights = (
|
// export const stringToSeedWeights = (
|
||||||
string: string
|
// string: string
|
||||||
): InvokeAI.SeedWeights | boolean => {
|
// ): InvokeAI.SeedWeights | boolean => {
|
||||||
const stringPairs = string.split(',');
|
// const stringPairs = string.split(',');
|
||||||
const arrPairs = stringPairs.map((p) => p.split(':'));
|
// const arrPairs = stringPairs.map((p) => p.split(':'));
|
||||||
const pairs = arrPairs.map((p: Array<string>): InvokeAI.SeedWeightPair => {
|
// const pairs = arrPairs.map((p: Array<string>): InvokeAI.SeedWeightPair => {
|
||||||
return { seed: Number(p[0]), weight: Number(p[1]) };
|
// return { seed: Number(p[0]), weight: Number(p[1]) };
|
||||||
});
|
// });
|
||||||
|
|
||||||
if (!validateSeedWeights(pairs)) {
|
// if (!validateSeedWeights(pairs)) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return pairs;
|
// return pairs;
|
||||||
};
|
// };
|
||||||
|
|
||||||
export const validateSeedWeights = (
|
// export const validateSeedWeights = (
|
||||||
seedWeights: InvokeAI.SeedWeights | string
|
// seedWeights: InvokeAI.SeedWeights | string
|
||||||
): boolean => {
|
// ): boolean => {
|
||||||
return typeof seedWeights === 'string'
|
// return typeof seedWeights === 'string'
|
||||||
? Boolean(stringToSeedWeights(seedWeights))
|
// ? Boolean(stringToSeedWeights(seedWeights))
|
||||||
: Boolean(
|
// : Boolean(
|
||||||
seedWeights.length &&
|
// seedWeights.length &&
|
||||||
!seedWeights.some((pair: InvokeAI.SeedWeightPair) => {
|
// !seedWeights.some((pair: InvokeAI.SeedWeightPair) => {
|
||||||
const { seed, weight } = pair;
|
// const { seed, weight } = pair;
|
||||||
const isSeedValid = !isNaN(parseInt(seed.toString(), 10));
|
// const isSeedValid = !isNaN(parseInt(seed.toString(), 10));
|
||||||
const isWeightValid =
|
// const isWeightValid =
|
||||||
!isNaN(parseInt(weight.toString(), 10)) &&
|
// !isNaN(parseInt(weight.toString(), 10)) &&
|
||||||
weight >= 0 &&
|
// weight >= 0 &&
|
||||||
weight <= 1;
|
// weight <= 1;
|
||||||
return !(isSeedValid && isWeightValid);
|
// return !(isSeedValid && isWeightValid);
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
};
|
// };
|
||||||
|
|
||||||
export const seedWeightsToString = (
|
// export const seedWeightsToString = (
|
||||||
seedWeights: InvokeAI.SeedWeights
|
// seedWeights: InvokeAI.SeedWeights
|
||||||
): string => {
|
// ): string => {
|
||||||
return seedWeights.reduce((acc, pair, i, arr) => {
|
// return seedWeights.reduce((acc, pair, i, arr) => {
|
||||||
const { seed, weight } = pair;
|
// const { seed, weight } = pair;
|
||||||
acc += `${seed}:${weight}`;
|
// acc += `${seed}:${weight}`;
|
||||||
if (i !== arr.length - 1) {
|
// if (i !== arr.length - 1) {
|
||||||
acc += ',';
|
// acc += ',';
|
||||||
}
|
// }
|
||||||
return acc;
|
// return acc;
|
||||||
}, '');
|
// }, '');
|
||||||
};
|
// };
|
||||||
|
|
||||||
export const seedWeightsToArray = (
|
// export const seedWeightsToArray = (
|
||||||
seedWeights: InvokeAI.SeedWeights
|
// seedWeights: InvokeAI.SeedWeights
|
||||||
): Array<Array<number>> => {
|
// ): Array<Array<number>> => {
|
||||||
return seedWeights.map((pair: InvokeAI.SeedWeightPair) => [
|
// return seedWeights.map((pair: InvokeAI.SeedWeightPair) => [
|
||||||
pair.seed,
|
// pair.seed,
|
||||||
pair.weight,
|
// pair.weight,
|
||||||
]);
|
// ]);
|
||||||
};
|
// };
|
||||||
|
|
||||||
export const stringToSeedWeightsArray = (
|
// export const stringToSeedWeightsArray = (
|
||||||
string: string
|
// string: string
|
||||||
): Array<Array<number>> => {
|
// ): Array<Array<number>> => {
|
||||||
const stringPairs = string.split(',');
|
// const stringPairs = string.split(',');
|
||||||
const arrPairs = stringPairs.map((p) => p.split(':'));
|
// const arrPairs = stringPairs.map((p) => p.split(':'));
|
||||||
return arrPairs.map(
|
// return arrPairs.map(
|
||||||
(p: Array<string>): Array<number> => [parseInt(p[0], 10), parseFloat(p[1])]
|
// (p: Array<string>): Array<number> => [parseInt(p[0], 10), parseFloat(p[1])]
|
||||||
);
|
// );
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
export default {};
|
||||||
|
4
invokeai/frontend/web/src/common/util/serialize.ts
Normal file
4
invokeai/frontend/web/src/common/util/serialize.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Serialize an object to JSON and back to a new object
|
||||||
|
*/
|
||||||
|
export const parseify = (obj: unknown) => JSON.parse(JSON.stringify(obj));
|
@ -1,6 +1,7 @@
|
|||||||
import { Box, chakra, Flex } from '@chakra-ui/react';
|
import { Box, chakra, Flex } from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import {
|
import {
|
||||||
canvasSelector,
|
canvasSelector,
|
||||||
isStagingSelector,
|
isStagingSelector,
|
||||||
@ -8,8 +9,6 @@ import {
|
|||||||
import Konva from 'konva';
|
import Konva from 'konva';
|
||||||
import { KonvaEventObject } from 'konva/lib/Node';
|
import { KonvaEventObject } from 'konva/lib/Node';
|
||||||
import { Vector2d } from 'konva/lib/types';
|
import { Vector2d } from 'konva/lib/types';
|
||||||
import { isEqual } from 'lodash-es';
|
|
||||||
|
|
||||||
import { useCallback, useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
import { Layer, Stage } from 'react-konva';
|
import { Layer, Stage } from 'react-konva';
|
||||||
import useCanvasDragMove from '../hooks/useCanvasDragMove';
|
import useCanvasDragMove from '../hooks/useCanvasDragMove';
|
||||||
@ -34,7 +33,6 @@ import IAICanvasStagingAreaToolbar from './IAICanvasStagingAreaToolbar';
|
|||||||
import IAICanvasStatusText from './IAICanvasStatusText';
|
import IAICanvasStatusText from './IAICanvasStatusText';
|
||||||
import IAICanvasBoundingBox from './IAICanvasToolbar/IAICanvasBoundingBox';
|
import IAICanvasBoundingBox from './IAICanvasToolbar/IAICanvasBoundingBox';
|
||||||
import IAICanvasToolPreview from './IAICanvasToolPreview';
|
import IAICanvasToolPreview from './IAICanvasToolPreview';
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
[canvasSelector, isStagingSelector],
|
[canvasSelector, isStagingSelector],
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import {
|
import {
|
||||||
roundDownToMultiple,
|
roundDownToMultiple,
|
||||||
roundToMultiple,
|
roundToMultiple,
|
||||||
} from 'common/util/roundDownToMultiple';
|
} from 'common/util/roundDownToMultiple';
|
||||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
|
||||||
import {
|
import {
|
||||||
setBoundingBoxCoordinates,
|
setBoundingBoxCoordinates,
|
||||||
setBoundingBoxDimensions,
|
setBoundingBoxDimensions,
|
||||||
@ -13,7 +13,6 @@ import {
|
|||||||
setIsTransformingBoundingBox,
|
setIsTransformingBoundingBox,
|
||||||
setShouldSnapToGrid,
|
setShouldSnapToGrid,
|
||||||
} from 'features/canvas/store/canvasSlice';
|
} from 'features/canvas/store/canvasSlice';
|
||||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
|
||||||
import Konva from 'konva';
|
import Konva from 'konva';
|
||||||
import { GroupConfig } from 'konva/lib/Group';
|
import { GroupConfig } from 'konva/lib/Group';
|
||||||
import { KonvaEventObject } from 'konva/lib/Node';
|
import { KonvaEventObject } from 'konva/lib/Node';
|
||||||
@ -25,8 +24,8 @@ import { useHotkeys } from 'react-hotkeys-hook';
|
|||||||
import { Group, Rect, Transformer } from 'react-konva';
|
import { Group, Rect, Transformer } from 'react-konva';
|
||||||
|
|
||||||
const boundingBoxPreviewSelector = createSelector(
|
const boundingBoxPreviewSelector = createSelector(
|
||||||
[canvasSelector, uiSelector],
|
[stateSelector],
|
||||||
(canvas, ui) => {
|
({ canvas, generation }) => {
|
||||||
const {
|
const {
|
||||||
boundingBoxCoordinates,
|
boundingBoxCoordinates,
|
||||||
boundingBoxDimensions,
|
boundingBoxDimensions,
|
||||||
@ -38,7 +37,7 @@ const boundingBoxPreviewSelector = createSelector(
|
|||||||
shouldSnapToGrid,
|
shouldSnapToGrid,
|
||||||
} = canvas;
|
} = canvas;
|
||||||
|
|
||||||
const { aspectRatio } = ui;
|
const { aspectRatio } = generation;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
boundingBoxCoordinates,
|
boundingBoxCoordinates,
|
||||||
|
@ -4,14 +4,13 @@ import {
|
|||||||
roundDownToMultiple,
|
roundDownToMultiple,
|
||||||
roundToMultiple,
|
roundToMultiple,
|
||||||
} from 'common/util/roundDownToMultiple';
|
} from 'common/util/roundDownToMultiple';
|
||||||
import { IRect, Vector2d } from 'konva/lib/types';
|
import { setAspectRatio } from 'features/parameters/store/generationSlice';
|
||||||
import { clamp, cloneDeep } from 'lodash-es';
|
|
||||||
//
|
|
||||||
import {
|
import {
|
||||||
setActiveTab,
|
setActiveTab,
|
||||||
setAspectRatio,
|
|
||||||
setShouldUseCanvasBetaLayout,
|
setShouldUseCanvasBetaLayout,
|
||||||
} from 'features/ui/store/uiSlice';
|
} from 'features/ui/store/uiSlice';
|
||||||
|
import { IRect, Vector2d } from 'konva/lib/types';
|
||||||
|
import { clamp, cloneDeep } from 'lodash-es';
|
||||||
import { RgbaColor } from 'react-colorful';
|
import { RgbaColor } from 'react-colorful';
|
||||||
import { sessionCanceled } from 'services/api/thunks/session';
|
import { sessionCanceled } from 'services/api/thunks/session';
|
||||||
import { ImageDTO } from 'services/api/types';
|
import { ImageDTO } from 'services/api/types';
|
||||||
@ -714,7 +713,7 @@ export const canvasSlice = createSlice({
|
|||||||
},
|
},
|
||||||
commitStagingAreaImage: (
|
commitStagingAreaImage: (
|
||||||
state,
|
state,
|
||||||
action: PayloadAction<string | undefined>
|
_action: PayloadAction<string | undefined>
|
||||||
) => {
|
) => {
|
||||||
if (!state.layerState.stagingArea.images.length) {
|
if (!state.layerState.stagingArea.images.length) {
|
||||||
return;
|
return;
|
||||||
@ -867,11 +866,11 @@ export const canvasSlice = createSlice({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.addCase(setShouldUseCanvasBetaLayout, (state, action) => {
|
builder.addCase(setShouldUseCanvasBetaLayout, (state) => {
|
||||||
state.doesCanvasNeedScaling = true;
|
state.doesCanvasNeedScaling = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.addCase(setActiveTab, (state, action) => {
|
builder.addCase(setActiveTab, (state) => {
|
||||||
state.doesCanvasNeedScaling = true;
|
state.doesCanvasNeedScaling = true;
|
||||||
});
|
});
|
||||||
builder.addCase(setAspectRatio, (state, action) => {
|
builder.addCase(setAspectRatio, (state, action) => {
|
||||||
@ -883,26 +882,6 @@ export const canvasSlice = createSlice({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// builder.addCase(imageUrlsReceived.fulfilled, (state, action) => {
|
|
||||||
// const { image_name, image_url, thumbnail_url } = action.payload;
|
|
||||||
|
|
||||||
// state.layerState.objects.forEach((object) => {
|
|
||||||
// if (object.kind === 'image') {
|
|
||||||
// if (object.image.image_name === image_name) {
|
|
||||||
// object.image.image_url = image_url;
|
|
||||||
// object.image.thumbnail_url = thumbnail_url;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// state.layerState.stagingArea.images.forEach((stagedImage) => {
|
|
||||||
// if (stagedImage.image.image_name === image_name) {
|
|
||||||
// stagedImage.image.image_url = image_url;
|
|
||||||
// stagedImage.image.thumbnail_url = thumbnail_url;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import * as InvokeAI from 'app/types/invokeai';
|
|
||||||
import { IRect, Vector2d } from 'konva/lib/types';
|
import { IRect, Vector2d } from 'konva/lib/types';
|
||||||
import { RgbaColor } from 'react-colorful';
|
import { RgbaColor } from 'react-colorful';
|
||||||
import { ImageDTO } from 'services/api/types';
|
|
||||||
|
|
||||||
export const LAYER_NAMES_DICT = [
|
export const LAYER_NAMES_DICT = [
|
||||||
{ label: 'Base', value: 'base' },
|
{ label: 'Base', value: 'base' },
|
||||||
@ -133,7 +131,6 @@ export interface CanvasState {
|
|||||||
cursorPosition: Vector2d | null;
|
cursorPosition: Vector2d | null;
|
||||||
doesCanvasNeedScaling: boolean;
|
doesCanvasNeedScaling: boolean;
|
||||||
futureLayerStates: CanvasLayerState[];
|
futureLayerStates: CanvasLayerState[];
|
||||||
intermediateImage?: InvokeAI.Image;
|
|
||||||
isCanvasInitialized: boolean;
|
isCanvasInitialized: boolean;
|
||||||
isDrawing: boolean;
|
isDrawing: boolean;
|
||||||
isMaskEnabled: boolean;
|
isMaskEnabled: boolean;
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
|
import { logger } from 'app/logging/logger';
|
||||||
import { RootState } from 'app/store/store';
|
import { RootState } from 'app/store/store';
|
||||||
import { getCanvasBaseLayer, getCanvasStage } from './konvaInstanceProvider';
|
|
||||||
import { isCanvasMaskLine } from '../store/canvasTypes';
|
import { isCanvasMaskLine } from '../store/canvasTypes';
|
||||||
import { log } from 'app/logging/useLogger';
|
|
||||||
import createMaskStage from './createMaskStage';
|
import createMaskStage from './createMaskStage';
|
||||||
import { konvaNodeToImageData } from './konvaNodeToImageData';
|
import { getCanvasBaseLayer, getCanvasStage } from './konvaInstanceProvider';
|
||||||
import { konvaNodeToBlob } from './konvaNodeToBlob';
|
import { konvaNodeToBlob } from './konvaNodeToBlob';
|
||||||
|
import { konvaNodeToImageData } from './konvaNodeToImageData';
|
||||||
const moduleLog = log.child({ namespace: 'getCanvasDataURLs' });
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets Blob and ImageData objects for the base and mask layers
|
* Gets Blob and ImageData objects for the base and mask layers
|
||||||
*/
|
*/
|
||||||
export const getCanvasData = async (state: RootState) => {
|
export const getCanvasData = async (state: RootState) => {
|
||||||
|
const log = logger('canvas');
|
||||||
|
|
||||||
const canvasBaseLayer = getCanvasBaseLayer();
|
const canvasBaseLayer = getCanvasBaseLayer();
|
||||||
const canvasStage = getCanvasStage();
|
const canvasStage = getCanvasStage();
|
||||||
|
|
||||||
if (!canvasBaseLayer || !canvasStage) {
|
if (!canvasBaseLayer || !canvasStage) {
|
||||||
moduleLog.error('Unable to find canvas / stage');
|
log.error('Unable to find canvas / stage');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
|||||||
import IAIDndImage from 'common/components/IAIDndImage';
|
import IAIDndImage from 'common/components/IAIDndImage';
|
||||||
import { memo, useCallback, useMemo, useState } from 'react';
|
import { memo, useCallback, useMemo, useState } from 'react';
|
||||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||||
import { controlNetImageChanged } from '../store/controlNetSlice';
|
|
||||||
import { PostUploadAction } from 'services/api/types';
|
import { PostUploadAction } from 'services/api/types';
|
||||||
|
import { controlNetImageChanged } from '../store/controlNetSlice';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
controlNetId: string;
|
controlNetId: string;
|
||||||
@ -59,19 +59,13 @@ const ControlNetImagePreview = (props: Props) => {
|
|||||||
|
|
||||||
const [isMouseOverImage, setIsMouseOverImage] = useState(false);
|
const [isMouseOverImage, setIsMouseOverImage] = useState(false);
|
||||||
|
|
||||||
const {
|
const { currentData: controlImage } = useGetImageDTOQuery(
|
||||||
currentData: controlImage,
|
controlImageName ?? skipToken
|
||||||
isLoading: isLoadingControlImage,
|
);
|
||||||
isError: isErrorControlImage,
|
|
||||||
isSuccess: isSuccessControlImage,
|
|
||||||
} = useGetImageDTOQuery(controlImageName ?? skipToken);
|
|
||||||
|
|
||||||
const {
|
const { currentData: processedControlImage } = useGetImageDTOQuery(
|
||||||
currentData: processedControlImage,
|
processedControlImageName ?? skipToken
|
||||||
isLoading: isLoadingProcessedControlImage,
|
);
|
||||||
isError: isErrorProcessedControlImage,
|
|
||||||
isSuccess: isSuccessProcessedControlImage,
|
|
||||||
} = useGetImageDTOQuery(processedControlImageName ?? skipToken);
|
|
||||||
|
|
||||||
const handleResetControlImage = useCallback(() => {
|
const handleResetControlImage = useCallback(() => {
|
||||||
dispatch(controlNetImageChanged({ controlNetId, controlImage: null }));
|
dispatch(controlNetImageChanged({ controlNetId, controlImage: null }));
|
||||||
|
@ -55,11 +55,6 @@ const ParamControlNetBeginEnd = (props: Props) => {
|
|||||||
[controlNetId, dispatch]
|
[controlNetId, dispatch]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleStepPctReset = useCallback(() => {
|
|
||||||
dispatch(controlNetBeginStepPctChanged({ controlNetId, beginStepPct: 0 }));
|
|
||||||
dispatch(controlNetEndStepPctChanged({ controlNetId, endStepPct: 1 }));
|
|
||||||
}, [controlNetId, dispatch]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControl isDisabled={!isEnabled}>
|
<FormControl isDisabled={!isEnabled}>
|
||||||
<FormLabel>Begin / End Step Percentage</FormLabel>
|
<FormLabel>Begin / End Step Percentage</FormLabel>
|
||||||
|
@ -8,7 +8,6 @@ import {
|
|||||||
controlNetControlModeChanged,
|
controlNetControlModeChanged,
|
||||||
} from 'features/controlNet/store/controlNetSlice';
|
} from 'features/controlNet/store/controlNetSlice';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
type ParamControlNetControlModeProps = {
|
type ParamControlNetControlModeProps = {
|
||||||
controlNetId: string;
|
controlNetId: string;
|
||||||
@ -42,8 +41,6 @@ export default function ParamControlNetControlMode(
|
|||||||
|
|
||||||
const { controlMode, isEnabled } = useAppSelector(selector);
|
const { controlMode, isEnabled } = useAppSelector(selector);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const handleControlModeChange = useCallback(
|
const handleControlModeChange = useCallback(
|
||||||
(controlMode: ControlModes) => {
|
(controlMode: ControlModes) => {
|
||||||
dispatch(controlNetControlModeChanged({ controlNetId, controlMode }));
|
dispatch(controlNetControlModeChanged({ controlNetId, controlMode }));
|
||||||
|
@ -13,7 +13,6 @@ import { memo, useCallback, useMemo } from 'react';
|
|||||||
import { CONTROLNET_PROCESSORS } from '../../store/constants';
|
import { CONTROLNET_PROCESSORS } from '../../store/constants';
|
||||||
import { controlNetProcessorTypeChanged } from '../../store/controlNetSlice';
|
import { controlNetProcessorTypeChanged } from '../../store/controlNetSlice';
|
||||||
import { ControlNetProcessorType } from '../../store/types';
|
import { ControlNetProcessorType } from '../../store/types';
|
||||||
import { FormControl, FormLabel } from '@chakra-ui/react';
|
|
||||||
|
|
||||||
type ParamControlNetProcessorSelectProps = {
|
type ParamControlNetProcessorSelectProps = {
|
||||||
controlNetId: string;
|
controlNetId: string;
|
||||||
|
@ -8,7 +8,6 @@ import {
|
|||||||
controlNetResizeModeChanged,
|
controlNetResizeModeChanged,
|
||||||
} from 'features/controlNet/store/controlNetSlice';
|
} from 'features/controlNet/store/controlNetSlice';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
type ParamControlNetResizeModeProps = {
|
type ParamControlNetResizeModeProps = {
|
||||||
controlNetId: string;
|
controlNetId: string;
|
||||||
@ -41,8 +40,6 @@ export default function ParamControlNetResizeMode(
|
|||||||
|
|
||||||
const { resizeMode, isEnabled } = useAppSelector(selector);
|
const { resizeMode, isEnabled } = useAppSelector(selector);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const handleResizeModeChange = useCallback(
|
const handleResizeModeChange = useCallback(
|
||||||
(resizeMode: ResizeModes) => {
|
(resizeMode: ResizeModes) => {
|
||||||
dispatch(controlNetResizeModeChanged({ controlNetId, resizeMode }));
|
dispatch(controlNetResizeModeChanged({ controlNetId, resizeMode }));
|
||||||
|
@ -7,7 +7,7 @@ type Props = {
|
|||||||
isEnabled: boolean;
|
isEnabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ZoeDepthProcessor = (props: Props) => {
|
const ZoeDepthProcessor = (_props: Props) => {
|
||||||
// Has no parameters?
|
// Has no parameters?
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
|
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
|
||||||
import { RootState } from 'app/store/store';
|
|
||||||
import { ControlNetModelParam } from 'features/parameters/types/parameterSchemas';
|
import { ControlNetModelParam } from 'features/parameters/types/parameterSchemas';
|
||||||
import { cloneDeep, forEach } from 'lodash-es';
|
import { cloneDeep, forEach } from 'lodash-es';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
@ -315,11 +314,11 @@ export const controlNetSlice = createSlice({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.addCase(appSocketInvocationError, (state, action) => {
|
builder.addCase(appSocketInvocationError, (state) => {
|
||||||
state.pendingControlImages = [];
|
state.pendingControlImages = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.addMatcher(isAnySessionRejected, (state, action) => {
|
builder.addMatcher(isAnySessionRejected, (state) => {
|
||||||
state.pendingControlImages = [];
|
state.pendingControlImages = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -365,5 +364,3 @@ export const {
|
|||||||
} = controlNetSlice.actions;
|
} = controlNetSlice.actions;
|
||||||
|
|
||||||
export default controlNetSlice.reducer;
|
export default controlNetSlice.reducer;
|
||||||
|
|
||||||
export const controlNetSelector = (state: RootState) => state.controlNet;
|
|
||||||
|
@ -4,7 +4,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import IAISwitch from 'common/components/IAISwitch';
|
import IAISwitch from 'common/components/IAISwitch';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { combinatorialToggled } from '../store/slice';
|
import { combinatorialToggled } from '../store/dynamicPromptsSlice';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
stateSelector,
|
stateSelector,
|
||||||
|
@ -4,7 +4,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import IAISwitch from 'common/components/IAISwitch';
|
import IAISwitch from 'common/components/IAISwitch';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { isEnabledToggled } from '../store/slice';
|
import { isEnabledToggled } from '../store/dynamicPromptsSlice';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
stateSelector,
|
stateSelector,
|
||||||
|
@ -4,7 +4,10 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import IAISlider from 'common/components/IAISlider';
|
import IAISlider from 'common/components/IAISlider';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { maxPromptsChanged, maxPromptsReset } from '../store/slice';
|
import {
|
||||||
|
maxPromptsChanged,
|
||||||
|
maxPromptsReset,
|
||||||
|
} from '../store/dynamicPromptsSlice';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
stateSelector,
|
stateSelector,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
|
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
|
||||||
import { RootState } from 'app/store/store';
|
|
||||||
|
|
||||||
export interface DynamicPromptsState {
|
export interface DynamicPromptsState {
|
||||||
isEnabled: boolean;
|
isEnabled: boolean;
|
||||||
@ -32,9 +31,6 @@ export const dynamicPromptsSlice = createSlice({
|
|||||||
state.isEnabled = !state.isEnabled;
|
state.isEnabled = !state.isEnabled;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extraReducers: (builder) => {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
@ -45,6 +41,3 @@ export const {
|
|||||||
} = dynamicPromptsSlice.actions;
|
} = dynamicPromptsSlice.actions;
|
||||||
|
|
||||||
export default dynamicPromptsSlice.reducer;
|
export default dynamicPromptsSlice.reducer;
|
||||||
|
|
||||||
export const dynamicPromptsSelector = (state: RootState) =>
|
|
||||||
state.dynamicPrompts;
|
|
@ -1,19 +1,16 @@
|
|||||||
import { MenuGroup, MenuItem, MenuList } from '@chakra-ui/react';
|
import { MenuGroup, MenuItem, MenuList } from '@chakra-ui/react';
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { ContextMenu, ContextMenuProps } from 'chakra-ui-contextmenu';
|
import { ContextMenu, ContextMenuProps } from 'chakra-ui-contextmenu';
|
||||||
import {
|
import { autoAddBoardIdChanged } from 'features/gallery/store/gallerySlice';
|
||||||
autoAddBoardIdChanged,
|
|
||||||
boardIdSelected,
|
|
||||||
} from 'features/gallery/store/gallerySlice';
|
|
||||||
import { MouseEvent, memo, useCallback, useMemo } from 'react';
|
import { MouseEvent, memo, useCallback, useMemo } from 'react';
|
||||||
import { FaFolder, FaPlus } from 'react-icons/fa';
|
import { FaPlus } from 'react-icons/fa';
|
||||||
|
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||||
import { BoardDTO } from 'services/api/types';
|
import { BoardDTO } from 'services/api/types';
|
||||||
import { menuListMotionProps } from 'theme/components/menu';
|
import { menuListMotionProps } from 'theme/components/menu';
|
||||||
import GalleryBoardContextMenuItems from './GalleryBoardContextMenuItems';
|
import GalleryBoardContextMenuItems from './GalleryBoardContextMenuItems';
|
||||||
import NoBoardContextMenuItems from './NoBoardContextMenuItems';
|
import NoBoardContextMenuItems from './NoBoardContextMenuItems';
|
||||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { stateSelector } from 'app/store/store';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
board?: BoardDTO;
|
board?: BoardDTO;
|
||||||
@ -29,20 +26,15 @@ const BoardContextMenu = memo(
|
|||||||
const selector = useMemo(
|
const selector = useMemo(
|
||||||
() =>
|
() =>
|
||||||
createSelector(stateSelector, ({ gallery }) => {
|
createSelector(stateSelector, ({ gallery }) => {
|
||||||
const isSelected = gallery.selectedBoardId === board_id;
|
|
||||||
const isAutoAdd = gallery.autoAddBoardId === board_id;
|
const isAutoAdd = gallery.autoAddBoardId === board_id;
|
||||||
return { isSelected, isAutoAdd };
|
return { isAutoAdd };
|
||||||
}),
|
}),
|
||||||
[board_id]
|
[board_id]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { isSelected, isAutoAdd } = useAppSelector(selector);
|
const { isAutoAdd } = useAppSelector(selector);
|
||||||
const boardName = useBoardName(board_id);
|
const boardName = useBoardName(board_id);
|
||||||
|
|
||||||
const handleSelectBoard = useCallback(() => {
|
|
||||||
dispatch(boardIdSelected(board_id));
|
|
||||||
}, [board_id, dispatch]);
|
|
||||||
|
|
||||||
const handleSetAutoAdd = useCallback(() => {
|
const handleSetAutoAdd = useCallback(() => {
|
||||||
dispatch(autoAddBoardIdChanged(board_id));
|
dispatch(autoAddBoardIdChanged(board_id));
|
||||||
}, [board_id, dispatch]);
|
}, [board_id, dispatch]);
|
||||||
|
@ -1,21 +1,16 @@
|
|||||||
import { ButtonGroup, Collapse, Flex, Grid, GridItem } from '@chakra-ui/react';
|
import { Collapse, Flex, Grid, GridItem } from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import IAIIconButton from 'common/components/IAIIconButton';
|
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
|
||||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||||
import { memo, useCallback, useState } from 'react';
|
import { memo, useState } from 'react';
|
||||||
import { FaSearch } from 'react-icons/fa';
|
|
||||||
import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
|
import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
|
||||||
import { BoardDTO } from 'services/api/types';
|
import { BoardDTO } from 'services/api/types';
|
||||||
import { useFeatureStatus } from '../../../../system/hooks/useFeatureStatus';
|
|
||||||
import DeleteBoardModal from '../DeleteBoardModal';
|
import DeleteBoardModal from '../DeleteBoardModal';
|
||||||
import AddBoardButton from './AddBoardButton';
|
import AddBoardButton from './AddBoardButton';
|
||||||
import BoardsSearch from './BoardsSearch';
|
import BoardsSearch from './BoardsSearch';
|
||||||
import GalleryBoard from './GalleryBoard';
|
import GalleryBoard from './GalleryBoard';
|
||||||
import SystemBoardButton from './SystemBoardButton';
|
|
||||||
import NoBoardBoard from './NoBoardBoard';
|
import NoBoardBoard from './NoBoardBoard';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
@ -36,7 +31,6 @@ const BoardsList = (props: Props) => {
|
|||||||
const { isOpen } = props;
|
const { isOpen } = props;
|
||||||
const { selectedBoardId, searchText } = useAppSelector(selector);
|
const { selectedBoardId, searchText } = useAppSelector(selector);
|
||||||
const { data: boards } = useListAllBoardsQuery();
|
const { data: boards } = useListAllBoardsQuery();
|
||||||
const isBatchEnabled = useFeatureStatus('batches').isFeatureEnabled;
|
|
||||||
const filteredBoards = searchText
|
const filteredBoards = searchText
|
||||||
? boards?.filter((board) =>
|
? boards?.filter((board) =>
|
||||||
board.board_name.toLowerCase().includes(searchText.toLowerCase())
|
board.board_name.toLowerCase().includes(searchText.toLowerCase())
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
Badge,
|
|
||||||
Box,
|
Box,
|
||||||
ChakraProps,
|
|
||||||
Editable,
|
Editable,
|
||||||
EditableInput,
|
EditableInput,
|
||||||
EditablePreview,
|
EditablePreview,
|
||||||
@ -17,21 +15,16 @@ import { stateSelector } from 'app/store/store';
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import IAIDroppable from 'common/components/IAIDroppable';
|
import IAIDroppable from 'common/components/IAIDroppable';
|
||||||
|
import SelectionOverlay from 'common/components/SelectionOverlay';
|
||||||
import { boardIdSelected } from 'features/gallery/store/gallerySlice';
|
import { boardIdSelected } from 'features/gallery/store/gallerySlice';
|
||||||
import { memo, useCallback, useMemo, useState } from 'react';
|
import { memo, useCallback, useMemo, useState } from 'react';
|
||||||
import { FaUser } from 'react-icons/fa';
|
import { FaUser } from 'react-icons/fa';
|
||||||
import { useUpdateBoardMutation } from 'services/api/endpoints/boards';
|
import { useUpdateBoardMutation } from 'services/api/endpoints/boards';
|
||||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||||
import { useBoardTotal } from 'services/api/hooks/useBoardTotal';
|
|
||||||
import { BoardDTO } from 'services/api/types';
|
import { BoardDTO } from 'services/api/types';
|
||||||
import AutoAddIcon from '../AutoAddIcon';
|
import AutoAddIcon from '../AutoAddIcon';
|
||||||
import BoardContextMenu from '../BoardContextMenu';
|
import BoardContextMenu from '../BoardContextMenu';
|
||||||
import SelectionOverlay from 'common/components/SelectionOverlay';
|
|
||||||
|
|
||||||
const BASE_BADGE_STYLES: ChakraProps['sx'] = {
|
|
||||||
bg: 'base.500',
|
|
||||||
color: 'whiteAlpha.900',
|
|
||||||
};
|
|
||||||
interface GalleryBoardProps {
|
interface GalleryBoardProps {
|
||||||
board: BoardDTO;
|
board: BoardDTO;
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
@ -68,8 +61,6 @@ const GalleryBoard = memo(
|
|||||||
board.cover_image_name ?? skipToken
|
board.cover_image_name ?? skipToken
|
||||||
);
|
);
|
||||||
|
|
||||||
const { totalImages, totalAssets } = useBoardTotal(board.board_id);
|
|
||||||
|
|
||||||
const { board_name, board_id } = board;
|
const { board_name, board_id } = board;
|
||||||
const [localBoardName, setLocalBoardName] = useState(board_name);
|
const [localBoardName, setLocalBoardName] = useState(board_name);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { As, Badge, Flex } from '@chakra-ui/react';
|
|||||||
import { TypesafeDroppableData } from 'app/components/ImageDnd/typesafeDnd';
|
import { TypesafeDroppableData } from 'app/components/ImageDnd/typesafeDnd';
|
||||||
import IAIDroppable from 'common/components/IAIDroppable';
|
import IAIDroppable from 'common/components/IAIDroppable';
|
||||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||||
import { BoardId } from 'features/gallery/store/gallerySlice';
|
import { BoardId } from 'features/gallery/store/types';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import BoardContextMenu from '../BoardContextMenu';
|
import BoardContextMenu from '../BoardContextMenu';
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Box, ChakraProps, Flex, Image, Text } from '@chakra-ui/react';
|
import { Box, Flex, Image, Text } from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { MoveBoardDropData } from 'app/components/ImageDnd/typesafeDnd';
|
import { MoveBoardDropData } from 'app/components/ImageDnd/typesafeDnd';
|
||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
@ -10,14 +10,8 @@ import SelectionOverlay from 'common/components/SelectionOverlay';
|
|||||||
import { boardIdSelected } from 'features/gallery/store/gallerySlice';
|
import { boardIdSelected } from 'features/gallery/store/gallerySlice';
|
||||||
import { memo, useCallback, useMemo, useState } from 'react';
|
import { memo, useCallback, useMemo, useState } from 'react';
|
||||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||||
import { useBoardTotal } from 'services/api/hooks/useBoardTotal';
|
|
||||||
import AutoAddIcon from '../AutoAddIcon';
|
import AutoAddIcon from '../AutoAddIcon';
|
||||||
import BoardContextMenu from '../BoardContextMenu';
|
import BoardContextMenu from '../BoardContextMenu';
|
||||||
|
|
||||||
const BASE_BADGE_STYLES: ChakraProps['sx'] = {
|
|
||||||
bg: 'base.500',
|
|
||||||
color: 'whiteAlpha.900',
|
|
||||||
};
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
}
|
}
|
||||||
@ -33,7 +27,6 @@ const selector = createSelector(
|
|||||||
|
|
||||||
const NoBoardBoard = memo(({ isSelected }: Props) => {
|
const NoBoardBoard = memo(({ isSelected }: Props) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { totalImages, totalAssets } = useBoardTotal(undefined);
|
|
||||||
const { autoAddBoardId } = useAppSelector(selector);
|
const { autoAddBoardId } = useAppSelector(selector);
|
||||||
const boardName = useBoardName(undefined);
|
const boardName = useBoardName(undefined);
|
||||||
const handleSelectBoard = useCallback(() => {
|
const handleSelectBoard = useCallback(() => {
|
||||||
|
@ -11,14 +11,12 @@ import {
|
|||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
||||||
|
import { ImageUsage } from 'app/contexts/AddImageToBoardContext';
|
||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIButton from 'common/components/IAIButton';
|
import IAIButton from 'common/components/IAIButton';
|
||||||
import ImageUsageMessage from 'features/imageDeletion/components/ImageUsageMessage';
|
import ImageUsageMessage from 'features/imageDeletion/components/ImageUsageMessage';
|
||||||
import {
|
import { getImageUsage } from 'features/imageDeletion/store/imageDeletionSelectors';
|
||||||
ImageUsage,
|
|
||||||
getImageUsage,
|
|
||||||
} from 'features/imageDeletion/store/imageDeletionSlice';
|
|
||||||
import { some } from 'lodash-es';
|
import { some } from 'lodash-es';
|
||||||
import { memo, useCallback, useMemo, useRef } from 'react';
|
import { memo, useCallback, useMemo, useRef } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
import { MenuItem } from '@chakra-ui/react';
|
import { MenuItem } from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { memo, useCallback } from 'react';
|
||||||
import { stateSelector } from 'app/store/store';
|
import { FaTrash } from 'react-icons/fa';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
|
||||||
import { autoAddBoardIdChanged } from 'features/gallery/store/gallerySlice';
|
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
|
||||||
import { FaPlus, FaTrash } from 'react-icons/fa';
|
|
||||||
import { BoardDTO } from 'services/api/types';
|
import { BoardDTO } from 'services/api/types';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -14,25 +9,6 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const GalleryBoardContextMenuItems = ({ board, setBoardToDelete }: Props) => {
|
const GalleryBoardContextMenuItems = ({ board, setBoardToDelete }: Props) => {
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const selector = useMemo(
|
|
||||||
() =>
|
|
||||||
createSelector(
|
|
||||||
stateSelector,
|
|
||||||
({ gallery }) => {
|
|
||||||
const isSelectedForAutoAdd =
|
|
||||||
board.board_id === gallery.autoAddBoardId;
|
|
||||||
|
|
||||||
return { isSelectedForAutoAdd };
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
),
|
|
||||||
[board.board_id]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { isSelectedForAutoAdd } = useAppSelector(selector);
|
|
||||||
|
|
||||||
const handleDelete = useCallback(() => {
|
const handleDelete = useCallback(() => {
|
||||||
if (!setBoardToDelete) {
|
if (!setBoardToDelete) {
|
||||||
return;
|
return;
|
||||||
@ -40,12 +16,6 @@ const GalleryBoardContextMenuItems = ({ board, setBoardToDelete }: Props) => {
|
|||||||
setBoardToDelete(board);
|
setBoardToDelete(board);
|
||||||
}, [board, setBoardToDelete]);
|
}, [board, setBoardToDelete]);
|
||||||
|
|
||||||
const handleToggleAutoAdd = useCallback(() => {
|
|
||||||
dispatch(
|
|
||||||
autoAddBoardIdChanged(isSelectedForAutoAdd ? undefined : board.board_id)
|
|
||||||
);
|
|
||||||
}, [board.board_id, dispatch, isSelectedForAutoAdd]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{board.image_count > 0 && (
|
{board.image_count > 0 && (
|
||||||
@ -59,11 +29,6 @@ const GalleryBoardContextMenuItems = ({ board, setBoardToDelete }: Props) => {
|
|||||||
</MenuItem> */}
|
</MenuItem> */}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{/* {!isSelectedForAutoAdd && (
|
|
||||||
<MenuItem icon={<FaPlus />} onClick={handleToggleAutoAdd}>
|
|
||||||
Auto-add to this Board
|
|
||||||
</MenuItem>
|
|
||||||
)} */}
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
sx={{ color: 'error.600', _dark: { color: 'error.300' } }}
|
sx={{ color: 'error.600', _dark: { color: 'error.300' } }}
|
||||||
icon={<FaTrash />}
|
icon={<FaTrash />}
|
||||||
|
@ -1,19 +1,6 @@
|
|||||||
import { MenuItem } from '@chakra-ui/react';
|
import { memo } from 'react';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import { autoAddBoardIdChanged } from 'features/gallery/store/gallerySlice';
|
|
||||||
import { memo, useCallback } from 'react';
|
|
||||||
import { FaPlus } from 'react-icons/fa';
|
|
||||||
|
|
||||||
const NoBoardContextMenuItems = () => {
|
const NoBoardContextMenuItems = () => {
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const autoAddBoardId = useAppSelector(
|
|
||||||
(state) => state.gallery.autoAddBoardId
|
|
||||||
);
|
|
||||||
const handleDisableAutoAdd = useCallback(() => {
|
|
||||||
dispatch(autoAddBoardIdChanged(undefined));
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* {autoAddBoardId && (
|
{/* {autoAddBoardId && (
|
||||||
|
@ -108,7 +108,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
500
|
500
|
||||||
);
|
);
|
||||||
|
|
||||||
const { currentData: imageDTO, isFetching } = useGetImageDTOQuery(
|
const { currentData: imageDTO } = useGetImageDTOQuery(
|
||||||
lastSelectedImage ?? skipToken
|
lastSelectedImage ?? skipToken
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -8,17 +8,17 @@ import {
|
|||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIDndImage from 'common/components/IAIDndImage';
|
import IAIDndImage from 'common/components/IAIDndImage';
|
||||||
|
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||||
import { useNextPrevImage } from 'features/gallery/hooks/useNextPrevImage';
|
import { useNextPrevImage } from 'features/gallery/hooks/useNextPrevImage';
|
||||||
import { selectLastSelectedImage } from 'features/gallery/store/gallerySelectors';
|
import { selectLastSelectedImage } from 'features/gallery/store/gallerySelectors';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import { memo, useCallback, useMemo, useRef, useState } from 'react';
|
import { memo, useCallback, useMemo, useRef, useState } from 'react';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
|
import { FaImage } from 'react-icons/fa';
|
||||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||||
import ImageMetadataViewer from '../ImageMetadataViewer/ImageMetadataViewer';
|
import ImageMetadataViewer from '../ImageMetadataViewer/ImageMetadataViewer';
|
||||||
import NextPrevImageButtons from '../NextPrevImageButtons';
|
import NextPrevImageButtons from '../NextPrevImageButtons';
|
||||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
|
||||||
import { FaImage } from 'react-icons/fa';
|
|
||||||
|
|
||||||
export const imagesSelector = createSelector(
|
export const imagesSelector = createSelector(
|
||||||
[stateSelector, selectLastSelectedImage],
|
[stateSelector, selectLastSelectedImage],
|
||||||
@ -93,12 +93,7 @@ const CurrentImagePreview = () => {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const { currentData: imageDTO } = useGetImageDTOQuery(imageName ?? skipToken);
|
||||||
currentData: imageDTO,
|
|
||||||
isLoading,
|
|
||||||
isError,
|
|
||||||
isSuccess,
|
|
||||||
} = useGetImageDTOQuery(imageName ?? skipToken);
|
|
||||||
|
|
||||||
const draggableData = useMemo<TypesafeDraggableData | undefined>(() => {
|
const draggableData = useMemo<TypesafeDraggableData | undefined>(() => {
|
||||||
if (imageDTO) {
|
if (imageDTO) {
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
import { Flex, Image, Spinner } from '@chakra-ui/react';
|
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
|
||||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
|
||||||
import { memo } from 'react';
|
|
||||||
import { gallerySelector } from '../store/gallerySelectors';
|
|
||||||
|
|
||||||
const selector = createSelector(
|
|
||||||
[systemSelector, gallerySelector],
|
|
||||||
(system, gallery) => {
|
|
||||||
const { shouldUseSingleGalleryColumn, galleryImageObjectFit } = gallery;
|
|
||||||
const { progressImage, shouldAntialiasProgressImage } = system;
|
|
||||||
|
|
||||||
return {
|
|
||||||
progressImage,
|
|
||||||
shouldUseSingleGalleryColumn,
|
|
||||||
galleryImageObjectFit,
|
|
||||||
shouldAntialiasProgressImage,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
const GalleryProgressImage = () => {
|
|
||||||
const {
|
|
||||||
progressImage,
|
|
||||||
shouldUseSingleGalleryColumn,
|
|
||||||
galleryImageObjectFit,
|
|
||||||
shouldAntialiasProgressImage,
|
|
||||||
} = useAppSelector(selector);
|
|
||||||
|
|
||||||
if (!progressImage) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Flex
|
|
||||||
sx={{
|
|
||||||
w: 'full',
|
|
||||||
h: 'full',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
aspectRatio: '1/1',
|
|
||||||
position: 'relative',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
draggable={false}
|
|
||||||
src={progressImage.dataURL}
|
|
||||||
width={progressImage.width}
|
|
||||||
height={progressImage.height}
|
|
||||||
sx={{
|
|
||||||
objectFit: shouldUseSingleGalleryColumn
|
|
||||||
? 'contain'
|
|
||||||
: galleryImageObjectFit,
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
maxWidth: '100%',
|
|
||||||
maxHeight: '100%',
|
|
||||||
borderRadius: 'base',
|
|
||||||
imageRendering: shouldAntialiasProgressImage ? 'auto' : 'pixelated',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Spinner
|
|
||||||
sx={{ position: 'absolute', top: 1, right: 1, opacity: 0.7 }}
|
|
||||||
speed="1.2s"
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(GalleryProgressImage);
|
|
@ -1,9 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
Flex,
|
Flex,
|
||||||
Spacer,
|
|
||||||
Tab,
|
Tab,
|
||||||
TabList,
|
TabList,
|
||||||
Tabs,
|
Tabs,
|
||||||
@ -14,16 +12,16 @@ import { createSelector } from '@reduxjs/toolkit';
|
|||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
import IAIButton from 'common/components/IAIButton';
|
||||||
import { memo, useCallback, useRef } from 'react';
|
import { memo, useCallback, useRef } from 'react';
|
||||||
|
import { FaImages, FaServer } from 'react-icons/fa';
|
||||||
|
import { galleryViewChanged } from '../store/gallerySlice';
|
||||||
import BoardsList from './Boards/BoardsList/BoardsList';
|
import BoardsList from './Boards/BoardsList/BoardsList';
|
||||||
import GalleryBoardName from './GalleryBoardName';
|
import GalleryBoardName from './GalleryBoardName';
|
||||||
import GalleryPinButton from './GalleryPinButton';
|
import GalleryPinButton from './GalleryPinButton';
|
||||||
import GallerySettingsPopover from './GallerySettingsPopover';
|
import GallerySettingsPopover from './GallerySettingsPopover';
|
||||||
import BatchImageGrid from './ImageGrid/BatchImageGrid';
|
import BatchImageGrid from './ImageGrid/BatchImageGrid';
|
||||||
import GalleryImageGrid from './ImageGrid/GalleryImageGrid';
|
import GalleryImageGrid from './ImageGrid/GalleryImageGrid';
|
||||||
import IAIButton from 'common/components/IAIButton';
|
|
||||||
import { FaImages, FaServer } from 'react-icons/fa';
|
|
||||||
import { galleryViewChanged } from '../store/gallerySlice';
|
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
[stateSelector],
|
[stateSelector],
|
||||||
|
@ -8,13 +8,8 @@ import IAIDndImage from 'common/components/IAIDndImage';
|
|||||||
import IAIErrorLoadingImageFallback from 'common/components/IAIErrorLoadingImageFallback';
|
import IAIErrorLoadingImageFallback from 'common/components/IAIErrorLoadingImageFallback';
|
||||||
import IAIFillSkeleton from 'common/components/IAIFillSkeleton';
|
import IAIFillSkeleton from 'common/components/IAIFillSkeleton';
|
||||||
import ImageContextMenu from 'features/gallery/components/ImageContextMenu/ImageContextMenu';
|
import ImageContextMenu from 'features/gallery/components/ImageContextMenu/ImageContextMenu';
|
||||||
import {
|
import { imagesRemovedFromBatch } from 'features/gallery/store/gallerySlice';
|
||||||
imageRangeEndSelected,
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
imageSelected,
|
|
||||||
imageSelectionToggled,
|
|
||||||
imagesRemovedFromBatch,
|
|
||||||
} from 'features/gallery/store/gallerySlice';
|
|
||||||
import { MouseEvent, memo, useCallback, useMemo } from 'react';
|
|
||||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||||
|
|
||||||
const makeSelector = (image_name: string) =>
|
const makeSelector = (image_name: string) =>
|
||||||
@ -39,7 +34,6 @@ const BatchImage = (props: BatchImageProps) => {
|
|||||||
currentData: imageDTO,
|
currentData: imageDTO,
|
||||||
isLoading,
|
isLoading,
|
||||||
isError,
|
isError,
|
||||||
isSuccess,
|
|
||||||
} = useGetImageDTOQuery(imageName);
|
} = useGetImageDTOQuery(imageName);
|
||||||
const selector = useMemo(() => makeSelector(imageName), [imageName]);
|
const selector = useMemo(() => makeSelector(imageName), [imageName]);
|
||||||
|
|
||||||
@ -49,18 +43,18 @@ const BatchImage = (props: BatchImageProps) => {
|
|||||||
dispatch(imagesRemovedFromBatch([imageName]));
|
dispatch(imagesRemovedFromBatch([imageName]));
|
||||||
}, [dispatch, imageName]);
|
}, [dispatch, imageName]);
|
||||||
|
|
||||||
const handleClick = useCallback(
|
// const handleClick = useCallback(
|
||||||
(e: MouseEvent<HTMLDivElement>) => {
|
// (e: MouseEvent<HTMLDivElement>) => {
|
||||||
if (e.shiftKey) {
|
// if (e.shiftKey) {
|
||||||
dispatch(imageRangeEndSelected(imageName));
|
// dispatch(imageRangeEndSelected(imageName));
|
||||||
} else if (e.ctrlKey || e.metaKey) {
|
// } else if (e.ctrlKey || e.metaKey) {
|
||||||
dispatch(imageSelectionToggled(imageName));
|
// dispatch(imageSelectionToggled(imageName));
|
||||||
} else {
|
// } else {
|
||||||
dispatch(imageSelected(imageName));
|
// dispatch(imageSelected(imageName));
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
[dispatch, imageName]
|
// [dispatch, imageName]
|
||||||
);
|
// );
|
||||||
|
|
||||||
const draggableData = useMemo<TypesafeDraggableData | undefined>(() => {
|
const draggableData = useMemo<TypesafeDraggableData | undefined>(() => {
|
||||||
if (selectionCount > 1) {
|
if (selectionCount > 1) {
|
||||||
@ -105,7 +99,7 @@ const BatchImage = (props: BatchImageProps) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IAIDndImage
|
<IAIDndImage
|
||||||
onClick={handleClick}
|
// onClick={handleClick}
|
||||||
imageDTO={imageDTO}
|
imageDTO={imageDTO}
|
||||||
draggableData={draggableData}
|
draggableData={draggableData}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user