fix(ui): memoize everything nodes

This commit is contained in:
psychedelicious 2023-04-22 22:03:27 +10:00
parent 4901911c1a
commit 43addc1548
22 changed files with 81 additions and 57 deletions

View File

@ -1,7 +1,7 @@
import { v4 as uuidv4 } from 'uuid';
import 'reactflow/dist/style.css';
import { useCallback } from 'react';
import { memo, useCallback } from 'react';
import {
Tooltip,
Menu,
@ -21,7 +21,7 @@ import { makeToast } from 'features/system/hooks/useToastWatcher';
import { IAIIconButton } from 'exports';
import { AnyInvocationType } from 'services/events/types';
export const AddNodeMenu = () => {
const AddNodeMenu = () => {
const dispatch = useAppDispatch();
const invocationTemplates = useAppSelector(
@ -67,3 +67,5 @@ export const AddNodeMenu = () => {
</Menu>
);
};
export default memo(AddNodeMenu);

View File

@ -2,8 +2,9 @@ import 'reactflow/dist/style.css';
import { Tooltip, Badge, HStack } from '@chakra-ui/react';
import { map } from 'lodash';
import { FIELDS } from '../types/constants';
import { memo } from 'react';
export const FieldTypeLegend = () => {
const FieldTypeLegend = () => {
return (
<HStack>
{map(FIELDS, ({ title, description, color }, key) => (
@ -16,3 +17,5 @@ export const FieldTypeLegend = () => {
</HStack>
);
};
export default memo(FieldTypeLegend);

View File

@ -1,15 +1,12 @@
import {
Background,
Controls,
MiniMap,
OnConnect,
OnEdgesChange,
OnNodesChange,
ReactFlow,
ConnectionLineType,
OnConnectStart,
OnConnectEnd,
Panel,
} from 'reactflow';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { RootState } from 'app/store';
@ -20,16 +17,8 @@ import {
edgesChanged,
nodesChanged,
} from '../store/nodesSlice';
import { useCallback, useState } from 'react';
import { useCallback } from 'react';
import { InvocationComponent } from './InvocationComponent';
import { AddNodeMenu } from './AddNodeMenu';
import { FieldTypeLegend } from './FieldTypeLegend';
import { Button } from '@chakra-ui/react';
import { nodesGraphBuilt } from 'services/thunks/session';
import { IAIIconButton } from 'exports';
import { InfoIcon } from '@chakra-ui/icons';
import { ViewportControls } from './ViewportControls';
import NodeGraphOverlay from './NodeGraphOverlay';
import TopLeftPanel from './panels/TopLeftPanel';
import TopRightPanel from './panels/TopRightPanel';
import TopCenterPanel from './panels/TopCenterPanel';

View File

@ -1,6 +1,6 @@
import { Flex, Heading, Tooltip, Icon } from '@chakra-ui/react';
import { InvocationTemplate } from 'features/nodes/types/types';
import { MutableRefObject } from 'react';
import { memo, MutableRefObject } from 'react';
import { FaInfoCircle } from 'react-icons/fa';
interface IAINodeHeaderProps {
@ -8,7 +8,7 @@ interface IAINodeHeaderProps {
template: InvocationTemplate;
}
export default function IAINodeHeader(props: IAINodeHeaderProps) {
const IAINodeHeader = (props: IAINodeHeaderProps) => {
const { nodeId, template } = props;
return (
<Flex
@ -34,4 +34,6 @@ export default function IAINodeHeader(props: IAINodeHeaderProps) {
</Tooltip>
</Flex>
);
}
};
export default memo(IAINodeHeader);

View File

@ -19,7 +19,7 @@ import {
} from '@chakra-ui/react';
import FieldHandle from '../FieldHandle';
import { useIsValidConnection } from 'features/nodes/hooks/useIsValidConnection';
import { InputFieldComponent } from '../InputFieldComponent';
import InputFieldComponent from '../InputFieldComponent';
import { FaInfoCircle } from 'react-icons/fa';
import { HANDLE_TOOLTIP_OPEN_DELAY } from 'features/nodes/types/constants';

View File

@ -1,6 +1,7 @@
import { memo } from 'react';
import { NodeResizeControl, NodeResizerProps } from 'reactflow';
export default function IAINodeResizer(props: NodeResizerProps) {
const IAINodeResizer = (props: NodeResizerProps) => {
const { ...rest } = props;
return (
<NodeResizeControl
@ -17,4 +18,6 @@ export default function IAINodeResizer(props: NodeResizerProps) {
{...rest}
></NodeResizeControl>
);
}
};
export default memo(IAINodeResizer);

View File

@ -1,13 +1,14 @@
import { Box } from '@chakra-ui/react';
import { memo } from 'react';
import { InputFieldTemplate, InputFieldValue } from '../types/types';
import { ArrayInputFieldComponent } from './fields/ArrayInputFieldComponent';
import { BooleanInputFieldComponent } from './fields/BooleanInputFieldComponent';
import { EnumInputFieldComponent } from './fields/EnumInputFieldComponent';
import { ImageInputFieldComponent } from './fields/ImageInputFieldComponent';
import { LatentsInputFieldComponent } from './fields/LatentsInputFieldComponent';
import { ModelInputFieldComponent } from './fields/ModelInputFieldComponent';
import { NumberInputFieldComponent } from './fields/NumberInputFieldComponent';
import { StringInputFieldComponent } from './fields/StringInputFieldComponent';
import ArrayInputFieldComponent from './fields/ArrayInputFieldComponent';
import BooleanInputFieldComponent from './fields/BooleanInputFieldComponent';
import EnumInputFieldComponent from './fields/EnumInputFieldComponent';
import ImageInputFieldComponent from './fields/ImageInputFieldComponent';
import LatentsInputFieldComponent from './fields/LatentsInputFieldComponent';
import ModelInputFieldComponent from './fields/ModelInputFieldComponent';
import NumberInputFieldComponent from './fields/NumberInputFieldComponent';
import StringInputFieldComponent from './fields/StringInputFieldComponent';
type InputFieldComponentProps = {
nodeId: string;
@ -16,7 +17,7 @@ type InputFieldComponentProps = {
};
// build an individual input element based on the schema
export const InputFieldComponent = (props: InputFieldComponentProps) => {
const InputFieldComponent = (props: InputFieldComponentProps) => {
const { nodeId, field, template } = props;
const { type, value } = field;
@ -105,3 +106,5 @@ export const InputFieldComponent = (props: InputFieldComponentProps) => {
return <Box p={2}>Unknown field type: {type}</Box>;
};
export default memo(InputFieldComponent);

View File

@ -1,14 +1,12 @@
import { NodeProps, NodeResizeControl } from 'reactflow';
import { NodeProps } from 'reactflow';
import { Box, Flex, Icon, useToken } from '@chakra-ui/react';
import { FaExclamationCircle } from 'react-icons/fa';
import { InvocationTemplate, InvocationValue } from '../types/types';
import { memo, PropsWithChildren, useMemo, useRef } from 'react';
import { useGetInvocationTemplate } from '../hooks/useInvocationTemplate';
import { memo, PropsWithChildren, useMemo } from 'react';
import IAINodeOutputs from './IAINode/IAINodeOutputs';
import IAINodeInputs from './IAINode/IAINodeInputs';
import IAINodeHeader from './IAINode/IAINodeHeader';
import { IoResize } from 'react-icons/io5';
import IAINodeResizer from './IAINode/IAINodeResizer';
import { RootState } from 'app/store';
import { AnyInvocationType } from 'services/events/types';

View File

@ -3,6 +3,7 @@ import { Box } from '@chakra-ui/react';
import { ReactFlowProvider } from 'reactflow';
import { Flow } from './Flow';
import { memo } from 'react';
const NodeEditor = () => {
return (
@ -22,4 +23,4 @@ const NodeEditor = () => {
);
};
export default NodeEditor;
export default memo(NodeEditor);

View File

@ -1,9 +1,10 @@
import { Box } from '@chakra-ui/react';
import { RootState } from 'app/store';
import { useAppSelector } from 'app/storeHooks';
import { memo } from 'react';
import { buildNodesGraph } from '../util/nodesGraphBuilder/buildNodesGraph';
export default function NodeGraphOverlay() {
const NodeGraphOverlay = () => {
const state = useAppSelector((state: RootState) => state);
const graph = buildNodesGraph(state);
@ -14,7 +15,6 @@ export default function NodeGraphOverlay() {
position="absolute"
top={10}
right={2}
userSelect="none"
opacity={0.7}
background="base.800"
p={2}
@ -25,4 +25,6 @@ export default function NodeGraphOverlay() {
{JSON.stringify(graph, null, 2)}
</Box>
);
}
};
export default memo(NodeGraphOverlay);

View File

@ -1,12 +1,12 @@
import { ButtonGroup } from '@chakra-ui/react';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { IAIIconButton } from 'exports';
import { useCallback } from 'react';
import { memo, useCallback } from 'react';
import { FaCode, FaExpand, FaMinus, FaPlus } from 'react-icons/fa';
import { useReactFlow } from 'reactflow';
import { shouldShowGraphOverlayChanged } from '../store/nodesSlice';
export const ViewportControls = () => {
const ViewportControls = () => {
const { zoomIn, zoomOut, fitView } = useReactFlow();
const dispatch = useAppDispatch();
const shouldShowGraphOverlay = useAppSelector(
@ -55,3 +55,5 @@ export const ViewportControls = () => {
</ButtonGroup>
);
};
export default memo(ViewportControls);

View File

@ -2,13 +2,16 @@ import {
ArrayInputFieldTemplate,
ArrayInputFieldValue,
} from 'features/nodes/types/types';
import { FaImage, FaList } from 'react-icons/fa';
import { memo } from 'react';
import { FaList } from 'react-icons/fa';
import { FieldComponentProps } from './types';
export const ArrayInputFieldComponent = (
const ArrayInputFieldComponent = (
props: FieldComponentProps<ArrayInputFieldValue, ArrayInputFieldTemplate>
) => {
const { nodeId, field } = props;
return <FaList />;
};
export default memo(ArrayInputFieldComponent);

View File

@ -5,10 +5,10 @@ import {
BooleanInputFieldTemplate,
BooleanInputFieldValue,
} from 'features/nodes/types/types';
import { ChangeEvent } from 'react';
import { ChangeEvent, memo } from 'react';
import { FieldComponentProps } from './types';
export const BooleanInputFieldComponent = (
const BooleanInputFieldComponent = (
props: FieldComponentProps<BooleanInputFieldValue, BooleanInputFieldTemplate>
) => {
const { nodeId, field } = props;
@ -29,3 +29,5 @@ export const BooleanInputFieldComponent = (
<Switch onChange={handleValueChanged} isChecked={field.value}></Switch>
);
};
export default memo(BooleanInputFieldComponent);

View File

@ -5,10 +5,10 @@ import {
EnumInputFieldTemplate,
EnumInputFieldValue,
} from 'features/nodes/types/types';
import { ChangeEvent } from 'react';
import { ChangeEvent, memo } from 'react';
import { FieldComponentProps } from './types';
export const EnumInputFieldComponent = (
const EnumInputFieldComponent = (
props: FieldComponentProps<EnumInputFieldValue, EnumInputFieldTemplate>
) => {
const { nodeId, field, template } = props;
@ -33,3 +33,5 @@ export const EnumInputFieldComponent = (
</Select>
);
};
export default memo(EnumInputFieldComponent);

View File

@ -9,12 +9,12 @@ import {
ImageInputFieldTemplate,
ImageInputFieldValue,
} from 'features/nodes/types/types';
import { DragEvent, useCallback, useState } from 'react';
import { DragEvent, memo, useCallback, useState } from 'react';
import { FaImage } from 'react-icons/fa';
import { ImageType } from 'services/api';
import { FieldComponentProps } from './types';
export const ImageInputFieldComponent = (
const ImageInputFieldComponent = (
props: FieldComponentProps<ImageInputFieldValue, ImageInputFieldTemplate>
) => {
const { nodeId, field } = props;
@ -62,3 +62,5 @@ export const ImageInputFieldComponent = (
</Box>
);
};
export default memo(ImageInputFieldComponent);

View File

@ -2,12 +2,15 @@ import {
LatentsInputFieldTemplate,
LatentsInputFieldValue,
} from 'features/nodes/types/types';
import { memo } from 'react';
import { FieldComponentProps } from './types';
export const LatentsInputFieldComponent = (
const LatentsInputFieldComponent = (
props: FieldComponentProps<LatentsInputFieldValue, LatentsInputFieldTemplate>
) => {
const { nodeId, field } = props;
return null;
};
export default memo(LatentsInputFieldComponent);

View File

@ -12,7 +12,7 @@ import {
selectModelsIds,
} from 'features/system/store/modelSlice';
import { isEqual, map } from 'lodash';
import { ChangeEvent } from 'react';
import { ChangeEvent, memo } from 'react';
import { FieldComponentProps } from './types';
const availableModelsSelector = createSelector(
@ -28,7 +28,7 @@ const availableModelsSelector = createSelector(
}
);
export const ModelInputFieldComponent = (
const ModelInputFieldComponent = (
props: FieldComponentProps<ModelInputFieldValue, ModelInputFieldTemplate>
) => {
const { nodeId, field } = props;
@ -55,3 +55,5 @@ export const ModelInputFieldComponent = (
</Select>
);
};
export default memo(ModelInputFieldComponent);

View File

@ -13,9 +13,10 @@ import {
IntegerInputFieldTemplate,
IntegerInputFieldValue,
} from 'features/nodes/types/types';
import { memo } from 'react';
import { FieldComponentProps } from './types';
export const NumberInputFieldComponent = (
const NumberInputFieldComponent = (
props: FieldComponentProps<
IntegerInputFieldValue | FloatInputFieldValue,
IntegerInputFieldTemplate | FloatInputFieldTemplate
@ -39,3 +40,5 @@ export const NumberInputFieldComponent = (
</NumberInput>
);
};
export default memo(NumberInputFieldComponent);

View File

@ -5,10 +5,10 @@ import {
StringInputFieldTemplate,
StringInputFieldValue,
} from 'features/nodes/types/types';
import { ChangeEvent } from 'react';
import { ChangeEvent, memo } from 'react';
import { FieldComponentProps } from './types';
export const StringInputFieldComponent = (
const StringInputFieldComponent = (
props: FieldComponentProps<StringInputFieldValue, StringInputFieldTemplate>
) => {
const { nodeId, field } = props;
@ -27,3 +27,5 @@ export const StringInputFieldComponent = (
return <Input onChange={handleValueChanged} value={field.value}></Input>;
};
export default memo(StringInputFieldComponent);

View File

@ -1,6 +1,6 @@
import { memo } from 'react';
import { Panel } from 'reactflow';
import { ViewportControls } from '../ViewportControls';
import ViewportControls from '../ViewportControls';
const BottomLeftPanel = () => (
<Panel position="bottom-left">

View File

@ -1,6 +1,6 @@
import { memo } from 'react';
import { Panel } from 'reactflow';
import { AddNodeMenu } from '../AddNodeMenu';
import AddNodeMenu from '../AddNodeMenu';
const TopLeftPanel = () => (
<Panel position="top-left">

View File

@ -2,7 +2,7 @@ import { RootState } from 'app/store';
import { useAppSelector } from 'app/storeHooks';
import { memo } from 'react';
import { Panel } from 'reactflow';
import { FieldTypeLegend } from '../FieldTypeLegend';
import FieldTypeLegend from '../FieldTypeLegend';
import NodeGraphOverlay from '../NodeGraphOverlay';
const TopRightPanel = () => {