feat(ui): move invocation templates out of redux (wip)

This commit is contained in:
psychedelicious
2024-05-16 15:17:23 +10:00
parent d4df312300
commit f6a44681a8
18 changed files with 303 additions and 318 deletions

View File

@ -1,4 +1,5 @@
import { useAppSelector } from 'app/store/storeHooks';
import { useStore } from '@nanostores/react';
import { $templates } from 'features/nodes/store/nodesSlice';
import { NODE_WIDTH } from 'features/nodes/types/constants';
import type { AnyNode, InvocationTemplate } from 'features/nodes/types/invocation';
import { buildCurrentImageNode } from 'features/nodes/util/node/buildCurrentImageNode';
@ -8,8 +9,7 @@ import { useCallback } from 'react';
import { useReactFlow } from 'reactflow';
export const useBuildNode = () => {
const nodeTemplates = useAppSelector((s) => s.nodes.present.templates);
const templates = useStore($templates);
const flow = useReactFlow();
return useCallback(
@ -41,10 +41,10 @@ export const useBuildNode = () => {
// TODO: Keep track of invocation types so we do not need to cast this
// We know it is safe because the caller of this function gets the `type` arg from the list of invocation templates.
const template = nodeTemplates[type] as InvocationTemplate;
const template = templates[type] as InvocationTemplate;
return buildInvocationNode(position, template);
},
[nodeTemplates, flow]
[templates, flow]
);
};

View File

@ -1,20 +1,26 @@
import { useStore } from '@nanostores/react';
import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks';
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
import { $templates, selectNodesSlice } from 'features/nodes/store/nodesSlice';
import { isInvocationNode } from 'features/nodes/types/invocation';
import { getNeedsUpdate } from 'features/nodes/util/node/nodeUpdate';
const selector = createSelector(selectNodesSlice, (nodes) =>
nodes.nodes.filter(isInvocationNode).some((node) => {
const template = nodes.templates[node.data.type];
if (!template) {
return false;
}
return getNeedsUpdate(node, template);
})
);
import { useMemo } from 'react';
export const useGetNodesNeedUpdate = () => {
const getNeedsUpdate = useAppSelector(selector);
return getNeedsUpdate;
const templates = useStore($templates);
const selector = useMemo(
() =>
createSelector(selectNodesSlice, (nodes) =>
nodes.nodes.filter(isInvocationNode).some((node) => {
const template = templates[node.data.type];
if (!template) {
return false;
}
return getNeedsUpdate(node, template);
})
),
[templates]
);
const needsUpdate = useAppSelector(selector);
return needsUpdate;
};

View File

@ -1,5 +1,7 @@
// TODO: enable this at some point
import { useStore } from '@nanostores/react';
import { useAppSelector, useAppStore } from 'app/store/storeHooks';
import { $templates } from 'features/nodes/store/nodesSlice';
import { getIsGraphAcyclic } from 'features/nodes/store/util/getIsGraphAcyclic';
import { validateSourceAndTargetTypes } from 'features/nodes/store/util/validateSourceAndTargetTypes';
import type { InvocationNodeData } from 'features/nodes/types/invocation';
@ -13,6 +15,7 @@ import type { Connection, Node } from 'reactflow';
export const useIsValidConnection = () => {
const store = useAppStore();
const templates = useStore($templates);
const shouldValidateGraph = useAppSelector((s) => s.workflowSettings.shouldValidateGraph);
const isValidConnection = useCallback(
({ source, sourceHandle, target, targetHandle }: Connection): boolean => {
@ -27,7 +30,7 @@ export const useIsValidConnection = () => {
}
const state = store.getState();
const { nodes, edges, templates } = state.nodes.present;
const { nodes, edges } = state.nodes.present;
// Find the source and target nodes
const sourceNode = nodes.find((node) => node.id === source) as Node<InvocationNodeData>;
@ -76,7 +79,7 @@ export const useIsValidConnection = () => {
// Graphs much be acyclic (no loops!)
return getIsGraphAcyclic(source, target, nodes, edges);
},
[shouldValidateGraph, store]
[shouldValidateGraph, templates, store]
);
return isValidConnection;