feat(ui): remove Console and redux logging state

This commit is contained in:
psychedelicious 2023-04-29 17:22:03 +10:00
parent bffdede0fa
commit 6d6b986a66
5 changed files with 1 additions and 267 deletions

View File

@ -1,5 +1,4 @@
import ImageUploader from 'common/components/ImageUploader';
import Console from 'features/system/components/Console';
import ProgressBar from 'features/system/components/ProgressBar';
import SiteHeader from 'features/system/components/SiteHeader';
import InvokeTabs from 'features/ui/components/InvokeTabs';
@ -121,9 +120,6 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => {
<Portal>
<FloatingGalleryButton />
</Portal>
<Portal>
<Console />
</Portal>
</Grid>
);
};

View File

@ -12,7 +12,6 @@ import {
removeImage,
} from 'features/gallery/store/gallerySlice';
import {
addLogEntry,
generationRequested,
modelChangeRequested,
modelConvertRequested,

View File

@ -6,7 +6,6 @@ import { v4 as uuidv4 } from 'uuid';
import * as InvokeAI from 'app/types/invokeai';
import {
addLogEntry,
addToast,
errorOccurred,
processingCanceled,

View File

@ -1,197 +0,0 @@
import { Flex, Text, Tooltip } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIIconButton from 'common/components/IAIIconButton';
import {
errorSeen,
setShouldShowLogViewer,
SystemState,
} from 'features/system/store/systemSlice';
import { isEqual } from 'lodash-es';
import { Resizable } from 're-resizable';
import { memo, useLayoutEffect, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
import { FaAngleDoubleDown, FaCode, FaMinus } from 'react-icons/fa';
import { systemSelector } from '../store/systemSelectors';
const logSelector = createSelector(
systemSelector,
(system: SystemState) => system.log,
{
memoizeOptions: {
// We don't need a deep equality check for this selector.
resultEqualityCheck: (a, b) => a.length === b.length,
},
}
);
const consoleSelector = createSelector(
systemSelector,
(system: SystemState) => {
return {
shouldShowLogViewer: system.shouldShowLogViewer,
hasError: system.hasError,
wasErrorSeen: system.wasErrorSeen,
};
},
{
memoizeOptions: {
resultEqualityCheck: isEqual,
},
}
);
/**
* Basic log viewer, floats on bottom of page.
*/
const Console = () => {
const dispatch = useAppDispatch();
const { t } = useTranslation();
const log = useAppSelector(logSelector);
const { shouldShowLogViewer, hasError, wasErrorSeen } =
useAppSelector(consoleSelector);
// Rudimentary autoscroll
const [shouldAutoscroll, setShouldAutoscroll] = useState<boolean>(true);
const viewerRef = useRef<HTMLDivElement>(null);
/**
* If autoscroll is on, scroll to the bottom when:
* - log updates
* - viewer is toggled
*
* Also scroll to the bottom whenever autoscroll is turned on.
*/
useLayoutEffect(() => {
if (viewerRef.current !== null && shouldAutoscroll) {
viewerRef.current.scrollTop = viewerRef.current.scrollHeight;
}
}, [shouldAutoscroll, log, shouldShowLogViewer]);
const handleClickLogViewerToggle = () => {
dispatch(errorSeen());
dispatch(setShouldShowLogViewer(!shouldShowLogViewer));
};
useHotkeys(
'`',
() => {
dispatch(setShouldShowLogViewer(!shouldShowLogViewer));
},
[shouldShowLogViewer]
);
useHotkeys('esc', () => {
dispatch(setShouldShowLogViewer(false));
});
const handleOnScroll = () => {
if (!viewerRef.current) return;
if (
shouldAutoscroll &&
viewerRef.current.scrollTop <
viewerRef.current.scrollHeight - viewerRef.current.clientHeight
) {
setShouldAutoscroll(false);
}
};
return (
<>
{shouldShowLogViewer && (
<Resizable
defaultSize={{
width: '100%',
height: 200,
}}
style={{
display: 'flex',
position: 'fixed',
insetInlineStart: 0,
bottom: 0,
zIndex: 1,
}}
maxHeight="90vh"
>
<Flex
sx={{
flexDirection: 'column',
width: '100vw',
overflow: 'auto',
direction: 'column',
fontFamily: 'monospace',
pt: 0,
pr: 4,
pb: 4,
pl: 12,
borderTopWidth: 5,
bg: 'base.850',
borderColor: 'base.700',
zIndex: 2,
}}
ref={viewerRef}
onScroll={handleOnScroll}
>
{log.map((entry, i) => {
const { timestamp, message, level } = entry;
const colorScheme = level === 'info' ? 'base' : level;
return (
<Flex
key={i}
sx={{
gap: 2,
color: `${colorScheme}.300`,
}}
>
<Text fontWeight="600">{timestamp}:</Text>
<Text wordBreak="break-all">{message}</Text>
</Flex>
);
})}
</Flex>
</Resizable>
)}
{shouldShowLogViewer && (
<Tooltip
hasArrow
label={shouldAutoscroll ? 'Autoscroll On' : 'Autoscroll Off'}
>
<IAIIconButton
size="sm"
aria-label={t('accessibility.toggleAutoscroll')}
icon={<FaAngleDoubleDown />}
onClick={() => setShouldAutoscroll(!shouldAutoscroll)}
isChecked={shouldAutoscroll}
sx={{
position: 'fixed',
insetInlineStart: 2,
bottom: 12,
zIndex: 1,
}}
/>
</Tooltip>
)}
<Tooltip
hasArrow
label={shouldShowLogViewer ? 'Hide Console' : 'Show Console'}
>
<IAIIconButton
size="sm"
aria-label={t('accessibility.toggleLogViewer')}
icon={shouldShowLogViewer ? <FaMinus /> : <FaCode />}
onClick={handleClickLogViewerToggle}
sx={{
position: 'fixed',
insetInlineStart: 2,
bottom: 2,
zIndex: 1,
}}
colorScheme={hasError || !wasErrorSeen ? 'error' : 'base'}
/>
</Tooltip>
</>
);
};
export default memo(Console);

View File

@ -14,7 +14,6 @@ import {
} from 'services/events/actions';
import i18n from 'i18n';
import { isImageOutput } from 'services/types/guards';
import { ProgressImage } from 'services/events/types';
import { initialImageSelected } from 'features/parameters/store/generationSlice';
import { makeToast } from '../hooks/useToastWatcher';
@ -22,7 +21,7 @@ import { sessionCanceled, sessionInvoked } from 'services/thunks/session';
import { receivedModels } from 'services/thunks/model';
import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice';
import { LogLevelName } from 'roarr';
import { InvokeLogLevel, VALID_LOG_LEVELS } from 'app/logging/useLogger';
import { InvokeLogLevel } from 'app/logging/useLogger';
export type LogLevel = 'info' | 'warning' | 'error';
@ -44,7 +43,6 @@ export interface SystemState
extends InvokeAI.SystemStatus,
InvokeAI.SystemConfig {
shouldDisplayInProgressType: InProgressImageType;
log: Array<LogEntry>;
shouldShowLogViewer: boolean;
isGFPGANAvailable: boolean;
isESRGANAvailable: boolean;
@ -108,7 +106,6 @@ export interface SystemState
const initialSystemState: SystemState = {
isConnected: false,
isProcessing: false,
log: [],
shouldShowLogViewer: false,
shouldDisplayInProgressType: 'latents',
shouldDisplayGuides: true,
@ -150,9 +147,6 @@ const initialSystemState: SystemState = {
cancelType: 'immediate',
isCancelScheduled: false,
subscribedNodeIds: [],
// shouldTransformUrls: false,
// disabledTabs: [],
// disabledFeatures: [],
wereModelsReceived: false,
wasSchemaParsed: false,
consoleLogLevel: 'info',
@ -196,25 +190,6 @@ export const systemSlice = createSlice({
? i18n.t('common.statusConnected')
: i18n.t('common.statusDisconnected');
},
addLogEntry: (
state,
action: PayloadAction<{
timestamp: string;
message: string;
level?: LogLevel;
}>
) => {
const { timestamp, message, level } = action.payload;
const logLevel = level || 'info';
const entry: LogEntry = {
timestamp,
message,
level: logLevel,
};
state.log.push(entry);
},
setShouldShowLogViewer: (state, action: PayloadAction<boolean>) => {
state.shouldShowLogViewer = action.payload;
},
@ -380,11 +355,6 @@ export const systemSlice = createSlice({
state.isConnected = true;
state.currentStatus = i18n.t('common.statusConnected');
state.log.push({
timestamp,
message: `Connected to server`,
level: 'error',
});
});
/**
@ -395,11 +365,6 @@ export const systemSlice = createSlice({
state.isConnected = false;
state.currentStatus = i18n.t('common.statusDisconnected');
state.log.push({
timestamp,
message: `Disconnected from server`,
level: 'error',
});
});
/**
@ -442,15 +407,6 @@ export const systemSlice = createSlice({
state.totalSteps = 0;
state.progressImage = null;
state.currentStatus = i18n.t('common.statusProcessingComplete');
// TODO: handle logging for other invocation types
if (isImageOutput(data.result)) {
state.log.push({
timestamp,
message: `Generated: ${data.result.image.image_name}`,
level: 'info',
});
}
});
/**
@ -459,12 +415,6 @@ export const systemSlice = createSlice({
builder.addCase(invocationError, (state, action) => {
const { data, timestamp } = action.payload;
state.log.push({
timestamp,
message: `Server error: ${data.error}`,
level: 'error',
});
state.wasErrorSeen = true;
state.progressImage = null;
state.isProcessing = false;
@ -472,12 +422,6 @@ export const systemSlice = createSlice({
state.toastQueue.push(
makeToast({ title: i18n.t('toast.serverError'), status: 'error' })
);
state.log.push({
timestamp,
message: `Server error: ${data.error}`,
level: 'error',
});
});
/**
@ -504,12 +448,6 @@ export const systemSlice = createSlice({
state.toastQueue.push(
makeToast({ title: i18n.t('toast.canceled'), status: 'warning' })
);
state.log.push({
timestamp,
message: `Processing canceled`,
level: 'warning',
});
});
/**
@ -538,7 +476,6 @@ export const systemSlice = createSlice({
export const {
setShouldDisplayInProgressType,
setIsProcessing,
addLogEntry,
setShouldShowLogViewer,
setIsConnected,
setSocketId,