diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json
index 7f6b196a060..f3dcc8097d0 100644
--- a/invokeai/frontend/web/public/locales/en.json
+++ b/invokeai/frontend/web/public/locales/en.json
@@ -1185,6 +1185,7 @@
"modelAddedSimple": "Model Added to Queue",
"modelImportCanceled": "Model Import Canceled",
"outOfMemoryError": "Out of Memory Error",
+ "outOfMemoryErrorDescLocal": "Follow our Low VRAM guide to reduce OOMs.",
"outOfMemoryErrorDesc": "Your current generation settings exceed system capacity. Please adjust your settings and try again.",
"parameters": "Parameters",
"parameterSet": "Parameter Recalled",
@@ -2133,7 +2134,7 @@
"toGetStartedLocal": "To get started, make sure to download or import models needed to run Invoke. Then, enter a prompt in the box and click Invoke to generate your first image. Select a prompt template to improve results. You can choose to save your images directly to the Gallery or edit them to the Canvas.",
"toGetStarted": "To get started, enter a prompt in the box and click Invoke to generate your first image. Select a prompt template to improve results. You can choose to save your images directly to the Gallery or edit them to the Canvas.",
"gettingStartedSeries": "Want more guidance? Check out our Getting Started Series for tips on unlocking the full potential of the Invoke Studio.",
- "lowVRAMMode": "For best performance, follow our Low VRAM mode guide.",
+ "lowVRAMMode": "For best performance, follow our Low VRAM guide.",
"noModelsInstalled": "It looks like you don't have any models installed! You can download a starter model bundle or import models."
},
"whatsNew": {
diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageViewer/NoContentForViewer.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageViewer/NoContentForViewer.tsx
index 08a2b0c3bd9..bc035491a6c 100644
--- a/invokeai/frontend/web/src/features/gallery/components/ImageViewer/NoContentForViewer.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/ImageViewer/NoContentForViewer.tsx
@@ -1,15 +1,5 @@
-import {
- Alert,
- AlertDescription,
- AlertIcon,
- Button,
- Divider,
- Flex,
- Icon,
- Link,
- Spinner,
- Text,
-} from '@invoke-ai/ui-library';
+import type { ButtonProps } from '@invoke-ai/ui-library';
+import { Alert, AlertDescription, AlertIcon, Button, Divider, Flex, Link, Spinner, Text } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
import { InvokeLogoIcon } from 'common/components/InvokeLogoIcon';
@@ -71,20 +61,19 @@ const LoadingSpinner = () => {
);
};
-const ExternalLink = (props: PropsWithChildren<{ href: string }>) => {
+export const ExternalLink = (props: ButtonProps & { href: string }) => {
return (
}
color="base.50"
- >
- {props.children}
-
-
+ mt={-1}
+ {...props}
+ />
);
};
diff --git a/invokeai/frontend/web/src/features/toast/ErrorToastDescription.tsx b/invokeai/frontend/web/src/features/toast/ErrorToastDescription.tsx
index 26baf9c739b..23f7ee64bda 100644
--- a/invokeai/frontend/web/src/features/toast/ErrorToastDescription.tsx
+++ b/invokeai/frontend/web/src/features/toast/ErrorToastDescription.tsx
@@ -1,39 +1,45 @@
import { Flex, IconButton, Text } from '@invoke-ai/ui-library';
-import { t } from 'i18next';
-import { useMemo } from 'react';
-import { useTranslation } from 'react-i18next';
+import { ExternalLink } from 'features/gallery/components/ImageViewer/NoContentForViewer';
+import { useCallback, useMemo } from 'react';
+import { Trans, useTranslation } from 'react-i18next';
import { PiCopyBold } from 'react-icons/pi';
-function onCopy(sessionId: string) {
- navigator.clipboard.writeText(sessionId);
-}
+type Props = { errorType: string; errorMessage?: string | null; sessionId: string; isLocal: boolean };
-const ERROR_TYPE_TO_TITLE: Record = {
- OutOfMemoryError: 'toast.outOfMemoryError',
-};
+export const ErrorToastTitle = ({ errorType }: Props) => {
+ const { t } = useTranslation();
-const COMMERCIAL_ERROR_TYPE_TO_DESC: Record = {
- OutOfMemoryError: 'toast.outOfMemoryErrorDesc',
-};
+ if (errorType === 'OutOfMemoryError') {
+ return t('toast.outOfMemoryError');
+ }
-export const getTitleFromErrorType = (errorType: string) => {
- return t(ERROR_TYPE_TO_TITLE[errorType] ?? 'toast.serverError');
+ return t('toast.serverError');
};
-type Props = { errorType: string; errorMessage?: string | null; sessionId: string; isLocal: boolean };
-
-export default function ErrorToastDescription({ errorType, errorMessage, sessionId, isLocal }: Props) {
+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 (
+ ,
+ }}
+ />
+ );
+ } else {
+ return t('toast.outOfMemoryErrorDesc');
+ }
+ } else if (errorMessage) {
return `${errorType}: ${errorMessage}`;
}
}, [errorMessage, errorType, isLocal, t]);
+
+ const copySessionId = useCallback(() => navigator.clipboard.writeText(sessionId), [sessionId]);
+
return (
{description && (
@@ -50,14 +56,12 @@ export default function ErrorToastDescription({ errorType, errorMessage, session
size="sm"
aria-label="Copy"
icon={}
- onClick={onCopy.bind(null, sessionId)}
+ onClick={copySessionId}
variant="ghost"
- sx={sx}
+ sx={{ svg: { fill: 'base.50' } }}
/>
)}
);
}
-
-const sx = { svg: { fill: 'base.50' } };
diff --git a/invokeai/frontend/web/src/services/events/setEventListeners.tsx b/invokeai/frontend/web/src/services/events/setEventListeners.tsx
index b3c8d72cea9..bb389b3406a 100644
--- a/invokeai/frontend/web/src/services/events/setEventListeners.tsx
+++ b/invokeai/frontend/web/src/services/events/setEventListeners.tsx
@@ -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';
@@ -400,7 +400,14 @@ export const setEventListeners = ({ socket, store, setIsConnected }: SetEventLis
toast({
id: `INVOCATION_ERROR_${error_type}`,
- title: getTitleFromErrorType(error_type),
+ title: (
+
+ ),
status: 'error',
duration: null,
updateDescription: isLocal,