fix: Fix app crashing when you upload an incorrect JSON to node editor

This commit is contained in:
blessedcoolant 2023-07-23 15:24:04 +12:00
parent 075f9b3a7a
commit fdc444ed61
2 changed files with 54 additions and 26 deletions

View File

@ -615,6 +615,8 @@
"initialImageNotSetDesc": "Could not load initial image", "initialImageNotSetDesc": "Could not load initial image",
"nodesSaved": "Nodes Saved", "nodesSaved": "Nodes Saved",
"nodesLoaded": "Nodes Loaded", "nodesLoaded": "Nodes Loaded",
"nodesNotValidGraph": "Not a valid InvokeAI Node Graph",
"nodesNotValidJSON": "Not a valid JSON",
"nodesLoadedFailed": "Failed To Load Nodes", "nodesLoadedFailed": "Failed To Load Nodes",
"nodesCleared": "Nodes Cleared" "nodesCleared": "Nodes Cleared"
}, },

View File

@ -1,14 +1,28 @@
import { FileButton } from '@mantine/core'; import { FileButton } from '@mantine/core';
import { makeToast } from 'features/system/util/makeToast';
import { useAppDispatch } from 'app/store/storeHooks'; import { useAppDispatch } from 'app/store/storeHooks';
import IAIIconButton from 'common/components/IAIIconButton'; import IAIIconButton from 'common/components/IAIIconButton';
import { loadFileEdges, loadFileNodes } from 'features/nodes/store/nodesSlice'; import { loadFileEdges, loadFileNodes } from 'features/nodes/store/nodesSlice';
import { addToast } from 'features/system/store/systemSlice'; import { addToast } from 'features/system/store/systemSlice';
import { makeToast } from 'features/system/util/makeToast';
import { memo, useCallback, useRef } from 'react'; import { memo, useCallback, useRef } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FaUpload } from 'react-icons/fa'; import { FaUpload } from 'react-icons/fa';
import { useReactFlow } from 'reactflow'; import { useReactFlow } from 'reactflow';
interface JsonFile {
[key: string]: unknown;
}
function validateInvokeAIGraph(jsonFile: JsonFile): boolean {
const keys = ['nodes', 'edges', 'viewport'];
for (const key of keys) {
if (!(key in jsonFile)) {
return false;
}
}
return true;
}
const LoadNodesButton = () => { const LoadNodesButton = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -22,20 +36,12 @@ const LoadNodesButton = () => {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = async () => { reader.onload = async () => {
const json = reader.result; const json = reader.result;
try {
const retrievedNodeTree = await JSON.parse(String(json)); const retrievedNodeTree = await JSON.parse(String(json));
const isValidNodeTree = validateInvokeAIGraph(retrievedNodeTree);
if (!retrievedNodeTree) { if (isValidNodeTree) {
dispatch(
addToast(
makeToast({
title: t('toast.nodesLoadedFailed'),
status: 'error',
})
)
);
}
if (retrievedNodeTree) {
dispatch(loadFileNodes(retrievedNodeTree.nodes)); dispatch(loadFileNodes(retrievedNodeTree.nodes));
dispatch(loadFileEdges(retrievedNodeTree.edges)); dispatch(loadFileEdges(retrievedNodeTree.edges));
fitView(); fitView();
@ -45,10 +51,30 @@ const LoadNodesButton = () => {
makeToast({ title: t('toast.nodesLoaded'), status: 'success' }) makeToast({ title: t('toast.nodesLoaded'), status: 'success' })
) )
); );
} else {
dispatch(
addToast(
makeToast({
title: t('toast.nodesNotValidGraph'),
status: 'error',
})
)
);
} }
// Cleanup // Cleanup
reader.abort(); reader.abort();
} catch (error) {
if (error) {
dispatch(
addToast(
makeToast({
title: t('toast.nodesNotValidJSON'),
status: 'error',
})
)
);
}
}
}; };
reader.readAsText(v); reader.readAsText(v);