Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions invokeai/frontend/web/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ patches/
stats.html
index.html
.yarn/
.yalc/
*.scss
src/services/api/
src/services/fixtures/*
docs/
static/
src/theme/css/overlayscrollbars.css
1 change: 1 addition & 0 deletions invokeai/frontend/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"@mantine/core": "^6.0.14",
"@mantine/form": "^6.0.15",
"@mantine/hooks": "^6.0.14",
"@nanostores/react": "^0.7.1",
"@reduxjs/toolkit": "^1.9.5",
"@roarr/browser-log-writer": "^1.1.5",
"chakra-ui-contextmenu": "^1.0.5",
Expand Down
2 changes: 1 addition & 1 deletion invokeai/frontend/web/scripts/typegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ async function main() {
);
const types = await openapiTS(OPENAPI_URL, {
exportType: true,
transform: (schemaObject, metadata) => {
transform: (schemaObject) => {
if ('format' in schemaObject && schemaObject.format === 'binary') {
return schemaObject.nullable ? 'Blob | null' : 'Blob';
}
Expand Down
12 changes: 7 additions & 5 deletions invokeai/frontend/web/src/app/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import FloatingParametersPanelButtons from 'features/ui/components/FloatingParam
import InvokeTabs from 'features/ui/components/InvokeTabs';
import ParametersDrawer from 'features/ui/components/ParametersDrawer';
import i18n from 'i18n';
import { size } from 'lodash-es';
import { ReactNode, memo, useEffect } from 'react';
import UpdateImageBoardModal from '../../features/gallery/components/Boards/UpdateImageBoardModal';
import GlobalHotkeys from './GlobalHotkeys';
Expand All @@ -29,18 +30,19 @@ interface Props {
const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => {
const language = useAppSelector(languageSelector);

const log = useLogger();

const logger = useLogger();
const dispatch = useAppDispatch();

useEffect(() => {
i18n.changeLanguage(language);
}, [language]);

useEffect(() => {
log.info({ namespace: 'App', data: config }, 'Received config');
dispatch(configChanged(config));
}, [dispatch, config, log]);
if (size(config)) {
logger.info({ namespace: 'App', config }, 'Received config');
dispatch(configChanged(config));
}
}, [dispatch, config, logger]);

useEffect(() => {
dispatch(appStarted());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const STYLES: ChakraProps['sx'] = {

const DragPreview = (props: OverlayDragImageProps) => {
if (!props.dragData) {
return;
return null;
}

if (props.dragData.payloadType === 'IMAGE_DTO') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ const ImageDndContext = (props: ImageDndContextProps) => {
const handleDragEnd = useCallback(
(event: DragEndEvent) => {
console.log('dragEnd', event.active.data.current);
const activeData = event.active.data.current;
const overData = event.over?.data.current;
if (!activeDragData || !overData) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
useDraggable as useOriginalDraggable,
useDroppable as useOriginalDroppable,
} from '@dnd-kit/core';
import { BoardId } from 'features/gallery/store/gallerySlice';
import { BoardId } from 'features/gallery/store/types';
import { ImageDTO } from 'services/api/types';

type BaseDropData = {
Expand Down
22 changes: 2 additions & 20 deletions invokeai/frontend/web/src/app/components/Toaster.ts
Original file line number Diff line number Diff line change
@@ -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 { toastQueueSelector } from 'features/system/store/systemSelectors';
import { addToast, clearToastQueue } from 'features/system/store/systemSlice';
import { MakeToastArg, makeToast } from 'features/system/util/makeToast';
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.
* @returns null
Expand Down
64 changes: 0 additions & 64 deletions invokeai/frontend/web/src/app/constants.ts
Original file line number Diff line number Diff line change
@@ -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_MAX = 2147483647;

export const NODE_MIN_WIDTH = 250;
46 changes: 46 additions & 0 deletions invokeai/frontend/web/src/app/logging/logger.ts
Original file line number Diff line number Diff line change
@@ -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,
};
57 changes: 13 additions & 44 deletions invokeai/frontend/web/src/app/logging/useLogger.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,19 @@
import { useStore } from '@nanostores/react';
import { createSelector } from '@reduxjs/toolkit';
import { createLogWriter } from '@roarr/browser-log-writer';
import { useAppSelector } from 'app/store/storeHooks';
import { systemSelector } from 'features/system/store/systemSelectors';
import { isEqual } from 'lodash-es';
import { useEffect } from 'react';
import { LogLevelName, ROARR, Roarr } from 'roarr';
import { createLogWriter } from '@roarr/browser-log-writer';

// 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];
import { ROARR, Roarr } from 'roarr';
import { $logger, BASE_CONTEXT, LOG_LEVEL_MAP } from './logger';

const selector = createSelector(
systemSelector,
(system) => {
const { app_version, consoleLogLevel, shouldLogToConsole } = system;
const { consoleLogLevel, shouldLogToConsole } = system;

return {
version: app_version,
consoleLogLevel,
shouldLogToConsole,
};
Expand All @@ -55,8 +26,7 @@ const selector = createSelector(
);

export const useLogger = () => {
const { version, consoleLogLevel, shouldLogToConsole } =
useAppSelector(selector);
const { consoleLogLevel, shouldLogToConsole } = useAppSelector(selector);

// The provided Roarr browser log writer uses localStorage to config logging to console
useEffect(() => {
Expand All @@ -78,17 +48,16 @@ export const useLogger = () => {

// Update the module-scoped logger context as needed
useEffect(() => {
// TODO: type this properly
//eslint-disable-next-line @typescript-eslint/no-explicit-any
const newContext: Record<string, any> = {
...baseContext,
...BASE_CONTEXT,
};

if (version) {
newContext.version = version;
}
$logger.set(Roarr.child(newContext));
}, []);

log = Roarr.child(newContext);
}, [version]);
const logger = useStore($logger);

// Use the logger within components - no different than just importing it directly
return log;
return logger;
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { defaultsDeep } from 'lodash-es';
import { UnserializeFunction } from 'redux-remember';

const initialStates: {
[key: string]: any;
[key: string]: object; // TODO: type this properly
} = {
canvas: initialCanvasState,
gallery: initialGalleryState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import {

import type { AppDispatch, RootState } from '../../store';
import { addCommitStagingAreaImageListener } from './listeners/addCommitStagingAreaImageListener';
import { addFirstListImagesListener } from './listeners/addFirstListImagesListener.ts';
import { addAppConfigReceivedListener } from './listeners/appConfigReceived';
import { addAppStartedListener } from './listeners/appStarted';
import { addBoardIdSelectedListener } from './listeners/boardIdSelected';
import { addDeleteBoardAndImagesFulfilledListener } from './listeners/boardAndImagesDeleted';
import { addBoardIdSelectedListener } from './listeners/boardIdSelected';
import { addCanvasCopiedToClipboardListener } from './listeners/canvasCopiedToClipboard';
import { addCanvasDownloadedAsImageListener } from './listeners/canvasDownloadedAsImage';
import { addCanvasMergedListener } from './listeners/canvasMerged';
Expand All @@ -34,10 +35,6 @@ import {
addImageRemovedFromBoardRejectedListener,
} from './listeners/imageRemovedFromBoard';
import { addImageToDeleteSelectedListener } from './listeners/imageToDeleteSelected';
import {
addImageUpdatedFulfilledListener,
addImageUpdatedRejectedListener,
} from './listeners/imageUpdated';
import {
addImageUploadedFulfilledListener,
addImageUploadedRejectedListener,
Expand Down Expand Up @@ -69,17 +66,15 @@ import { addGraphExecutionStateCompleteEventListener as addGraphExecutionStateCo
import { addInvocationCompleteEventListener as addInvocationCompleteListener } from './listeners/socketio/socketInvocationComplete';
import { addInvocationErrorEventListener as addInvocationErrorListener } from './listeners/socketio/socketInvocationError';
import { addInvocationStartedEventListener as addInvocationStartedListener } from './listeners/socketio/socketInvocationStarted';
import { addModelLoadEventListener } from './listeners/socketio/socketModelLoad';
import { addSocketSubscribedEventListener as addSocketSubscribedListener } from './listeners/socketio/socketSubscribed';
import { addSocketUnsubscribedEventListener as addSocketUnsubscribedListener } from './listeners/socketio/socketUnsubscribed';
import { addStagingAreaImageSavedListener } from './listeners/stagingAreaImageSaved';
import { addUpscaleRequestedListener } from './listeners/upscaleRequested';
import { addUserInvokedCanvasListener } from './listeners/userInvokedCanvas';
import { addUserInvokedImageToImageListener } from './listeners/userInvokedImageToImage';
import { addUserInvokedNodesListener } from './listeners/userInvokedNodes';
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();

Expand Down Expand Up @@ -109,10 +104,6 @@ export type AppListenerEffect = ListenerEffect<
addImageUploadedFulfilledListener();
addImageUploadedRejectedListener();

// Image updated
addImageUpdatedFulfilledListener();
addImageUpdatedRejectedListener();

// Image selected
addInitialImageSelectedListener();

Expand Down Expand Up @@ -161,8 +152,7 @@ addSocketConnectedListener();
addSocketDisconnectedListener();
addSocketSubscribedListener();
addSocketUnsubscribedListener();
addModelLoadStartedEventListener();
addModelLoadCompletedEventListener();
addModelLoadEventListener();

// Session Created
addSessionCreatedPendingListener();
Expand Down
Loading