mirror of
https://github.com/stan-smith/FossFLOW.git
synced 2025-12-26 07:59:10 -05:00
feat: allows all interactions to be disabled
This commit is contained in:
@@ -14,7 +14,6 @@ import {
|
||||
import { useSceneStore, SceneProvider } from 'src/stores/sceneStore';
|
||||
import { GlobalStyles } from 'src/styles/GlobalStyles';
|
||||
import { Renderer } from 'src/components/Renderer/Renderer';
|
||||
import { sceneToSceneInput } from 'src/utils';
|
||||
import { LabelContainer } from 'src/components/Node/LabelContainer';
|
||||
import { useWindowUtils } from 'src/hooks/useWindowUtils';
|
||||
import { ItemControlsManager } from './components/ItemControls/ItemControlsManager';
|
||||
@@ -23,14 +22,20 @@ import { UiStateProvider, useUiStateStore } from './stores/uiStateStore';
|
||||
interface Props {
|
||||
initialScene: SceneInput & {
|
||||
zoom?: number;
|
||||
isToolbarVisible?: boolean;
|
||||
};
|
||||
interactionsEnabled?: boolean;
|
||||
onSceneUpdated?: (scene: SceneInput, prevScene: SceneInput) => void;
|
||||
width?: number | string;
|
||||
height?: number | string;
|
||||
}
|
||||
|
||||
const App = ({ initialScene, width, height = 500, onSceneUpdated }: Props) => {
|
||||
const App = ({
|
||||
initialScene,
|
||||
width,
|
||||
height = 500,
|
||||
interactionsEnabled: interactionsEnabledProp = true,
|
||||
onSceneUpdated
|
||||
}: Props) => {
|
||||
useWindowUtils();
|
||||
const sceneActions = useSceneStore((state) => {
|
||||
return state.actions;
|
||||
@@ -38,19 +43,14 @@ const App = ({ initialScene, width, height = 500, onSceneUpdated }: Props) => {
|
||||
const uiActions = useUiStateStore((state) => {
|
||||
return state.actions;
|
||||
});
|
||||
const isToolbarVisible = useUiStateStore((state) => {
|
||||
return state.isToolbarVisible;
|
||||
const interactionsEnabled = useUiStateStore((state) => {
|
||||
return state.interactionsEnabled;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
uiActions.setZoom(initialScene.zoom ?? 1);
|
||||
uiActions.setToolbarVisibility(initialScene.isToolbarVisible ?? true);
|
||||
}, [
|
||||
initialScene.zoom,
|
||||
initialScene.isToolbarVisible,
|
||||
sceneActions,
|
||||
uiActions
|
||||
]);
|
||||
uiActions.setInteractionsEnabled(interactionsEnabledProp);
|
||||
}, [initialScene.zoom, interactionsEnabledProp, sceneActions, uiActions]);
|
||||
|
||||
useEffect(() => {
|
||||
sceneActions.setScene(initialScene);
|
||||
@@ -68,8 +68,8 @@ const App = ({ initialScene, width, height = 500, onSceneUpdated }: Props) => {
|
||||
}}
|
||||
>
|
||||
<Renderer />
|
||||
{isToolbarVisible && <ItemControlsManager />}
|
||||
<ToolMenu />
|
||||
<ItemControlsManager />
|
||||
{interactionsEnabled && <ToolMenu />}
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -18,6 +18,9 @@ export const Renderer = () => {
|
||||
const scene = useSceneStore(({ nodes, connectors, groups }) => {
|
||||
return { nodes, connectors, groups };
|
||||
});
|
||||
const interactionsEnabled = useUiStateStore((state) => {
|
||||
return state.interactionsEnabled;
|
||||
});
|
||||
const icons = useSceneStore((state) => {
|
||||
return state.icons;
|
||||
});
|
||||
@@ -36,7 +39,10 @@ export const Renderer = () => {
|
||||
const { setRendererSize } = useUiStateStore((state) => {
|
||||
return state.actions;
|
||||
});
|
||||
const { setElement } = useInteractionManager();
|
||||
const {
|
||||
setElement: setInteractionsElement,
|
||||
setIsEnabled: setInteractionsEnabled
|
||||
} = useInteractionManager();
|
||||
const { observe, disconnect, size: rendererSize } = useResizeObserver();
|
||||
|
||||
const getNodesFromIds = useCallback(
|
||||
@@ -58,12 +64,16 @@ export const Renderer = () => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
observe(containerRef.current);
|
||||
setElement(containerRef.current);
|
||||
setInteractionsElement(containerRef.current);
|
||||
|
||||
return () => {
|
||||
disconnect();
|
||||
};
|
||||
}, [setElement, observe, disconnect]);
|
||||
}, [setInteractionsElement, observe, disconnect]);
|
||||
|
||||
useEffect(() => {
|
||||
setInteractionsEnabled(interactionsEnabled);
|
||||
}, [interactionsEnabled, setInteractionsEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
setRendererSize(rendererSize);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { produce } from 'immer';
|
||||
import { useSceneStore } from 'src/stores/sceneStore';
|
||||
import { useUiStateStore } from 'src/stores/uiStateStore';
|
||||
@@ -18,6 +18,8 @@ const reducers: { [k in string]: InteractionReducer } = {
|
||||
|
||||
export const useInteractionManager = () => {
|
||||
const rendererRef = useRef<HTMLElement>();
|
||||
const [isEnabled, setIsEnabled] = useState(true);
|
||||
const destroyListeners = useRef<() => void>();
|
||||
const mode = useUiStateStore((state) => {
|
||||
return state.mode;
|
||||
});
|
||||
@@ -140,8 +142,12 @@ export const useInteractionManager = () => {
|
||||
]
|
||||
);
|
||||
|
||||
// TODO: Needs optimisation, listeners are added / removed every time the mouse position changes. Very intensive.
|
||||
useEffect(() => {
|
||||
if (!rendererRef.current) return;
|
||||
if (!rendererRef.current || !isEnabled) {
|
||||
destroyListeners.current?.();
|
||||
return;
|
||||
}
|
||||
|
||||
const el = rendererRef.current;
|
||||
|
||||
@@ -149,18 +155,21 @@ export const useInteractionManager = () => {
|
||||
el.addEventListener('mousedown', onMouseEvent);
|
||||
el.addEventListener('mouseup', onMouseEvent);
|
||||
|
||||
return () => {
|
||||
destroyListeners.current = () => {
|
||||
el.removeEventListener('mousemove', onMouseEvent);
|
||||
el.removeEventListener('mousedown', onMouseEvent);
|
||||
el.removeEventListener('mouseup', onMouseEvent);
|
||||
};
|
||||
}, [onMouseEvent]);
|
||||
|
||||
return destroyListeners.current;
|
||||
}, [onMouseEvent, isEnabled]);
|
||||
|
||||
const setElement = useCallback((element: HTMLElement) => {
|
||||
rendererRef.current = element;
|
||||
}, []);
|
||||
|
||||
return {
|
||||
setElement
|
||||
setElement,
|
||||
setIsEnabled
|
||||
};
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ type UiStateStore = UiState & Actions;
|
||||
const initialState = () => {
|
||||
return createStore<UiStateStore>((set, get) => {
|
||||
return {
|
||||
isToolbarVisible: true,
|
||||
interactionsEnabled: true,
|
||||
mode: {
|
||||
type: 'CURSOR',
|
||||
showCursor: true,
|
||||
@@ -61,8 +61,16 @@ const initialState = () => {
|
||||
setRendererSize: (rendererSize) => {
|
||||
set({ rendererSize });
|
||||
},
|
||||
setToolbarVisibility: (visible) => {
|
||||
set({ isToolbarVisible: visible });
|
||||
setInteractionsEnabled: (enabled) => {
|
||||
set({ interactionsEnabled: enabled });
|
||||
|
||||
if (!enabled) {
|
||||
set({ mode: { type: 'INTERACTIONS_DISABLED', showCursor: false } });
|
||||
} else {
|
||||
set({
|
||||
mode: { type: 'CURSOR', showCursor: true, mousedown: null }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,6 +32,11 @@ export interface Mouse {
|
||||
}
|
||||
|
||||
// Begin mode types
|
||||
export interface InteractionsDisabled {
|
||||
type: 'INTERACTIONS_DISABLED';
|
||||
showCursor: boolean;
|
||||
}
|
||||
|
||||
export interface CursorMode {
|
||||
type: 'CURSOR';
|
||||
showCursor: boolean;
|
||||
@@ -63,7 +68,12 @@ export interface DragItemsMode {
|
||||
items: SceneItem[];
|
||||
}
|
||||
|
||||
export type Mode = CursorMode | PanMode | DragItemsMode | LassoMode;
|
||||
export type Mode =
|
||||
| InteractionsDisabled
|
||||
| CursorMode
|
||||
| PanMode
|
||||
| DragItemsMode
|
||||
| LassoMode;
|
||||
// End mode types
|
||||
|
||||
export type ContextMenu =
|
||||
@@ -80,7 +90,7 @@ export interface Scroll {
|
||||
}
|
||||
|
||||
export interface UiState {
|
||||
isToolbarVisible: boolean;
|
||||
interactionsEnabled: boolean;
|
||||
mode: Mode;
|
||||
itemControls: ItemControls;
|
||||
contextMenu: ContextMenu;
|
||||
@@ -92,7 +102,6 @@ export interface UiState {
|
||||
|
||||
export interface UiStateActions {
|
||||
setMode: (mode: Mode) => void;
|
||||
setToolbarVisibility: (visible: boolean) => void;
|
||||
incrementZoom: () => void;
|
||||
decrementZoom: () => void;
|
||||
setZoom: (zoom: number) => void;
|
||||
@@ -101,4 +110,5 @@ export interface UiStateActions {
|
||||
setContextMenu: (contextMenu: ContextMenu) => void;
|
||||
setMouse: (mouse: Mouse) => void;
|
||||
setRendererSize: (rendererSize: Size) => void;
|
||||
setInteractionsEnabled: (enabled: boolean) => void;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user