mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): clean up logging namespaces, allow skipping namespaces
This commit is contained in:
parent
e83513882a
commit
4da4b3bd50
@ -1106,7 +1106,6 @@
|
|||||||
"confirmOnDelete": "Confirm On Delete",
|
"confirmOnDelete": "Confirm On Delete",
|
||||||
"developer": "Developer",
|
"developer": "Developer",
|
||||||
"displayInProgress": "Display Progress Images",
|
"displayInProgress": "Display Progress Images",
|
||||||
"enableImageDebugging": "Enable Image Debugging",
|
|
||||||
"enableInformationalPopovers": "Enable Informational Popovers",
|
"enableInformationalPopovers": "Enable Informational Popovers",
|
||||||
"informationalPopoversDisabled": "Informational Popovers Disabled",
|
"informationalPopoversDisabled": "Informational Popovers Disabled",
|
||||||
"informationalPopoversDisabledDesc": "Informational popovers have been disabled. Enable them in Settings.",
|
"informationalPopoversDisabledDesc": "Informational popovers have been disabled. Enable them in Settings.",
|
||||||
@ -1817,5 +1816,30 @@
|
|||||||
"upscaling": "Upscaling",
|
"upscaling": "Upscaling",
|
||||||
"upscalingTab": "$t(ui.tabs.upscaling) $t(common.tab)"
|
"upscalingTab": "$t(ui.tabs.upscaling) $t(common.tab)"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"system": {
|
||||||
|
"enableLogging": "Enable Logging",
|
||||||
|
"logLevel": {
|
||||||
|
"logLevel": "Log Level",
|
||||||
|
"trace": "Trace",
|
||||||
|
"debug": "Debug",
|
||||||
|
"info": "Info",
|
||||||
|
"warn": "Warn",
|
||||||
|
"error": "Error",
|
||||||
|
"fatal": "Fatal"
|
||||||
|
},
|
||||||
|
"logNamespaces": {
|
||||||
|
"logNamespaces": "Log Namespaces",
|
||||||
|
"gallery": "Gallery",
|
||||||
|
"models": "Models",
|
||||||
|
"config": "Config",
|
||||||
|
"canvas": "Canvas",
|
||||||
|
"generation": "Generation",
|
||||||
|
"workflows": "Workflows",
|
||||||
|
"system": "System",
|
||||||
|
"events": "Events",
|
||||||
|
"queue": "Queue",
|
||||||
|
"metadata": "Metadata"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,24 +15,23 @@ export const BASE_CONTEXT = {};
|
|||||||
|
|
||||||
export const $logger = atom<Logger>(Roarr.child(BASE_CONTEXT));
|
export const $logger = atom<Logger>(Roarr.child(BASE_CONTEXT));
|
||||||
|
|
||||||
export type LoggerNamespace =
|
export const zLogNamespace = z.enum([
|
||||||
| 'images'
|
'gallery',
|
||||||
| 'models'
|
'models',
|
||||||
| 'config'
|
'config',
|
||||||
| 'canvas'
|
'canvas',
|
||||||
| 'generation'
|
'generation',
|
||||||
| 'nodes'
|
'workflows',
|
||||||
| 'system'
|
'system',
|
||||||
| 'socketio'
|
'events',
|
||||||
| 'session'
|
'queue',
|
||||||
| 'queue'
|
'metadata',
|
||||||
| 'dnd'
|
]);
|
||||||
| 'controlLayers'
|
const zLogNamespacesArray = z.array(zLogNamespace);
|
||||||
| 'metadata'
|
export type LogNamespace = z.infer<typeof zLogNamespace>;
|
||||||
| 'konva'
|
export const isLogNamespaceArray = (v: unknown): v is LogNamespace[] => zLogNamespacesArray.safeParse(v).success;
|
||||||
| 'worker';
|
|
||||||
|
|
||||||
export const logger = (namespace: LoggerNamespace) => $logger.get().child({ namespace });
|
export const logger = (namespace: LogNamespace) => $logger.get().child({ namespace });
|
||||||
|
|
||||||
export const zLogLevel = z.enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal']);
|
export const zLogLevel = z.enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal']);
|
||||||
export type LogLevel = z.infer<typeof zLogLevel>;
|
export type LogLevel = z.infer<typeof zLogLevel>;
|
||||||
|
@ -3,27 +3,35 @@ import { useAppSelector } from 'app/store/storeHooks';
|
|||||||
import { useEffect, useMemo } from 'react';
|
import { useEffect, useMemo } from 'react';
|
||||||
import { ROARR, Roarr } from 'roarr';
|
import { ROARR, Roarr } from 'roarr';
|
||||||
|
|
||||||
import type { LoggerNamespace } from './logger';
|
import type { LogNamespace } from './logger';
|
||||||
import { $logger, BASE_CONTEXT, LOG_LEVEL_MAP, logger } from './logger';
|
import { $logger, BASE_CONTEXT, LOG_LEVEL_MAP, logger } from './logger';
|
||||||
|
|
||||||
export const useLogger = (namespace: LoggerNamespace) => {
|
export const useLogger = (namespace: LogNamespace) => {
|
||||||
const consoleLogLevel = useAppSelector((s) => s.system.consoleLogLevel);
|
const logLevel = useAppSelector((s) => s.system.logLevel);
|
||||||
const shouldLogToConsole = useAppSelector((s) => s.system.shouldLogToConsole);
|
const logNamespaces = useAppSelector((s) => s.system.logNamespaces);
|
||||||
|
const logIsEnabled = useAppSelector((s) => s.system.logIsEnabled);
|
||||||
|
|
||||||
// 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(() => {
|
||||||
if (shouldLogToConsole) {
|
if (logIsEnabled) {
|
||||||
// Enable console log output
|
// Enable console log output
|
||||||
localStorage.setItem('ROARR_LOG', 'true');
|
localStorage.setItem('ROARR_LOG', 'true');
|
||||||
|
|
||||||
// Use a filter to show only logs of the given level
|
// Use a filter to show only logs of the given level
|
||||||
localStorage.setItem('ROARR_FILTER', `context.logLevel:>=${LOG_LEVEL_MAP[consoleLogLevel]}`);
|
let filter = `context.logLevel:>=${LOG_LEVEL_MAP[logLevel]}`;
|
||||||
|
if (logNamespaces.length > 0) {
|
||||||
|
filter += ' AND ';
|
||||||
|
filter = `(${logNamespaces.map((ns) => `context.namespace:${ns}`).join(' OR ')})`;
|
||||||
|
} else {
|
||||||
|
filter += ' AND context.namespace:undefined';
|
||||||
|
}
|
||||||
|
localStorage.setItem('ROARR_FILTER', filter);
|
||||||
} else {
|
} else {
|
||||||
// Disable console log output
|
// Disable console log output
|
||||||
localStorage.setItem('ROARR_LOG', 'false');
|
localStorage.setItem('ROARR_LOG', 'false');
|
||||||
}
|
}
|
||||||
ROARR.write = createLogWriter();
|
ROARR.write = createLogWriter();
|
||||||
}, [consoleLogLevel, shouldLogToConsole]);
|
}, [logLevel, logIsEnabled, logNamespaces]);
|
||||||
|
|
||||||
// Update the module-scoped logger context as needed
|
// Update the module-scoped logger context as needed
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -8,14 +8,14 @@ import { t } from 'i18next';
|
|||||||
import { queueApi } from 'services/api/endpoints/queue';
|
import { queueApi } from 'services/api/endpoints/queue';
|
||||||
import type { BatchConfig, ImageDTO } from 'services/api/types';
|
import type { BatchConfig, ImageDTO } from 'services/api/types';
|
||||||
|
|
||||||
|
const log = logger('queue');
|
||||||
|
|
||||||
export const adHocPostProcessingRequested = createAction<{ imageDTO: ImageDTO }>(`upscaling/postProcessingRequested`);
|
export const adHocPostProcessingRequested = createAction<{ imageDTO: ImageDTO }>(`upscaling/postProcessingRequested`);
|
||||||
|
|
||||||
export const addAdHocPostProcessingRequestedListener = (startAppListening: AppStartListening) => {
|
export const addAdHocPostProcessingRequestedListener = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: adHocPostProcessingRequested,
|
actionCreator: adHocPostProcessingRequested,
|
||||||
effect: async (action, { dispatch, getState }) => {
|
effect: async (action, { dispatch, getState }) => {
|
||||||
const log = logger('session');
|
|
||||||
|
|
||||||
const { imageDTO } = action.payload;
|
const { imageDTO } = action.payload;
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
|
@ -13,12 +13,12 @@ import { queueApi } from 'services/api/endpoints/queue';
|
|||||||
import { $lastCanvasProgressEvent } from 'services/events/setEventListeners';
|
import { $lastCanvasProgressEvent } from 'services/events/setEventListeners';
|
||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
|
|
||||||
|
const log = logger('canvas');
|
||||||
|
|
||||||
export const addStagingListeners = (startAppListening: AppStartListening) => {
|
export const addStagingListeners = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: sessionStagingAreaReset,
|
actionCreator: sessionStagingAreaReset,
|
||||||
effect: async (_, { dispatch }) => {
|
effect: async (_, { dispatch }) => {
|
||||||
const log = logger('canvas');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const req = dispatch(
|
const req = dispatch(
|
||||||
queueApi.endpoints.cancelByBatchOrigin.initiate(
|
queueApi.endpoints.cancelByBatchOrigin.initiate(
|
||||||
|
@ -7,6 +7,8 @@ import { t } from 'i18next';
|
|||||||
import { truncate, upperFirst } from 'lodash-es';
|
import { truncate, upperFirst } from 'lodash-es';
|
||||||
import { queueApi } from 'services/api/endpoints/queue';
|
import { queueApi } from 'services/api/endpoints/queue';
|
||||||
|
|
||||||
|
const log = logger('queue');
|
||||||
|
|
||||||
export const addBatchEnqueuedListener = (startAppListening: AppStartListening) => {
|
export const addBatchEnqueuedListener = (startAppListening: AppStartListening) => {
|
||||||
// success
|
// success
|
||||||
startAppListening({
|
startAppListening({
|
||||||
@ -14,7 +16,7 @@ export const addBatchEnqueuedListener = (startAppListening: AppStartListening) =
|
|||||||
effect: async (action) => {
|
effect: async (action) => {
|
||||||
const response = action.payload;
|
const response = action.payload;
|
||||||
const arg = action.meta.arg.originalArgs;
|
const arg = action.meta.arg.originalArgs;
|
||||||
logger('queue').debug({ enqueueResult: parseify(response) }, 'Batch enqueued');
|
log.debug({ enqueueResult: parseify(response) }, 'Batch enqueued');
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
id: 'QUEUE_BATCH_SUCCEEDED',
|
id: 'QUEUE_BATCH_SUCCEEDED',
|
||||||
@ -42,7 +44,7 @@ export const addBatchEnqueuedListener = (startAppListening: AppStartListening) =
|
|||||||
status: 'error',
|
status: 'error',
|
||||||
description: t('common.unknownError'),
|
description: t('common.unknownError'),
|
||||||
});
|
});
|
||||||
logger('queue').error({ batchConfig: parseify(arg), error: parseify(response) }, t('queue.batchFailedToQueue'));
|
log.error({ batchConfig: parseify(arg), error: parseify(response) }, t('queue.batchFailedToQueue'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ export const addBatchEnqueuedListener = (startAppListening: AppStartListening) =
|
|||||||
description: t('common.unknownError'),
|
description: t('common.unknownError'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
logger('queue').error({ batchConfig: parseify(arg), error: parseify(response) }, t('queue.batchFailedToQueue'));
|
log.error({ batchConfig: parseify(arg), error: parseify(response) }, t('queue.batchFailedToQueue'));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ import { toast } from 'features/toast/toast';
|
|||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
|
|
||||||
const log = logger('images');
|
const log = logger('gallery');
|
||||||
|
|
||||||
export const addBulkDownloadListeners = (startAppListening: AppStartListening) => {
|
export const addBulkDownloadListeners = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
|
@ -7,11 +7,12 @@ import { toast } from 'features/toast/toast';
|
|||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
|
|
||||||
|
const log = logger('canvas');
|
||||||
|
|
||||||
export const addCanvasImageToControlNetListener = (startAppListening: AppStartListening) => {
|
export const addCanvasImageToControlNetListener = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: canvasImageToControlAdapter,
|
actionCreator: canvasImageToControlAdapter,
|
||||||
effect: async (action, { dispatch, getState }) => {
|
effect: async (action, { dispatch, getState }) => {
|
||||||
const log = logger('canvas');
|
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { id } = action.payload;
|
const { id } = action.payload;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ import { assert } from 'tsafe';
|
|||||||
const matcher = isAnyOf(caImageChanged, caProcessedImageChanged, caProcessorConfigChanged, caModelChanged, caRecalled);
|
const matcher = isAnyOf(caImageChanged, caProcessedImageChanged, caProcessorConfigChanged, caModelChanged, caRecalled);
|
||||||
|
|
||||||
const DEBOUNCE_MS = 300;
|
const DEBOUNCE_MS = 300;
|
||||||
const log = logger('session');
|
const log = logger('queue');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple helper to cancel a batch and reset the pending batch ID
|
* Simple helper to cancel a batch and reset the pending batch ID
|
||||||
|
@ -6,7 +6,7 @@ import { parseify } from 'common/util/serialize';
|
|||||||
import { canvasBatchIdAdded, stagingAreaInitialized } from 'features/canvas/store/canvasSlice';
|
import { canvasBatchIdAdded, stagingAreaInitialized } from 'features/canvas/store/canvasSlice';
|
||||||
import { getCanvasData } from 'features/canvas/util/getCanvasData';
|
import { getCanvasData } from 'features/canvas/util/getCanvasData';
|
||||||
import { getCanvasGenerationMode } from 'features/canvas/util/getCanvasGenerationMode';
|
import { getCanvasGenerationMode } from 'features/canvas/util/getCanvasGenerationMode';
|
||||||
import { blobToDataURL } from "features/controlLayers/konva/util";
|
import { blobToDataURL } from 'features/controlLayers/konva/util';
|
||||||
import { canvasGraphBuilt } from 'features/nodes/store/actions';
|
import { canvasGraphBuilt } from 'features/nodes/store/actions';
|
||||||
import { prepareLinearUIBatch } from 'features/nodes/util/graph/buildLinearBatchConfig';
|
import { prepareLinearUIBatch } from 'features/nodes/util/graph/buildLinearBatchConfig';
|
||||||
import { buildCanvasGraph } from 'features/nodes/util/graph/canvas/buildCanvasGraph';
|
import { buildCanvasGraph } from 'features/nodes/util/graph/canvas/buildCanvasGraph';
|
||||||
@ -14,6 +14,8 @@ import { imagesApi } from 'services/api/endpoints/images';
|
|||||||
import { queueApi } from 'services/api/endpoints/queue';
|
import { queueApi } from 'services/api/endpoints/queue';
|
||||||
import type { ImageDTO } from 'services/api/types';
|
import type { ImageDTO } from 'services/api/types';
|
||||||
|
|
||||||
|
const log = logger('queue');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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:
|
||||||
*
|
*
|
||||||
@ -32,7 +34,6 @@ export const addEnqueueRequestedCanvasListener = (startAppListening: AppStartLis
|
|||||||
predicate: (action): action is ReturnType<typeof enqueueRequested> =>
|
predicate: (action): action is ReturnType<typeof enqueueRequested> =>
|
||||||
enqueueRequested.match(action) && action.payload.tabName === 'canvas',
|
enqueueRequested.match(action) && action.payload.tabName === 'canvas',
|
||||||
effect: async (action, { getState, dispatch }) => {
|
effect: async (action, { getState, dispatch }) => {
|
||||||
const log = logger('queue');
|
|
||||||
const { prepend } = action.payload;
|
const { prepend } = action.payload;
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
|
@ -6,11 +6,12 @@ import { parseSchema } from 'features/nodes/util/schema/parseSchema';
|
|||||||
import { size } from 'lodash-es';
|
import { size } from 'lodash-es';
|
||||||
import { appInfoApi } from 'services/api/endpoints/appInfo';
|
import { appInfoApi } from 'services/api/endpoints/appInfo';
|
||||||
|
|
||||||
|
const log = logger('system');
|
||||||
|
|
||||||
export const addGetOpenAPISchemaListener = (startAppListening: AppStartListening) => {
|
export const addGetOpenAPISchemaListener = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: appInfoApi.endpoints.getOpenAPISchema.matchFulfilled,
|
matcher: appInfoApi.endpoints.getOpenAPISchema.matchFulfilled,
|
||||||
effect: (action, { getState }) => {
|
effect: (action, { getState }) => {
|
||||||
const log = logger('system');
|
|
||||||
const schemaJSON = action.payload;
|
const schemaJSON = action.payload;
|
||||||
|
|
||||||
log.debug({ schemaJSON: parseify(schemaJSON) }, 'Received OpenAPI schema');
|
log.debug({ schemaJSON: parseify(schemaJSON) }, 'Received OpenAPI schema');
|
||||||
@ -30,7 +31,6 @@ export const addGetOpenAPISchemaListener = (startAppListening: AppStartListening
|
|||||||
// If action.meta.condition === true, the request was canceled/skipped because another request was in flight or
|
// If action.meta.condition === true, the request was canceled/skipped because another request was in flight or
|
||||||
// the value was already in the cache. We don't want to log these errors.
|
// the value was already in the cache. We don't want to log these errors.
|
||||||
if (!action.meta.condition) {
|
if (!action.meta.condition) {
|
||||||
const log = logger('system');
|
|
||||||
log.error({ error: parseify(action.error) }, 'Problem retrieving OpenAPI Schema');
|
log.error({ error: parseify(action.error) }, 'Problem retrieving OpenAPI Schema');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2,15 +2,13 @@ import { logger } from 'app/logging/logger';
|
|||||||
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
|
|
||||||
|
const log = logger('gallery');
|
||||||
|
|
||||||
export const addImageAddedToBoardFulfilledListener = (startAppListening: AppStartListening) => {
|
export const addImageAddedToBoardFulfilledListener = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.addImageToBoard.matchFulfilled,
|
matcher: imagesApi.endpoints.addImageToBoard.matchFulfilled,
|
||||||
effect: (action) => {
|
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
|
|
||||||
|
|
||||||
log.debug({ board_id, imageDTO }, 'Image added to board');
|
log.debug({ board_id, imageDTO }, 'Image added to board');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -18,9 +16,7 @@ export const addImageAddedToBoardFulfilledListener = (startAppListening: AppStar
|
|||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.addImageToBoard.matchRejected,
|
matcher: imagesApi.endpoints.addImageToBoard.matchRejected,
|
||||||
effect: (action) => {
|
effect: (action) => {
|
||||||
const log = logger('images');
|
|
||||||
const { board_id, imageDTO } = action.meta.arg.originalArgs;
|
const { board_id, imageDTO } = action.meta.arg.originalArgs;
|
||||||
|
|
||||||
log.debug({ board_id, imageDTO }, 'Problem adding image to board');
|
log.debug({ board_id, imageDTO }, 'Problem adding image to board');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -13,6 +13,8 @@ import { forEach, intersectionBy } from 'lodash-es';
|
|||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
import type { ImageDTO } from 'services/api/types';
|
import type { ImageDTO } from 'services/api/types';
|
||||||
|
|
||||||
|
const log = logger('gallery');
|
||||||
|
|
||||||
// Some utils to delete images from different parts of the app
|
// Some utils to delete images from different parts of the app
|
||||||
const deleteNodesImages = (state: RootState, dispatch: AppDispatch, imageDTO: ImageDTO) => {
|
const deleteNodesImages = (state: RootState, dispatch: AppDispatch, imageDTO: ImageDTO) => {
|
||||||
state.nodes.present.nodes.forEach((node) => {
|
state.nodes.present.nodes.forEach((node) => {
|
||||||
@ -185,7 +187,6 @@ export const addImageDeletionListeners = (startAppListening: AppStartListening)
|
|||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.deleteImage.matchFulfilled,
|
matcher: imagesApi.endpoints.deleteImage.matchFulfilled,
|
||||||
effect: (action) => {
|
effect: (action) => {
|
||||||
const log = logger('images');
|
|
||||||
log.debug({ imageDTO: action.meta.arg.originalArgs }, 'Image deleted');
|
log.debug({ imageDTO: action.meta.arg.originalArgs }, 'Image deleted');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -193,7 +194,6 @@ export const addImageDeletionListeners = (startAppListening: AppStartListening)
|
|||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.deleteImage.matchRejected,
|
matcher: imagesApi.endpoints.deleteImage.matchRejected,
|
||||||
effect: (action) => {
|
effect: (action) => {
|
||||||
const log = logger('images');
|
|
||||||
log.debug({ imageDTO: action.meta.arg.originalArgs }, 'Unable to delete image');
|
log.debug({ imageDTO: action.meta.arg.originalArgs }, 'Unable to delete image');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -2,11 +2,7 @@ import { createAction } from '@reduxjs/toolkit';
|
|||||||
import { logger } from 'app/logging/logger';
|
import { logger } from 'app/logging/logger';
|
||||||
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
||||||
import { parseify } from 'common/util/serialize';
|
import { parseify } from 'common/util/serialize';
|
||||||
import {
|
import { ipaImageChanged, rasterLayerAdded, rgIPAdapterImageChanged } from 'features/controlLayers/store/canvasV2Slice';
|
||||||
ipaImageChanged,
|
|
||||||
rasterLayerAdded,
|
|
||||||
rgIPAdapterImageChanged,
|
|
||||||
} from 'features/controlLayers/store/canvasV2Slice';
|
|
||||||
import type { CanvasRasterLayerState } from 'features/controlLayers/store/types';
|
import type { CanvasRasterLayerState } from 'features/controlLayers/store/types';
|
||||||
import { imageDTOToImageObject } from 'features/controlLayers/store/types';
|
import { imageDTOToImageObject } from 'features/controlLayers/store/types';
|
||||||
import type { TypesafeDraggableData, TypesafeDroppableData } from 'features/dnd/types';
|
import type { TypesafeDraggableData, TypesafeDroppableData } from 'features/dnd/types';
|
||||||
@ -26,11 +22,12 @@ export const dndDropped = createAction<{
|
|||||||
activeData: TypesafeDraggableData;
|
activeData: TypesafeDraggableData;
|
||||||
}>('dnd/dndDropped');
|
}>('dnd/dndDropped');
|
||||||
|
|
||||||
|
const log = logger('system');
|
||||||
|
|
||||||
export const addImageDroppedListener = (startAppListening: AppStartListening) => {
|
export const addImageDroppedListener = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: dndDropped,
|
actionCreator: dndDropped,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch, getState }) => {
|
||||||
const log = logger('dnd');
|
|
||||||
const { activeData, overData } = action.payload;
|
const { activeData, overData } = action.payload;
|
||||||
if (!isValidDrop(overData, activeData)) {
|
if (!isValidDrop(overData, activeData)) {
|
||||||
return;
|
return;
|
||||||
|
@ -2,13 +2,13 @@ import { logger } from 'app/logging/logger';
|
|||||||
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
|
|
||||||
|
const log = logger('gallery');
|
||||||
|
|
||||||
export const addImageRemovedFromBoardFulfilledListener = (startAppListening: AppStartListening) => {
|
export const addImageRemovedFromBoardFulfilledListener = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.removeImageFromBoard.matchFulfilled,
|
matcher: imagesApi.endpoints.removeImageFromBoard.matchFulfilled,
|
||||||
effect: (action) => {
|
effect: (action) => {
|
||||||
const log = logger('images');
|
|
||||||
const imageDTO = action.meta.arg.originalArgs;
|
const imageDTO = action.meta.arg.originalArgs;
|
||||||
|
|
||||||
log.debug({ imageDTO }, 'Image removed from board');
|
log.debug({ imageDTO }, 'Image removed from board');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -16,9 +16,7 @@ export const addImageRemovedFromBoardFulfilledListener = (startAppListening: App
|
|||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.removeImageFromBoard.matchRejected,
|
matcher: imagesApi.endpoints.removeImageFromBoard.matchRejected,
|
||||||
effect: (action) => {
|
effect: (action) => {
|
||||||
const log = logger('images');
|
|
||||||
const imageDTO = action.meta.arg.originalArgs;
|
const imageDTO = action.meta.arg.originalArgs;
|
||||||
|
|
||||||
log.debug({ imageDTO }, 'Problem removing image from board');
|
log.debug({ imageDTO }, 'Problem removing image from board');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -10,11 +10,12 @@ import { omit } from 'lodash-es';
|
|||||||
import { boardsApi } from 'services/api/endpoints/boards';
|
import { boardsApi } from 'services/api/endpoints/boards';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
|
|
||||||
|
const log = logger('gallery');
|
||||||
|
|
||||||
export const addImageUploadedFulfilledListener = (startAppListening: AppStartListening) => {
|
export const addImageUploadedFulfilledListener = (startAppListening: AppStartListening) => {
|
||||||
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 { autoAddBoardId } = state.gallery;
|
const { autoAddBoardId } = state.gallery;
|
||||||
@ -112,7 +113,6 @@ export const addImageUploadedFulfilledListener = (startAppListening: AppStartLis
|
|||||||
startAppListening({
|
startAppListening({
|
||||||
matcher: imagesApi.endpoints.uploadImage.matchRejected,
|
matcher: imagesApi.endpoints.uploadImage.matchRejected,
|
||||||
effect: (action) => {
|
effect: (action) => {
|
||||||
const log = logger('images');
|
|
||||||
const sanitizedData = {
|
const sanitizedData = {
|
||||||
arg: {
|
arg: {
|
||||||
...omit(action.meta.arg.originalArgs, ['file', 'postUploadAction']),
|
...omit(action.meta.arg.originalArgs, ['file', 'postUploadAction']),
|
||||||
|
@ -1,21 +1,17 @@
|
|||||||
import { logger } from 'app/logging/logger';
|
import { logger } from 'app/logging/logger';
|
||||||
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
||||||
import {
|
import { loraDeleted, modelChanged, vaeSelected } from 'features/controlLayers/store/canvasV2Slice';
|
||||||
loraDeleted,
|
|
||||||
modelChanged,
|
|
||||||
vaeSelected,
|
|
||||||
} from 'features/controlLayers/store/canvasV2Slice';
|
|
||||||
import { modelSelected } from 'features/parameters/store/actions';
|
import { modelSelected } from 'features/parameters/store/actions';
|
||||||
import { zParameterModel } from 'features/parameters/types/parameterSchemas';
|
import { zParameterModel } from 'features/parameters/types/parameterSchemas';
|
||||||
import { toast } from 'features/toast/toast';
|
import { toast } from 'features/toast/toast';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
|
|
||||||
|
const log = logger('models');
|
||||||
|
|
||||||
export const addModelSelectedListener = (startAppListening: AppStartListening) => {
|
export const addModelSelectedListener = (startAppListening: AppStartListening) => {
|
||||||
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 = zParameterModel.safeParse(action.payload);
|
const result = zParameterModel.safeParse(action.payload);
|
||||||
|
|
||||||
|
@ -30,12 +30,13 @@ import {
|
|||||||
isVAEModelConfig,
|
isVAEModelConfig,
|
||||||
} from 'services/api/types';
|
} from 'services/api/types';
|
||||||
|
|
||||||
|
const log = logger('models');
|
||||||
|
|
||||||
export const addModelsLoadedListener = (startAppListening: AppStartListening) => {
|
export const addModelsLoadedListener = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
predicate: modelsApi.endpoints.getModelConfigs.matchFulfilled,
|
predicate: modelsApi.endpoints.getModelConfigs.matchFulfilled,
|
||||||
effect: (action, { getState, dispatch }) => {
|
effect: (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 }, `Models loaded (${action.payload.ids.length})`);
|
log.info({ models: action.payload.entities }, `Models loaded (${action.payload.ids.length})`);
|
||||||
|
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
@ -8,7 +8,7 @@ import { modelsApi } from 'services/api/endpoints/models';
|
|||||||
import { queueApi, selectQueueStatus } from 'services/api/endpoints/queue';
|
import { queueApi, selectQueueStatus } from 'services/api/endpoints/queue';
|
||||||
import { socketConnected } from 'services/events/setEventListeners';
|
import { socketConnected } from 'services/events/setEventListeners';
|
||||||
|
|
||||||
const log = logger('socketio');
|
const log = logger('events');
|
||||||
|
|
||||||
const $isFirstConnection = atom(true);
|
const $isFirstConnection = atom(true);
|
||||||
|
|
||||||
|
@ -8,11 +8,12 @@ import { getNeedsUpdate, updateNode } from 'features/nodes/util/node/nodeUpdate'
|
|||||||
import { toast } from 'features/toast/toast';
|
import { toast } from 'features/toast/toast';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
|
|
||||||
|
const log = logger('workflows');
|
||||||
|
|
||||||
export const addUpdateAllNodesRequestedListener = (startAppListening: AppStartListening) => {
|
export const addUpdateAllNodesRequestedListener = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: updateAllNodesRequested,
|
actionCreator: updateAllNodesRequested,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch, getState }) => {
|
||||||
const log = logger('nodes');
|
|
||||||
const { nodes } = getState().nodes.present;
|
const { nodes } = getState().nodes.present;
|
||||||
const templates = $templates.get();
|
const templates = $templates.get();
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ import type { GraphAndWorkflowResponse, NonNullableGraph } from 'services/api/ty
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { fromZodError } from 'zod-validation-error';
|
import { fromZodError } from 'zod-validation-error';
|
||||||
|
|
||||||
|
const log = logger('workflows');
|
||||||
|
|
||||||
const getWorkflow = async (data: GraphAndWorkflowResponse, templates: Templates) => {
|
const getWorkflow = async (data: GraphAndWorkflowResponse, templates: Templates) => {
|
||||||
if (data.workflow) {
|
if (data.workflow) {
|
||||||
// Prefer to load the workflow if it's available - it has more information
|
// Prefer to load the workflow if it's available - it has more information
|
||||||
@ -35,7 +37,6 @@ export const addWorkflowLoadRequestedListener = (startAppListening: AppStartList
|
|||||||
startAppListening({
|
startAppListening({
|
||||||
actionCreator: workflowLoadRequested,
|
actionCreator: workflowLoadRequested,
|
||||||
effect: async (action, { dispatch }) => {
|
effect: async (action, { dispatch }) => {
|
||||||
const log = logger('nodes');
|
|
||||||
const { data, asCopy } = action.payload;
|
const { data, asCopy } = action.payload;
|
||||||
const nodeTemplates = $templates.get();
|
const nodeTemplates = $templates.get();
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ import { actionsDenylist } from './middleware/devtools/actionsDenylist';
|
|||||||
import { stateSanitizer } from './middleware/devtools/stateSanitizer';
|
import { stateSanitizer } from './middleware/devtools/stateSanitizer';
|
||||||
import { listenerMiddleware } from './middleware/listenerMiddleware';
|
import { listenerMiddleware } from './middleware/listenerMiddleware';
|
||||||
|
|
||||||
|
const log = logger('system');
|
||||||
|
|
||||||
const allReducers = {
|
const allReducers = {
|
||||||
[api.reducerPath]: api.reducer,
|
[api.reducerPath]: api.reducer,
|
||||||
[gallerySlice.name]: gallerySlice.reducer,
|
[gallerySlice.name]: gallerySlice.reducer,
|
||||||
@ -98,7 +100,6 @@ const persistConfigs: { [key in keyof typeof allReducers]?: PersistConfig } = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const unserialize: UnserializeFunction = (data, key) => {
|
const unserialize: UnserializeFunction = (data, key) => {
|
||||||
const log = logger('system');
|
|
||||||
const persistConfig = persistConfigs[key as keyof typeof persistConfigs];
|
const persistConfig = persistConfigs[key as keyof typeof persistConfigs];
|
||||||
if (!persistConfig) {
|
if (!persistConfig) {
|
||||||
throw new Error(`No persist config for slice "${key}"`);
|
throw new Error(`No persist config for slice "${key}"`);
|
||||||
|
@ -54,7 +54,6 @@ export class CanvasManager {
|
|||||||
background: CanvasBackground;
|
background: CanvasBackground;
|
||||||
|
|
||||||
log: Logger;
|
log: Logger;
|
||||||
workerLog: Logger;
|
|
||||||
socket: AppSocket;
|
socket: AppSocket;
|
||||||
|
|
||||||
_store: AppStore;
|
_store: AppStore;
|
||||||
@ -85,7 +84,6 @@ export class CanvasManager {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
this.workerLog = logger('worker');
|
|
||||||
|
|
||||||
this.preview = new CanvasPreview(this);
|
this.preview = new CanvasPreview(this);
|
||||||
this.stage.add(this.preview.getLayer());
|
this.stage.add(this.preview.getLayer());
|
||||||
@ -97,9 +95,9 @@ export class CanvasManager {
|
|||||||
const { type, data } = event.data;
|
const { type, data } = event.data;
|
||||||
if (type === 'log') {
|
if (type === 'log') {
|
||||||
if (data.ctx) {
|
if (data.ctx) {
|
||||||
this.workerLog[data.level](data.ctx, data.message);
|
this.log[data.level](data.ctx, data.message);
|
||||||
} else {
|
} else {
|
||||||
this.workerLog[data.level](data.message);
|
this.log[data.level](data.message);
|
||||||
}
|
}
|
||||||
} else if (type === 'extents') {
|
} else if (type === 'extents') {
|
||||||
const task = this._tasks.get(data.id);
|
const task = this._tasks.get(data.id);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
|
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
|
||||||
import {
|
import {
|
||||||
alignCoordForTool,
|
alignCoordForTool,
|
||||||
getObjectId,
|
getPrefixedId,
|
||||||
getScaledCursorPosition,
|
getScaledCursorPosition,
|
||||||
offsetCoord,
|
offsetCoord,
|
||||||
} from 'features/controlLayers/konva/util';
|
} from 'features/controlLayers/konva/util';
|
||||||
@ -216,7 +216,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await selectedEntity.adapter.renderer.setBuffer({
|
await selectedEntity.adapter.renderer.setBuffer({
|
||||||
id: getObjectId('brush_line', true),
|
id: getPrefixedId('brush_line'),
|
||||||
type: 'brush_line',
|
type: 'brush_line',
|
||||||
points: [
|
points: [
|
||||||
// The last point of the last line is already normalized to the entity's coordinates
|
// The last point of the last line is already normalized to the entity's coordinates
|
||||||
@ -234,7 +234,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
|
|||||||
selectedEntity.adapter.renderer.commitBuffer();
|
selectedEntity.adapter.renderer.commitBuffer();
|
||||||
}
|
}
|
||||||
await selectedEntity.adapter.renderer.setBuffer({
|
await selectedEntity.adapter.renderer.setBuffer({
|
||||||
id: getObjectId('brush_line', true),
|
id: getPrefixedId('brush_line'),
|
||||||
type: 'brush_line',
|
type: 'brush_line',
|
||||||
points: [alignedPoint.x, alignedPoint.y],
|
points: [alignedPoint.x, alignedPoint.y],
|
||||||
strokeWidth: toolState.brush.width,
|
strokeWidth: toolState.brush.width,
|
||||||
@ -254,7 +254,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
|
|||||||
selectedEntity.adapter.renderer.commitBuffer();
|
selectedEntity.adapter.renderer.commitBuffer();
|
||||||
}
|
}
|
||||||
await selectedEntity.adapter.renderer.setBuffer({
|
await selectedEntity.adapter.renderer.setBuffer({
|
||||||
id: getObjectId('eraser_line', true),
|
id: getPrefixedId('eraser_line'),
|
||||||
type: 'eraser_line',
|
type: 'eraser_line',
|
||||||
points: [
|
points: [
|
||||||
// The last point of the last line is already normalized to the entity's coordinates
|
// The last point of the last line is already normalized to the entity's coordinates
|
||||||
@ -271,7 +271,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
|
|||||||
selectedEntity.adapter.renderer.commitBuffer();
|
selectedEntity.adapter.renderer.commitBuffer();
|
||||||
}
|
}
|
||||||
await selectedEntity.adapter.renderer.setBuffer({
|
await selectedEntity.adapter.renderer.setBuffer({
|
||||||
id: getObjectId('eraser_line', true),
|
id: getPrefixedId('eraser_line'),
|
||||||
type: 'eraser_line',
|
type: 'eraser_line',
|
||||||
points: [alignedPoint.x, alignedPoint.y],
|
points: [alignedPoint.x, alignedPoint.y],
|
||||||
strokeWidth: toolState.eraser.width,
|
strokeWidth: toolState.eraser.width,
|
||||||
@ -286,7 +286,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
|
|||||||
selectedEntity.adapter.renderer.commitBuffer();
|
selectedEntity.adapter.renderer.commitBuffer();
|
||||||
}
|
}
|
||||||
await selectedEntity.adapter.renderer.setBuffer({
|
await selectedEntity.adapter.renderer.setBuffer({
|
||||||
id: getObjectId('rect', true),
|
id: getPrefixedId('rect'),
|
||||||
type: 'rect',
|
type: 'rect',
|
||||||
rect: { x: Math.round(normalizedPoint.x), y: Math.round(normalizedPoint.y), width: 0, height: 0 },
|
rect: { x: Math.round(normalizedPoint.x), y: Math.round(normalizedPoint.y), width: 0, height: 0 },
|
||||||
color: getCurrentFill(),
|
color: getCurrentFill(),
|
||||||
@ -375,7 +375,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
|
|||||||
const normalizedPoint = offsetCoord(pos, selectedEntity.state.position);
|
const normalizedPoint = offsetCoord(pos, selectedEntity.state.position);
|
||||||
const alignedPoint = alignCoordForTool(normalizedPoint, toolState.brush.width);
|
const alignedPoint = alignCoordForTool(normalizedPoint, toolState.brush.width);
|
||||||
await selectedEntity.adapter.renderer.setBuffer({
|
await selectedEntity.adapter.renderer.setBuffer({
|
||||||
id: getObjectId('brush_line', true),
|
id: getPrefixedId('brush_line'),
|
||||||
type: 'brush_line',
|
type: 'brush_line',
|
||||||
points: [alignedPoint.x, alignedPoint.y],
|
points: [alignedPoint.x, alignedPoint.y],
|
||||||
strokeWidth: toolState.brush.width,
|
strokeWidth: toolState.brush.width,
|
||||||
@ -412,7 +412,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
|
|||||||
const normalizedPoint = offsetCoord(pos, selectedEntity.state.position);
|
const normalizedPoint = offsetCoord(pos, selectedEntity.state.position);
|
||||||
const alignedPoint = alignCoordForTool(normalizedPoint, toolState.eraser.width);
|
const alignedPoint = alignCoordForTool(normalizedPoint, toolState.eraser.width);
|
||||||
await selectedEntity.adapter.renderer.setBuffer({
|
await selectedEntity.adapter.renderer.setBuffer({
|
||||||
id: getObjectId('eraser_line', true),
|
id: getPrefixedId('eraser_line'),
|
||||||
type: 'eraser_line',
|
type: 'eraser_line',
|
||||||
points: [alignedPoint.x, alignedPoint.y],
|
points: [alignedPoint.x, alignedPoint.y],
|
||||||
strokeWidth: toolState.eraser.width,
|
strokeWidth: toolState.eraser.width,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { CanvasObjectState, Coordinate, Rect, RgbaColor } from 'features/controlLayers/store/types';
|
import type { Coordinate, Rect, RgbaColor } from 'features/controlLayers/store/types';
|
||||||
import Konva from 'konva';
|
import Konva from 'konva';
|
||||||
import type { KonvaEventObject } from 'konva/lib/Node';
|
import type { KonvaEventObject } from 'konva/lib/Node';
|
||||||
import type { Vector2d } from 'konva/lib/types';
|
import type { Vector2d } from 'konva/lib/types';
|
||||||
@ -363,14 +363,6 @@ export function getPrefixedId(prefix: string): string {
|
|||||||
return `${prefix}:${nanoid()}`;
|
return `${prefix}:${nanoid()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getObjectId(type: CanvasObjectState['type'], isBuffer?: boolean): string {
|
|
||||||
if (isBuffer) {
|
|
||||||
return getPrefixedId(`buffer_${type}`);
|
|
||||||
} else {
|
|
||||||
return getPrefixedId(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getEmptyRect = (): Rect => {
|
export const getEmptyRect = (): Rect => {
|
||||||
return { x: 0, y: 0, width: 0, height: 0 };
|
return { x: 0, y: 0, width: 0, height: 0 };
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { CanvasControlAdapter } from 'features/controlLayers/konva/CanvasControlAdapter';
|
import type { CanvasControlAdapter } from 'features/controlLayers/konva/CanvasControlAdapter';
|
||||||
import { CanvasLayerAdapter } from 'features/controlLayers/konva/CanvasLayerAdapter';
|
import { CanvasLayerAdapter } from 'features/controlLayers/konva/CanvasLayerAdapter';
|
||||||
import { CanvasMaskAdapter } from 'features/controlLayers/konva/CanvasMaskAdapter';
|
import { CanvasMaskAdapter } from 'features/controlLayers/konva/CanvasMaskAdapter';
|
||||||
import { getObjectId } from 'features/controlLayers/konva/util';
|
import { getPrefixedId } from 'features/controlLayers/konva/util';
|
||||||
import { zModelIdentifierField } from 'features/nodes/types/common';
|
import { zModelIdentifierField } from 'features/nodes/types/common';
|
||||||
import type { AspectRatioState } from 'features/parameters/components/DocumentSize/types';
|
import type { AspectRatioState } from 'features/parameters/components/DocumentSize/types';
|
||||||
import type {
|
import type {
|
||||||
@ -803,7 +803,7 @@ export const imageDTOToImageWithDims = ({ image_name, width, height }: ImageDTO)
|
|||||||
export const imageDTOToImageObject = (imageDTO: ImageDTO, overrides?: Partial<CanvasImageState>): CanvasImageState => {
|
export const imageDTOToImageObject = (imageDTO: ImageDTO, overrides?: Partial<CanvasImageState>): CanvasImageState => {
|
||||||
const { width, height, image_name } = imageDTO;
|
const { width, height, image_name } = imageDTO;
|
||||||
return {
|
return {
|
||||||
id: getObjectId('image'),
|
id: getPrefixedId('image'),
|
||||||
type: 'image',
|
type: 'image',
|
||||||
image: {
|
image: {
|
||||||
image_name,
|
image_name,
|
||||||
|
@ -11,23 +11,21 @@ import { memo, useCallback, useState } from 'react';
|
|||||||
|
|
||||||
import { DndContextTypesafe } from './DndContextTypesafe';
|
import { DndContextTypesafe } from './DndContextTypesafe';
|
||||||
|
|
||||||
|
const log = logger('system');
|
||||||
|
|
||||||
const AppDndContext = (props: PropsWithChildren) => {
|
const AppDndContext = (props: PropsWithChildren) => {
|
||||||
const [activeDragData, setActiveDragData] = useState<TypesafeDraggableData | null>(null);
|
const [activeDragData, setActiveDragData] = useState<TypesafeDraggableData | null>(null);
|
||||||
const log = logger('images');
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const handleDragStart = useCallback(
|
const handleDragStart = useCallback((event: DragStartEvent) => {
|
||||||
(event: DragStartEvent) => {
|
|
||||||
log.trace({ dragData: parseify(event.active.data.current) }, 'Drag started');
|
log.trace({ dragData: parseify(event.active.data.current) }, 'Drag started');
|
||||||
const activeData = event.active.data.current;
|
const activeData = event.active.data.current;
|
||||||
if (!activeData) {
|
if (!activeData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setActiveDragData(activeData);
|
setActiveDragData(activeData);
|
||||||
},
|
}, []);
|
||||||
[log]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleDragEnd = useCallback(
|
const handleDragEnd = useCallback(
|
||||||
(event: DragEndEvent) => {
|
(event: DragEndEvent) => {
|
||||||
@ -39,7 +37,7 @@ const AppDndContext = (props: PropsWithChildren) => {
|
|||||||
dispatch(dndDropped({ overData, activeData: activeDragData }));
|
dispatch(dndDropped({ overData, activeData: activeDragData }));
|
||||||
setActiveDragData(null);
|
setActiveDragData(null);
|
||||||
},
|
},
|
||||||
[activeDragData, dispatch, log]
|
[activeDragData, dispatch]
|
||||||
);
|
);
|
||||||
|
|
||||||
const mouseSensor = useSensor(MouseSensor, {
|
const mouseSensor = useSensor(MouseSensor, {
|
||||||
|
@ -15,14 +15,14 @@ import {
|
|||||||
bboxWidthChanged,
|
bboxWidthChanged,
|
||||||
// caRecalled,
|
// caRecalled,
|
||||||
ipaRecalled,
|
ipaRecalled,
|
||||||
rasterLayerAllDeleted,
|
|
||||||
rasterLayerRecalled,
|
|
||||||
loraAllDeleted,
|
loraAllDeleted,
|
||||||
loraRecalled,
|
loraRecalled,
|
||||||
negativePrompt2Changed,
|
negativePrompt2Changed,
|
||||||
negativePromptChanged,
|
negativePromptChanged,
|
||||||
positivePrompt2Changed,
|
positivePrompt2Changed,
|
||||||
positivePromptChanged,
|
positivePromptChanged,
|
||||||
|
rasterLayerAllDeleted,
|
||||||
|
rasterLayerRecalled,
|
||||||
refinerModelChanged,
|
refinerModelChanged,
|
||||||
rgRecalled,
|
rgRecalled,
|
||||||
setCfgRescaleMultiplier,
|
setCfgRescaleMultiplier,
|
||||||
@ -80,6 +80,8 @@ import type {
|
|||||||
import { getImageDTO } from 'services/api/endpoints/images';
|
import { getImageDTO } from 'services/api/endpoints/images';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
const log = logger('metadata');
|
||||||
|
|
||||||
const recallPositivePrompt: MetadataRecallFunc<ParameterPositivePrompt> = (positivePrompt) => {
|
const recallPositivePrompt: MetadataRecallFunc<ParameterPositivePrompt> = (positivePrompt) => {
|
||||||
getStore().dispatch(positivePromptChanged(positivePrompt));
|
getStore().dispatch(positivePromptChanged(positivePrompt));
|
||||||
};
|
};
|
||||||
@ -351,7 +353,7 @@ const recallLayer: MetadataRecallFunc<CanvasRasterLayerState> = async (layer) =>
|
|||||||
} else if (obj.type === 'rect') {
|
} else if (obj.type === 'rect') {
|
||||||
obj.id = getRectShapeId(clone.id, uuidv4());
|
obj.id = getRectShapeId(clone.id, uuidv4());
|
||||||
} else {
|
} else {
|
||||||
logger('metadata').error(`Unknown object type ${obj.type}`);
|
log.error(`Unknown object type ${obj.type}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clone.id = getRGId(uuidv4());
|
clone.id = getRGId(uuidv4());
|
||||||
|
@ -34,6 +34,7 @@ import { isNonRefinerMainModelConfig } from 'services/api/types';
|
|||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
|
|
||||||
import { addRegions } from './addRegions';
|
import { addRegions } from './addRegions';
|
||||||
|
|
||||||
const log = logger('system');
|
const log = logger('system');
|
||||||
|
|
||||||
export const buildSD1Graph = async (state: RootState, manager: CanvasManager): Promise<Graph> => {
|
export const buildSD1Graph = async (state: RootState, manager: CanvasManager): Promise<Graph> => {
|
||||||
|
@ -33,6 +33,7 @@ import { isNonRefinerMainModelConfig } from 'services/api/types';
|
|||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
|
|
||||||
import { addRegions } from './addRegions';
|
import { addRegions } from './addRegions';
|
||||||
|
|
||||||
const log = logger('system');
|
const log = logger('system');
|
||||||
|
|
||||||
export const buildSDXLGraph = async (state: RootState, manager: CanvasManager): Promise<Graph> => {
|
export const buildSDXLGraph = async (state: RootState, manager: CanvasManager): Promise<Graph> => {
|
||||||
|
@ -25,6 +25,8 @@ import { buildFieldInputTemplate } from './buildFieldInputTemplate';
|
|||||||
import { buildFieldOutputTemplate } from './buildFieldOutputTemplate';
|
import { buildFieldOutputTemplate } from './buildFieldOutputTemplate';
|
||||||
import { isCollectionFieldType, parseFieldType } from './parseFieldType';
|
import { isCollectionFieldType, parseFieldType } from './parseFieldType';
|
||||||
|
|
||||||
|
const log = logger('system');
|
||||||
|
|
||||||
const RESERVED_INPUT_FIELD_NAMES = ['id', 'type', 'use_cache'];
|
const RESERVED_INPUT_FIELD_NAMES = ['id', 'type', 'use_cache'];
|
||||||
const RESERVED_OUTPUT_FIELD_NAMES = ['type'];
|
const RESERVED_OUTPUT_FIELD_NAMES = ['type'];
|
||||||
const RESERVED_FIELD_TYPES = ['IsIntermediate'];
|
const RESERVED_FIELD_TYPES = ['IsIntermediate'];
|
||||||
@ -85,18 +87,12 @@ export const parseSchema = (
|
|||||||
schema.properties,
|
schema.properties,
|
||||||
(inputsAccumulator: Record<string, FieldInputTemplate>, property, propertyName) => {
|
(inputsAccumulator: Record<string, FieldInputTemplate>, property, propertyName) => {
|
||||||
if (isReservedInputField(type, propertyName)) {
|
if (isReservedInputField(type, propertyName)) {
|
||||||
logger('nodes').trace(
|
log.trace({ node: type, field: propertyName, schema: parseify(property) }, 'Skipped reserved input field');
|
||||||
{ node: type, field: propertyName, schema: parseify(property) },
|
|
||||||
'Skipped reserved input field'
|
|
||||||
);
|
|
||||||
return inputsAccumulator;
|
return inputsAccumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isInvocationFieldSchema(property)) {
|
if (!isInvocationFieldSchema(property)) {
|
||||||
logger('nodes').warn(
|
log.warn({ node: type, field: propertyName, schema: parseify(property) }, 'Unhandled input property');
|
||||||
{ node: type, field: propertyName, schema: parseify(property) },
|
|
||||||
'Unhandled input property'
|
|
||||||
);
|
|
||||||
return inputsAccumulator;
|
return inputsAccumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,18 +107,12 @@ export const parseSchema = (
|
|||||||
|
|
||||||
const fieldType = fieldTypeOverride ?? originalFieldType;
|
const fieldType = fieldTypeOverride ?? originalFieldType;
|
||||||
if (!fieldType) {
|
if (!fieldType) {
|
||||||
logger('nodes').trace(
|
log.trace({ node: type, field: propertyName, schema: parseify(property) }, 'Unable to parse field type');
|
||||||
{ node: type, field: propertyName, schema: parseify(property) },
|
|
||||||
'Unable to parse field type'
|
|
||||||
);
|
|
||||||
return inputsAccumulator;
|
return inputsAccumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isReservedFieldType(fieldType.name)) {
|
if (isReservedFieldType(fieldType.name)) {
|
||||||
logger('nodes').trace(
|
log.trace({ node: type, field: propertyName, schema: parseify(property) }, 'Skipped reserved input field');
|
||||||
{ node: type, field: propertyName, schema: parseify(property) },
|
|
||||||
'Skipped reserved input field'
|
|
||||||
);
|
|
||||||
return inputsAccumulator;
|
return inputsAccumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,18 +131,18 @@ export const parseSchema = (
|
|||||||
const outputSchemaName = schema.output.$ref.split('/').pop();
|
const outputSchemaName = schema.output.$ref.split('/').pop();
|
||||||
|
|
||||||
if (!outputSchemaName) {
|
if (!outputSchemaName) {
|
||||||
logger('nodes').warn({ outputRefObject: parseify(schema.output) }, 'No output schema name found in ref object');
|
log.warn({ outputRefObject: parseify(schema.output) }, 'No output schema name found in ref object');
|
||||||
return invocationsAccumulator;
|
return invocationsAccumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
const outputSchema = openAPI.components?.schemas?.[outputSchemaName];
|
const outputSchema = openAPI.components?.schemas?.[outputSchemaName];
|
||||||
if (!outputSchema) {
|
if (!outputSchema) {
|
||||||
logger('nodes').warn({ outputSchemaName }, 'Output schema not found');
|
log.warn({ outputSchemaName }, 'Output schema not found');
|
||||||
return invocationsAccumulator;
|
return invocationsAccumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isInvocationOutputSchemaObject(outputSchema)) {
|
if (!isInvocationOutputSchemaObject(outputSchema)) {
|
||||||
logger('nodes').error({ outputSchema: parseify(outputSchema) }, 'Invalid output schema');
|
log.error({ outputSchema: parseify(outputSchema) }, 'Invalid output schema');
|
||||||
return invocationsAccumulator;
|
return invocationsAccumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,18 +152,12 @@ export const parseSchema = (
|
|||||||
outputSchema.properties,
|
outputSchema.properties,
|
||||||
(outputsAccumulator, property, propertyName) => {
|
(outputsAccumulator, property, propertyName) => {
|
||||||
if (!isAllowedOutputField(type, propertyName)) {
|
if (!isAllowedOutputField(type, propertyName)) {
|
||||||
logger('nodes').trace(
|
log.trace({ node: type, field: propertyName, schema: parseify(property) }, 'Skipped reserved output field');
|
||||||
{ node: type, field: propertyName, schema: parseify(property) },
|
|
||||||
'Skipped reserved output field'
|
|
||||||
);
|
|
||||||
return outputsAccumulator;
|
return outputsAccumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isInvocationFieldSchema(property)) {
|
if (!isInvocationFieldSchema(property)) {
|
||||||
logger('nodes').warn(
|
log.warn({ node: type, field: propertyName, schema: parseify(property) }, 'Unhandled output property');
|
||||||
{ node: type, field: propertyName, schema: parseify(property) },
|
|
||||||
'Unhandled output property'
|
|
||||||
);
|
|
||||||
return outputsAccumulator;
|
return outputsAccumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,10 +172,7 @@ export const parseSchema = (
|
|||||||
|
|
||||||
const fieldType = fieldTypeOverride ?? originalFieldType;
|
const fieldType = fieldTypeOverride ?? originalFieldType;
|
||||||
if (!fieldType) {
|
if (!fieldType) {
|
||||||
logger('nodes').trace(
|
log.trace({ node: type, field: propertyName, schema: parseify(property) }, 'Unable to parse field type');
|
||||||
{ node: type, field: propertyName, schema: parseify(property) },
|
|
||||||
'Unable to parse field type'
|
|
||||||
);
|
|
||||||
return outputsAccumulator;
|
return outputsAccumulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +223,7 @@ const getFieldType = (
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
const tKey = kind === 'input' ? 'nodes.inputFieldTypeParseError' : 'nodes.outputFieldTypeParseError';
|
const tKey = kind === 'input' ? 'nodes.inputFieldTypeParseError' : 'nodes.outputFieldTypeParseError';
|
||||||
if (e instanceof FieldParseError) {
|
if (e instanceof FieldParseError) {
|
||||||
logger('nodes').warn(
|
log.warn(
|
||||||
{
|
{
|
||||||
node: type,
|
node: type,
|
||||||
field: propertyName,
|
field: propertyName,
|
||||||
@ -255,7 +236,7 @@ const getFieldType = (
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logger('nodes').warn(
|
log.warn(
|
||||||
{
|
{
|
||||||
node: type,
|
node: type,
|
||||||
field: propertyName,
|
field: propertyName,
|
||||||
|
@ -9,6 +9,8 @@ import i18n from 'i18n';
|
|||||||
import { pick } from 'lodash-es';
|
import { pick } from 'lodash-es';
|
||||||
import { fromZodError } from 'zod-validation-error';
|
import { fromZodError } from 'zod-validation-error';
|
||||||
|
|
||||||
|
const log = logger('workflows');
|
||||||
|
|
||||||
export type BuildWorkflowArg = {
|
export type BuildWorkflowArg = {
|
||||||
nodes: NodesState['nodes'];
|
nodes: NodesState['nodes'];
|
||||||
edges: NodesState['edges'];
|
edges: NodesState['edges'];
|
||||||
@ -93,7 +95,7 @@ export const buildWorkflowWithValidation = ({ nodes, edges, workflow }: BuildWor
|
|||||||
prefix: i18n.t('nodes.unableToValidateWorkflow'),
|
prefix: i18n.t('nodes.unableToValidateWorkflow'),
|
||||||
});
|
});
|
||||||
|
|
||||||
logger('nodes').warn({ workflow: parseify(workflowToValidate) }, message);
|
log.warn({ workflow: parseify(workflowToValidate) }, message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ import { forEach } from 'lodash-es';
|
|||||||
import type { NonNullableGraph } from 'services/api/types';
|
import type { NonNullableGraph } from 'services/api/types';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
const log = logger('workflows');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a graph to a workflow. This is a best-effort conversion and may not be perfect.
|
* Converts a graph to a workflow. This is a best-effort conversion and may not be perfect.
|
||||||
* For example, if a graph references an unknown node type, that node will be skipped.
|
* For example, if a graph references an unknown node type, that node will be skipped.
|
||||||
@ -43,7 +45,7 @@ export const graphToWorkflow = (graph: NonNullableGraph, autoLayout = true): Wor
|
|||||||
|
|
||||||
// Skip missing node templates - this is a best-effort
|
// Skip missing node templates - this is a best-effort
|
||||||
if (!template) {
|
if (!template) {
|
||||||
logger('nodes').warn(`Node type ${node.type} not found in templates`);
|
log.warn(`Node type ${node.type} not found in templates`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +62,7 @@ export const graphToWorkflow = (graph: NonNullableGraph, autoLayout = true): Wor
|
|||||||
|
|
||||||
// Skip missing input templates
|
// Skip missing input templates
|
||||||
if (!inputTemplate) {
|
if (!inputTemplate) {
|
||||||
logger('nodes').warn(`Input ${key} not found in template for node type ${node.type}`);
|
log.warn(`Input ${key} not found in template for node type ${node.type}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
import { Flex } from '@invoke-ai/ui-library';
|
||||||
|
import { SettingsDeveloperLogIsEnabled } from 'features/system/components/SettingsModal/SettingsDeveloperLogIsEnabled';
|
||||||
|
import { SettingsDeveloperLogLevel } from 'features/system/components/SettingsModal/SettingsDeveloperLogLevel';
|
||||||
|
import { SettingsDeveloperLogNamespaces } from 'features/system/components/SettingsModal/SettingsDeveloperLogNamespaces';
|
||||||
|
import { memo } from 'react';
|
||||||
|
|
||||||
|
export const SettingsDeveloperContent = memo(() => {
|
||||||
|
return (
|
||||||
|
<Flex flexDir="column" gap={4}>
|
||||||
|
<SettingsDeveloperLogIsEnabled />
|
||||||
|
<SettingsDeveloperLogLevel />
|
||||||
|
<SettingsDeveloperLogNamespaces />
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
SettingsDeveloperContent.displayName = 'SettingsDeveloperContent';
|
@ -0,0 +1,29 @@
|
|||||||
|
import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { logIsEnabledChanged } from 'features/system/store/systemSlice';
|
||||||
|
import type { ChangeEvent } from 'react';
|
||||||
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
||||||
|
export const SettingsDeveloperLogIsEnabled = memo(() => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const logIsEnabled = useAppSelector((s) => s.system.logIsEnabled);
|
||||||
|
|
||||||
|
const onChangeLogIsEnabled = useCallback(
|
||||||
|
(e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
dispatch(logIsEnabledChanged(e.target.checked));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>{t('system.enableLogging')}</FormLabel>
|
||||||
|
<Switch isChecked={logIsEnabled} onChange={onChangeLogIsEnabled} />
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
SettingsDeveloperLogIsEnabled.displayName = 'SettingsDeveloperLogIsEnabled';
|
@ -0,0 +1,34 @@
|
|||||||
|
import type { ComboboxOnChange } from '@invoke-ai/ui-library';
|
||||||
|
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
|
import { isLogLevel, zLogLevel } from 'app/logging/logger';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { logLevelChanged } from 'features/system/store/systemSlice';
|
||||||
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
export const SettingsDeveloperLogLevel = memo(() => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const logLevel = useAppSelector((s) => s.system.logLevel);
|
||||||
|
const options = useMemo(() => zLogLevel.options.map((o) => ({ label: t(`system.logLevel.${o}`), value: o })), [t]);
|
||||||
|
|
||||||
|
const value = useMemo(() => options.find((o) => o.value === logLevel), [logLevel, options]);
|
||||||
|
|
||||||
|
const onChange = useCallback<ComboboxOnChange>(
|
||||||
|
(v) => {
|
||||||
|
if (!isLogLevel(v?.value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dispatch(logLevelChanged(v.value));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>{t('system.logLevel.logLevel')}</FormLabel>
|
||||||
|
<Combobox value={value} options={options} onChange={onChange} isSearchable={false} />
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
SettingsDeveloperLogLevel.displayName = 'SettingsDeveloperLogLevel';
|
@ -0,0 +1,70 @@
|
|||||||
|
import { Flex, FormControl, FormLabel, Tag, TagCloseButton, Text } from '@invoke-ai/ui-library';
|
||||||
|
import type { LogNamespace } from 'app/logging/logger';
|
||||||
|
import { zLogNamespace } from 'app/logging/logger';
|
||||||
|
import { EMPTY_ARRAY } from 'app/store/constants';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { logNamespaceToggled } from 'features/system/store/systemSlice';
|
||||||
|
import { difference } from 'lodash-es';
|
||||||
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
||||||
|
export const SettingsDeveloperLogNamespaces = memo(() => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const enabledLogNamespaces = useAppSelector((s) => {
|
||||||
|
if (s.system.logNamespaces.length === 0) {
|
||||||
|
return EMPTY_ARRAY;
|
||||||
|
} else {
|
||||||
|
return s.system.logNamespaces.toSorted();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const disabledLogNamespaces = useMemo(
|
||||||
|
() => difference(zLogNamespace.options, enabledLogNamespaces).toSorted(),
|
||||||
|
[enabledLogNamespaces]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl orientation="vertical">
|
||||||
|
<FormLabel>{t('system.logNamespaces.logNamespaces')}</FormLabel>
|
||||||
|
<Flex w="full" gap={2} flexWrap="wrap" minH="32px" borderRadius="base" borderWidth={1} p={2} alignItems="center">
|
||||||
|
{enabledLogNamespaces.map((namespace) => (
|
||||||
|
<LogLevelTag key={`enabled-${namespace}`} namespace={namespace} isEnabled={true} />
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
<Flex gap={2} flexWrap="wrap">
|
||||||
|
{disabledLogNamespaces.map((namespace) => (
|
||||||
|
<LogLevelTag key={`disabled-${namespace}`} namespace={namespace} isEnabled={false} />
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
SettingsDeveloperLogNamespaces.displayName = 'SettingsDeveloperLogNamespaces';
|
||||||
|
|
||||||
|
const LogLevelTag = ({ namespace, isEnabled }: { namespace: LogNamespace; isEnabled: boolean }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const onClick = useCallback(() => {
|
||||||
|
dispatch(logNamespaceToggled(namespace));
|
||||||
|
}, [dispatch, namespace]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tag
|
||||||
|
h="min-content"
|
||||||
|
borderRadius="base"
|
||||||
|
onClick={onClick}
|
||||||
|
colorScheme={isEnabled ? 'invokeBlue' : 'base'}
|
||||||
|
userSelect="none"
|
||||||
|
role="button"
|
||||||
|
size="md"
|
||||||
|
color="base.900"
|
||||||
|
bg={isEnabled ? 'invokeBlue.300' : 'base.300'}
|
||||||
|
>
|
||||||
|
<Text fontSize="sm" fontWeight="semibold">
|
||||||
|
{t(`system.logNamespaces.${namespace}`)}
|
||||||
|
</Text>
|
||||||
|
{isEnabled && <TagCloseButton />}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
};
|
@ -2,30 +2,30 @@ import type { ComboboxOnChange } from '@invoke-ai/ui-library';
|
|||||||
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
import { isLogLevel, zLogLevel } from 'app/logging/logger';
|
import { isLogLevel, zLogLevel } from 'app/logging/logger';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { consoleLogLevelChanged } from 'features/system/store/systemSlice';
|
import { logLevelChanged } from 'features/system/store/systemSlice';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
export const SettingsLogLevelSelect = memo(() => {
|
export const SettingsLogLevelSelect = memo(() => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const consoleLogLevel = useAppSelector((s) => s.system.consoleLogLevel);
|
const logLevel = useAppSelector((s) => s.system.logLevel);
|
||||||
const shouldLogToConsole = useAppSelector((s) => s.system.shouldLogToConsole);
|
const logIsEnabled = useAppSelector((s) => s.system.logIsEnabled);
|
||||||
const options = useMemo(() => zLogLevel.options.map((o) => ({ label: o, value: o })), []);
|
const options = useMemo(() => zLogLevel.options.map((o) => ({ label: o, value: o })), []);
|
||||||
|
|
||||||
const value = useMemo(() => options.find((o) => o.value === consoleLogLevel), [consoleLogLevel, options]);
|
const value = useMemo(() => options.find((o) => o.value === logLevel), [logLevel, options]);
|
||||||
|
|
||||||
const onChange = useCallback<ComboboxOnChange>(
|
const onChange = useCallback<ComboboxOnChange>(
|
||||||
(v) => {
|
(v) => {
|
||||||
if (!isLogLevel(v?.value)) {
|
if (!isLogLevel(v?.value)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch(consoleLogLevelChanged(v.value));
|
dispatch(logLevelChanged(v.value));
|
||||||
},
|
},
|
||||||
[dispatch]
|
[dispatch]
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<FormControl isDisabled={!shouldLogToConsole}>
|
<FormControl isDisabled={!logIsEnabled}>
|
||||||
<FormLabel>{t('common.loglevel')}</FormLabel>
|
<FormLabel>{t('common.loglevel')}</FormLabel>
|
||||||
<Combobox value={value} options={options} onChange={onChange} />
|
<Combobox value={value} options={options} onChange={onChange} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -20,14 +20,16 @@ import { InformationalPopover } from 'common/components/InformationalPopover/Inf
|
|||||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||||
import { useClearStorage } from 'common/hooks/useClearStorage';
|
import { useClearStorage } from 'common/hooks/useClearStorage';
|
||||||
import { shouldUseCpuNoiseChanged } from 'features/controlLayers/store/canvasV2Slice';
|
import { shouldUseCpuNoiseChanged } from 'features/controlLayers/store/canvasV2Slice';
|
||||||
|
import { SettingsDeveloperLogIsEnabled } from 'features/system/components/SettingsModal/SettingsDeveloperLogIsEnabled';
|
||||||
|
import { SettingsDeveloperLogLevel } from 'features/system/components/SettingsModal/SettingsDeveloperLogLevel';
|
||||||
|
import { SettingsDeveloperLogNamespaces } from 'features/system/components/SettingsModal/SettingsDeveloperLogNamespaces';
|
||||||
import { useClearIntermediates } from 'features/system/components/SettingsModal/useClearIntermediates';
|
import { useClearIntermediates } from 'features/system/components/SettingsModal/useClearIntermediates';
|
||||||
import { StickyScrollable } from 'features/system/components/StickyScrollable';
|
import { StickyScrollable } from 'features/system/components/StickyScrollable';
|
||||||
import {
|
import {
|
||||||
setEnableImageDebugging,
|
logIsEnabledChanged,
|
||||||
setShouldConfirmOnDelete,
|
setShouldConfirmOnDelete,
|
||||||
setShouldEnableInformationalPopovers,
|
setShouldEnableInformationalPopovers,
|
||||||
shouldAntialiasProgressImageChanged,
|
shouldAntialiasProgressImageChanged,
|
||||||
shouldLogToConsoleChanged,
|
|
||||||
shouldUseNSFWCheckerChanged,
|
shouldUseNSFWCheckerChanged,
|
||||||
shouldUseWatermarkerChanged,
|
shouldUseWatermarkerChanged,
|
||||||
} from 'features/system/store/systemSlice';
|
} from 'features/system/store/systemSlice';
|
||||||
@ -38,7 +40,6 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { useGetAppConfigQuery } from 'services/api/endpoints/appInfo';
|
import { useGetAppConfigQuery } from 'services/api/endpoints/appInfo';
|
||||||
|
|
||||||
import { SettingsLanguageSelect } from './SettingsLanguageSelect';
|
import { SettingsLanguageSelect } from './SettingsLanguageSelect';
|
||||||
import { SettingsLogLevelSelect } from './SettingsLogLevelSelect';
|
|
||||||
|
|
||||||
type ConfigOptions = {
|
type ConfigOptions = {
|
||||||
shouldShowDeveloperSettings?: boolean;
|
shouldShowDeveloperSettings?: boolean;
|
||||||
@ -65,7 +66,7 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!shouldShowDeveloperSettings) {
|
if (!shouldShowDeveloperSettings) {
|
||||||
dispatch(shouldLogToConsoleChanged(false));
|
dispatch(logIsEnabledChanged(false));
|
||||||
}
|
}
|
||||||
}, [shouldShowDeveloperSettings, dispatch]);
|
}, [shouldShowDeveloperSettings, dispatch]);
|
||||||
|
|
||||||
@ -90,9 +91,7 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
|||||||
|
|
||||||
const shouldUseCpuNoise = useAppSelector((s) => s.canvasV2.params.shouldUseCpuNoise);
|
const shouldUseCpuNoise = useAppSelector((s) => s.canvasV2.params.shouldUseCpuNoise);
|
||||||
const shouldConfirmOnDelete = useAppSelector((s) => s.system.shouldConfirmOnDelete);
|
const shouldConfirmOnDelete = useAppSelector((s) => s.system.shouldConfirmOnDelete);
|
||||||
const enableImageDebugging = useAppSelector((s) => s.system.enableImageDebugging);
|
|
||||||
const shouldShowProgressInViewer = useAppSelector((s) => s.ui.shouldShowProgressInViewer);
|
const shouldShowProgressInViewer = useAppSelector((s) => s.ui.shouldShowProgressInViewer);
|
||||||
const shouldLogToConsole = useAppSelector((s) => s.system.shouldLogToConsole);
|
|
||||||
const shouldAntialiasProgressImage = useAppSelector((s) => s.system.shouldAntialiasProgressImage);
|
const shouldAntialiasProgressImage = useAppSelector((s) => s.system.shouldAntialiasProgressImage);
|
||||||
const shouldUseNSFWChecker = useAppSelector((s) => s.system.shouldUseNSFWChecker);
|
const shouldUseNSFWChecker = useAppSelector((s) => s.system.shouldUseNSFWChecker);
|
||||||
const shouldUseWatermarker = useAppSelector((s) => s.system.shouldUseWatermarker);
|
const shouldUseWatermarker = useAppSelector((s) => s.system.shouldUseWatermarker);
|
||||||
@ -120,13 +119,6 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
|||||||
}
|
}
|
||||||
}, [countdown]);
|
}, [countdown]);
|
||||||
|
|
||||||
const handleLogToConsoleChanged = useCallback(
|
|
||||||
(e: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
dispatch(shouldLogToConsoleChanged(e.target.checked));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleChangeShouldConfirmOnDelete = useCallback(
|
const handleChangeShouldConfirmOnDelete = useCallback(
|
||||||
(e: ChangeEvent<HTMLInputElement>) => {
|
(e: ChangeEvent<HTMLInputElement>) => {
|
||||||
dispatch(setShouldConfirmOnDelete(e.target.checked));
|
dispatch(setShouldConfirmOnDelete(e.target.checked));
|
||||||
@ -163,12 +155,6 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
|||||||
},
|
},
|
||||||
[dispatch]
|
[dispatch]
|
||||||
);
|
);
|
||||||
const handleChangeEnableImageDebugging = useCallback(
|
|
||||||
(e: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
dispatch(setEnableImageDebugging(e.target.checked));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
const handleChangeShouldUseCpuNoise = useCallback(
|
const handleChangeShouldUseCpuNoise = useCallback(
|
||||||
(e: ChangeEvent<HTMLInputElement>) => {
|
(e: ChangeEvent<HTMLInputElement>) => {
|
||||||
dispatch(shouldUseCpuNoiseChanged(e.target.checked));
|
dispatch(shouldUseCpuNoiseChanged(e.target.checked));
|
||||||
@ -242,15 +228,9 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
|||||||
|
|
||||||
{shouldShowDeveloperSettings && (
|
{shouldShowDeveloperSettings && (
|
||||||
<StickyScrollable title={t('settings.developer')}>
|
<StickyScrollable title={t('settings.developer')}>
|
||||||
<FormControl>
|
<SettingsDeveloperLogIsEnabled />
|
||||||
<FormLabel>{t('settings.shouldLogToConsole')}</FormLabel>
|
<SettingsDeveloperLogLevel />
|
||||||
<Switch isChecked={shouldLogToConsole} onChange={handleLogToConsoleChanged} />
|
<SettingsDeveloperLogNamespaces />
|
||||||
</FormControl>
|
|
||||||
<SettingsLogLevelSelect />
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel>{t('settings.enableImageDebugging')}</FormLabel>
|
|
||||||
<Switch isChecked={enableImageDebugging} onChange={handleChangeEnableImageDebugging} />
|
|
||||||
</FormControl>
|
|
||||||
</StickyScrollable>
|
</StickyScrollable>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
import type { LogNamespace } from 'app/logging/logger';
|
||||||
|
import { zLogNamespace } from 'app/logging/logger';
|
||||||
import type { PersistConfig, RootState } from 'app/store/store';
|
import type { PersistConfig, RootState } from 'app/store/store';
|
||||||
import type { LogLevelName } from 'roarr';
|
import { uniq } from 'lodash-es';
|
||||||
|
|
||||||
import type { Language, SystemState } from './types';
|
import type { Language, SystemState } from './types';
|
||||||
|
|
||||||
const initialSystemState: SystemState = {
|
const initialSystemState: SystemState = {
|
||||||
_version: 1,
|
_version: 1,
|
||||||
shouldConfirmOnDelete: true,
|
shouldConfirmOnDelete: true,
|
||||||
enableImageDebugging: false,
|
|
||||||
shouldAntialiasProgressImage: false,
|
shouldAntialiasProgressImage: false,
|
||||||
consoleLogLevel: 'debug',
|
|
||||||
shouldLogToConsole: true,
|
|
||||||
language: 'en',
|
language: 'en',
|
||||||
shouldUseNSFWChecker: false,
|
shouldUseNSFWChecker: false,
|
||||||
shouldUseWatermarker: false,
|
shouldUseWatermarker: false,
|
||||||
shouldEnableInformationalPopovers: true,
|
shouldEnableInformationalPopovers: true,
|
||||||
|
logIsEnabled: true,
|
||||||
|
logLevel: 'debug',
|
||||||
|
logNamespaces: [...zLogNamespace.options],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const systemSlice = createSlice({
|
export const systemSlice = createSlice({
|
||||||
@ -25,14 +27,18 @@ export const systemSlice = createSlice({
|
|||||||
setShouldConfirmOnDelete: (state, action: PayloadAction<boolean>) => {
|
setShouldConfirmOnDelete: (state, action: PayloadAction<boolean>) => {
|
||||||
state.shouldConfirmOnDelete = action.payload;
|
state.shouldConfirmOnDelete = action.payload;
|
||||||
},
|
},
|
||||||
setEnableImageDebugging: (state, action: PayloadAction<boolean>) => {
|
logIsEnabledChanged: (state, action: PayloadAction<SystemState['logIsEnabled']>) => {
|
||||||
state.enableImageDebugging = action.payload;
|
state.logIsEnabled = action.payload;
|
||||||
},
|
},
|
||||||
consoleLogLevelChanged: (state, action: PayloadAction<LogLevelName>) => {
|
logLevelChanged: (state, action: PayloadAction<SystemState['logLevel']>) => {
|
||||||
state.consoleLogLevel = action.payload;
|
state.logLevel = action.payload;
|
||||||
},
|
},
|
||||||
shouldLogToConsoleChanged: (state, action: PayloadAction<boolean>) => {
|
logNamespaceToggled: (state, action: PayloadAction<LogNamespace>) => {
|
||||||
state.shouldLogToConsole = action.payload;
|
if (state.logNamespaces.includes(action.payload)) {
|
||||||
|
state.logNamespaces = uniq(state.logNamespaces.filter((n) => n !== action.payload));
|
||||||
|
} else {
|
||||||
|
state.logNamespaces = uniq([...state.logNamespaces, action.payload]);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
shouldAntialiasProgressImageChanged: (state, action: PayloadAction<boolean>) => {
|
shouldAntialiasProgressImageChanged: (state, action: PayloadAction<boolean>) => {
|
||||||
state.shouldAntialiasProgressImage = action.payload;
|
state.shouldAntialiasProgressImage = action.payload;
|
||||||
@ -54,9 +60,9 @@ export const systemSlice = createSlice({
|
|||||||
|
|
||||||
export const {
|
export const {
|
||||||
setShouldConfirmOnDelete,
|
setShouldConfirmOnDelete,
|
||||||
setEnableImageDebugging,
|
logIsEnabledChanged,
|
||||||
consoleLogLevelChanged,
|
logLevelChanged,
|
||||||
shouldLogToConsoleChanged,
|
logNamespaceToggled,
|
||||||
shouldAntialiasProgressImageChanged,
|
shouldAntialiasProgressImageChanged,
|
||||||
languageChanged,
|
languageChanged,
|
||||||
shouldUseNSFWCheckerChanged,
|
shouldUseNSFWCheckerChanged,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { LogLevel } from 'app/logging/logger';
|
import type { LogLevel, LogNamespace } from 'app/logging/logger';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
const zLanguage = z.enum([
|
const zLanguage = z.enum([
|
||||||
@ -31,12 +31,12 @@ export const isLanguage = (v: unknown): v is Language => zLanguage.safeParse(v).
|
|||||||
export interface SystemState {
|
export interface SystemState {
|
||||||
_version: 1;
|
_version: 1;
|
||||||
shouldConfirmOnDelete: boolean;
|
shouldConfirmOnDelete: boolean;
|
||||||
enableImageDebugging: boolean;
|
|
||||||
consoleLogLevel: LogLevel;
|
|
||||||
shouldLogToConsole: boolean;
|
|
||||||
shouldAntialiasProgressImage: boolean;
|
shouldAntialiasProgressImage: boolean;
|
||||||
language: Language;
|
language: Language;
|
||||||
shouldUseNSFWChecker: boolean;
|
shouldUseNSFWChecker: boolean;
|
||||||
shouldUseWatermarker: boolean;
|
shouldUseWatermarker: boolean;
|
||||||
shouldEnableInformationalPopovers: boolean;
|
shouldEnableInformationalPopovers: boolean;
|
||||||
|
logIsEnabled: boolean;
|
||||||
|
logLevel: LogLevel;
|
||||||
|
logNamespaces: LogNamespace[];
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import type { Socket } from 'socket.io-client';
|
|||||||
|
|
||||||
export const socketConnected = createAction('socket/connected');
|
export const socketConnected = createAction('socket/connected');
|
||||||
|
|
||||||
const log = logger('socketio');
|
const log = logger('events');
|
||||||
|
|
||||||
type SetEventListenersArg = {
|
type SetEventListenersArg = {
|
||||||
socket: Socket<ServerToClientEvents, ClientToServerEvents>;
|
socket: Socket<ServerToClientEvents, ClientToServerEvents>;
|
||||||
|
Loading…
Reference in New Issue
Block a user