feat(ui): move viewport state to nanostores

This commit is contained in:
psychedelicious 2024-05-16 21:21:39 +10:00
parent 6cf5b402c6
commit 7f78fe7a36
4 changed files with 14 additions and 24 deletions

View File

@ -1,23 +1,21 @@
import type { Modifier } from '@dnd-kit/core';
import { getEventCoordinates } from '@dnd-kit/utilities';
import { createSelector } from '@reduxjs/toolkit';
import { useStore } from '@nanostores/react';
import { useAppSelector } from 'app/store/storeHooks';
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
import { $viewport } from 'features/nodes/store/nodesSlice';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { useCallback } from 'react';
const selectZoom = createSelector([selectNodesSlice, activeTabNameSelector], (nodes, activeTabName) =>
activeTabName === 'workflows' ? nodes.viewport.zoom : 1
);
/**
* Applies scaling to the drag transform (if on node editor tab) and centers it on cursor.
*/
export const useScaledModifer = () => {
const zoom = useAppSelector(selectZoom);
const activeTabName = useAppSelector(activeTabNameSelector);
const workflowsViewport = useStore($viewport);
const modifier: Modifier = useCallback(
({ activatorEvent, draggingNodeRect, transform }) => {
if (draggingNodeRect && activatorEvent) {
const zoom = activeTabName === 'workflows' ? workflowsViewport.zoom : 1;
const activatorCoordinates = getEventCoordinates(activatorEvent);
if (!activatorCoordinates) {
@ -42,7 +40,7 @@ export const useScaledModifer = () => {
return transform;
},
[zoom]
[activeTabName, workflowsViewport.zoom]
);
return modifier;

View File

@ -1,4 +1,5 @@
import { useGlobalMenuClose, useToken } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useConnection } from 'features/nodes/hooks/useConnection';
import { useCopyPaste } from 'features/nodes/hooks/useCopyPaste';
@ -6,6 +7,7 @@ import { useIsValidConnection } from 'features/nodes/hooks/useIsValidConnection'
import { useWorkflowWatcher } from 'features/nodes/hooks/useWorkflowWatcher';
import {
$cursorPos,
$viewport,
connectionMade,
edgeAdded,
edgeDeleted,
@ -16,7 +18,6 @@ import {
redo,
selectedAll,
undo,
viewportChanged,
} from 'features/nodes/store/nodesSlice';
import { $flow } from 'features/nodes/store/reactFlowInstance';
import type { CSSProperties, MouseEvent } from 'react';
@ -64,7 +65,7 @@ export const Flow = memo(() => {
const dispatch = useAppDispatch();
const nodes = useAppSelector((s) => s.nodes.present.nodes);
const edges = useAppSelector((s) => s.nodes.present.edges);
const viewport = useAppSelector((s) => s.nodes.present.viewport);
const viewport = useStore($viewport);
const shouldSnapToGrid = useAppSelector((s) => s.workflowSettings.shouldSnapToGrid);
const selectionMode = useAppSelector((s) => s.workflowSettings.selectionMode);
const { onConnectStart, onConnect, onConnectEnd } = useConnection();
@ -108,12 +109,9 @@ export const Flow = memo(() => {
[dispatch]
);
const handleMoveEnd: OnMoveEnd = useCallback(
(e, viewport) => {
dispatch(viewportChanged(viewport));
},
[dispatch]
);
const handleMoveEnd: OnMoveEnd = useCallback((e, viewport) => {
$viewport.set(viewport);
}, []);
const { onCloseGlobal } = useGlobalMenuClose();
const handlePaneClick = useCallback(() => {

View File

@ -75,7 +75,6 @@ const initialNodesState: NodesState = {
nodes: [],
edges: [],
nodeExecutionStates: {},
viewport: { x: 0, y: 0, zoom: 1 },
};
type FieldValueAction<T extends FieldValue> = PayloadAction<{
@ -410,9 +409,6 @@ export const nodesSlice = createSlice({
state.nodes = [];
state.edges = [];
},
viewportChanged: (state, action: PayloadAction<Viewport>) => {
state.viewport = action.payload;
},
selectedAll: (state) => {
state.nodes = applyNodeChanges(
state.nodes.map((n) => ({ id: n.id, type: 'select', selected: true })),
@ -586,7 +582,6 @@ export const {
notesNodeValueChanged,
selectedAll,
selectionPasted,
viewportChanged,
edgeAdded,
undo,
redo,
@ -598,6 +593,7 @@ export const $copiedNodes = atom<AnyNode[]>([]);
export const $copiedEdges = atom<InvocationNodeEdge[]>([]);
export const $pendingConnection = atom<PendingConnection | null>(null);
export const $isModifyingEdge = atom(false);
export const $viewport = atom<Viewport>({ x: 0, y: 0, zoom: 1 });
export const $isAddNodePopoverOpen = atom(false);
export const closeAddNodePopover = () => {
$isAddNodePopoverOpen.set(false);
@ -638,7 +634,7 @@ const isSelectionAction = (action: UnknownAction) => {
return false;
};
const individualGroupByMatcher = isAnyOf(nodesChanged, viewportChanged);
const individualGroupByMatcher = isAnyOf(nodesChanged);
export const nodesUndoableConfig: UndoableOptions<NodesState, UnknownAction> = {
limit: 64,

View File

@ -12,7 +12,6 @@ import type {
NodeExecutionState,
} from 'features/nodes/types/invocation';
import type { WorkflowV3 } from 'features/nodes/types/workflow';
import type { Viewport } from 'reactflow';
export type Templates = Record<string, InvocationTemplate>;
@ -27,7 +26,6 @@ export type NodesState = {
nodes: AnyNode[];
edges: InvocationNodeEdge[];
nodeExecutionStates: Record<string, NodeExecutionState>;
viewport: Viewport;
};
export type WorkflowMode = 'edit' | 'view';