Skip to content

Commit

Permalink
feat: add link to low vram guide to OOM toast (local only)
Browse files Browse the repository at this point in the history
Needed to do a bit of refactoring to support this. Overall, the error toast components are easier to understand now.
  • Loading branch information
psychedelicious committed Jan 8, 2025
1 parent 80aa5c8 commit bff64c2
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 31 deletions.
1 change: 1 addition & 0 deletions invokeai/frontend/web/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@
"modelAddedSimple": "Model Added to Queue",
"modelImportCanceled": "Model Import Canceled",
"outOfMemoryError": "Out of Memory Error",
"outOfMemoryErrorDescLocal": "Check out our <LinkComponent>Low VRAM guide</LinkComponent> to reduce OOMs.",
"outOfMemoryErrorDesc": "Your current generation settings exceed system capacity. Please adjust your settings and try again.",
"parameters": "Parameters",
"parameterSet": "Parameter Recalled",
Expand Down
79 changes: 50 additions & 29 deletions invokeai/frontend/web/src/features/toast/ErrorToastDescription.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,62 @@
import { Flex, IconButton, Text } from '@invoke-ai/ui-library';
import { t } from 'i18next';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { PiCopyBold } from 'react-icons/pi';

function onCopy(sessionId: string) {
navigator.clipboard.writeText(sessionId);
}
import { Button, Flex, Icon, IconButton, Link, Text } from '@invoke-ai/ui-library';
import type { PropsWithChildren } from 'react';
import { useCallback, useMemo } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { PiArrowSquareOutBold, PiCopyBold } from 'react-icons/pi';

const ERROR_TYPE_TO_TITLE: Record<string, string> = {
OutOfMemoryError: 'toast.outOfMemoryError',
};
type Props = { errorType: string; errorMessage?: string | null; sessionId: string; isLocal: boolean };

const COMMERCIAL_ERROR_TYPE_TO_DESC: Record<string, string> = {
OutOfMemoryError: 'toast.outOfMemoryErrorDesc',
const ExternalLink = (props: PropsWithChildren<{ href: string }>) => {
return (
<Button
as={Link}
variant="link"
isExternal
display="inline-flex"
alignItems="center"
href={props.href}
color="base.50"
>
{props.children}
<Icon display="inline" verticalAlign="middle" marginInlineStart={2} as={PiArrowSquareOutBold} />
</Button>
);
};

export const getTitleFromErrorType = (errorType: string) => {
return t(ERROR_TYPE_TO_TITLE[errorType] ?? 'toast.serverError');
};
export const ErrorToastTitle = ({ errorType }: Props) => {
const { t } = useTranslation();

type Props = { errorType: string; errorMessage?: string | null; sessionId: string; isLocal: boolean };
if (errorType === 'OutOfMemoryError') {
return t('toast.outOfMemoryError');
}

export default function ErrorToastDescription({ errorType, errorMessage, sessionId, isLocal }: Props) {
return t('toast.serverError');
};

export default function ErrorToastDescription({ errorType, isLocal, sessionId, errorMessage }: Props) {
const { t } = useTranslation();

const description = useMemo(() => {
// Special handling for commercial error types
const descriptionTKey = isLocal ? null : COMMERCIAL_ERROR_TYPE_TO_DESC[errorType];
if (descriptionTKey) {
return t(descriptionTKey);
}
if (errorMessage) {
if (errorType === 'OutOfMemoryError') {
if (isLocal) {
return (
<Trans
i18nKey="toast.outOfMemoryErrorDescLocal"
components={{
LinkComponent: <ExternalLink href="https://invoke-ai.github.io/InvokeAI/features/low-vram/" />,
}}
/>
);
} else {
return t('toast.outOfMemoryErrorDesc');
}
} else if (errorMessage) {
return `${errorType}: ${errorMessage}`;
}
}, [errorMessage, errorType, isLocal, t]);

const copySessionId = useCallback(() => navigator.clipboard.writeText(sessionId), [sessionId]);

return (
<Flex flexDir="column">
{description && (
Expand All @@ -50,14 +73,12 @@ export default function ErrorToastDescription({ errorType, errorMessage, session
size="sm"
aria-label="Copy"
icon={<PiCopyBold />}
onClick={onCopy.bind(null, sessionId)}
onClick={copySessionId}
variant="ghost"
sx={sx}
sx={{ svg: { fill: 'base.50' } }}
/>
</Flex>
)}
</Flex>
);
}

const sx = { svg: { fill: 'base.50' } };
11 changes: 9 additions & 2 deletions invokeai/frontend/web/src/services/events/setEventListeners.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { AppStore } from 'app/store/store';
import { deepClone } from 'common/util/deepClone';
import { $nodeExecutionStates, upsertExecutionState } from 'features/nodes/hooks/useExecutionState';
import { zNodeStatus } from 'features/nodes/types/invocation';
import ErrorToastDescription, { getTitleFromErrorType } from 'features/toast/ErrorToastDescription';
import ErrorToastDescription, { ErrorToastTitle } from 'features/toast/ErrorToastDescription';
import { toast } from 'features/toast/toast';
import { t } from 'i18next';
import { forEach, isNil, round } from 'lodash-es';
Expand Down Expand Up @@ -400,7 +400,14 @@ export const setEventListeners = ({ socket, store, setIsConnected }: SetEventLis

toast({
id: `INVOCATION_ERROR_${error_type}`,
title: getTitleFromErrorType(error_type),
title: (
<ErrorToastTitle
errorType={error_type}
errorMessage={error_message}
sessionId={sessionId}
isLocal={isLocal}
/>
),
status: 'error',
duration: null,
updateDescription: isLocal,
Expand Down

0 comments on commit bff64c2

Please sign in to comment.