fix: bug with disappearing item controls

This commit is contained in:
Mark Mankarious
2023-08-16 15:59:10 +01:00
parent 6139401711
commit c3b72e3cfd
8 changed files with 73 additions and 19 deletions

View File

@@ -1,8 +1,7 @@
import React from 'react';
import { Box, Typography, useTheme } from '@mui/material';
import { Box, useTheme } from '@mui/material';
import { useUiStateStore } from 'src/stores/uiStateStore';
import { SizeIndicator } from './SizeIndicator';
import { Value } from './Value';
import { LineItem } from './LineItem';
export const DebugUtils = () => {
@@ -19,7 +18,14 @@ export const DebugUtils = () => {
const { scroll, mouse, zoom, rendererSize } = uiState;
return (
<>
<Box
sx={{
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none'
}}
>
<SizeIndicator />
<Box
sx={{
@@ -60,6 +66,6 @@ export const DebugUtils = () => {
<LineItem title="Mode" value={mode.type} />
<LineItem title="Mode data" value={JSON.stringify(mode)} />
</Box>
</>
</Box>
);
};

View File

@@ -11,7 +11,6 @@ import { Connector } from 'src/components/Connector/Connector';
import { DebugUtils } from 'src/components/DebugUtils/DebugUtils';
import { useResizeObserver } from 'src/hooks/useResizeObserver';
import { SceneLayer } from 'src/components/SceneLayer/SceneLayer';
import { IsoTileArea } from 'src/components/IsoTileArea/IsoTileArea';
import { DEFAULT_COLOR } from 'src/config';
export const Renderer = () => {
@@ -73,7 +72,6 @@ export const Renderer = () => {
return (
<Box
ref={containerRef}
sx={{
width: '100%',
height: '100%'
@@ -126,6 +124,8 @@ export const Renderer = () => {
<DebugUtils />
</SceneLayer>
)}
{/* Interaction layer */}
<SceneLayer ref={containerRef} />
</Box>
);
};

View File

@@ -1,14 +1,15 @@
import React from 'react';
import React, { forwardRef } from 'react';
import { Box } from '@mui/material';
interface Props {
children: React.ReactNode;
children?: React.ReactNode;
order?: number;
}
export const SceneLayer = ({ children, order = 0 }: Props) => {
export const SceneLayer = forwardRef(({ children, order = 0 }: Props, ref) => {
return (
<Box
ref={ref}
sx={{
position: 'absolute',
zIndex: order,
@@ -21,4 +22,4 @@ export const SceneLayer = ({ children, order = 0 }: Props) => {
{children}
</Box>
);
};
});

View File

@@ -37,7 +37,8 @@ export const Cursor: InteractionReducer = {
}
},
mousedown: (draftState) => {
if (draftState.mode.type !== 'CURSOR') return;
if (draftState.mode.type !== 'CURSOR' || !draftState.isRendererInteraction)
return;
const itemsAtTile = filterNodesByTile({
tile: draftState.mouse.position.tile,

View File

@@ -97,7 +97,8 @@ export const useInteractionManager = () => {
contextMenu,
itemControls,
rendererRef: rendererRef.current,
sceneActions
sceneActions,
isRendererInteraction: rendererRef.current === e.target
};
const getTransitionaryState = () => {

View File

@@ -1,14 +1,13 @@
import React, { createContext, useRef, useContext } from 'react';
import { v4 as uuid } from 'uuid';
import { createStore, useStore } from 'zustand';
import { produce } from 'immer';
import { Scene, SceneActions, GroupInput } from 'src/types';
import { Scene, SceneActions } from 'src/types';
import { sceneInput } from 'src/validation/scene';
import {
sceneInputtoScene,
getItemById,
getConnectorPath,
groupInputToGroup
groupInputToGroup,
sceneInputtoScene
} from 'src/utils';
interface Actions {
@@ -31,12 +30,20 @@ const initialState = () => {
const newScene = sceneInputtoScene(scene);
set(newScene);
return newScene;
},
updateScene: (scene) => {
set(scene);
set({
nodes: scene.nodes,
connectors: scene.connectors,
groups: scene.groups
});
},
updateNode: (id, updates, scene) => {
return produce(scene ?? get(), (draftState) => {
const newScene = produce(scene ?? get(), (draftState) => {
const { item: node, index } = getItemById(draftState.nodes, id);
draftState.nodes[index] = {
@@ -57,11 +64,20 @@ const initialState = () => {
}
});
});
set({ nodes: newScene.nodes, connectors: newScene.connectors });
return newScene;
},
createGroup: (group) => {
return produce(get(), (draftState) => {
const newScene = produce(get(), (draftState) => {
draftState.groups.push(groupInputToGroup(group));
});
set({ groups: newScene.groups });
return newScene;
}
}
};

View File

@@ -18,6 +18,7 @@ export interface State {
contextMenu: ContextMenu;
itemControls: ItemControls;
rendererRef: HTMLElement;
isRendererInteraction: boolean;
}
export type InteractionReducerAction = (state: Draft<State>) => void;

View File

@@ -0,0 +1,28 @@
// Although we don't normally test third party libraries,
// this is useful to explore the behaviour of immer
import { produce } from 'immer';
const createItem = (x: number, y: number) => {
return {
x,
y
};
};
describe('Tests immer', () => {
test('Array equivalence without immer', () => {
const arr = [createItem(0, 0), createItem(1, 1)];
const newArr = [createItem(0, 0), createItem(2, 2)];
expect(arr[0]).not.toBe(newArr[0]);
});
test('Array equivalence with immer', () => {
const arr = [createItem(0, 0), createItem(1, 1)];
const newArr = produce(arr, (draftState) => {
draftState[1] = createItem(2, 2);
});
expect(arr[0]).toBe(newArr[0]);
});
});