From 6bb541a33f31b09e819d68367201b04fabf0030a Mon Sep 17 00:00:00 2001 From: Luke De Feo Date: Thu, 24 Nov 2022 09:23:16 -0800 Subject: [PATCH] Group app wide ui state into one object Summary: Should be a bit easier to see what UI state we are holding at the plugin instance level Reviewed By: lblasa Differential Revision: D41498272 fbshipit-source-id: 6d88086766efd9c39f71be7e2ce32c5058494c96 --- .../public/ui-debugger/components/Tree.tsx | 28 +++++++------- .../components/Visualization2D.tsx | 37 +++++++++++-------- .../public/ui-debugger/components/main.tsx | 4 +- .../components/util/UIDebuggerMenuItem.tsx | 4 +- desktop/plugins/public/ui-debugger/index.tsx | 29 +++++++-------- 5 files changed, 52 insertions(+), 50 deletions(-) diff --git a/desktop/plugins/public/ui-debugger/components/Tree.tsx b/desktop/plugins/public/ui-debugger/components/Tree.tsx index 9d0ed7504..18f042e62 100644 --- a/desktop/plugins/public/ui-debugger/components/Tree.tsx +++ b/desktop/plugins/public/ui-debugger/components/Tree.tsx @@ -40,17 +40,17 @@ export function Tree(props: { onSelectNode: (id: Id) => void; }) { const instance = usePlugin(plugin); - const expandedItems = useValue(instance.treeState).expandedNodes; - const focused = useValue(instance.focusedNode); + const expandedItems = useValue(instance.uiState.treeState).expandedNodes; + const focused = useValue(instance.uiState.focusedNode); const items = useMemo( () => toComplexTree(focused || props.rootId, props.nodes), [focused, props.nodes, props.rootId], ); - const hoveredNodes = useValue(instance.hoveredNodes); + const hoveredNodes = useValue(instance.uiState.hoveredNodes); const treeEnvRef = useRef(); - const searchTerm = useValue(instance.searchTerm); + const searchTerm = useValue(instance.uiState.searchTerm); useEffect(() => { //this makes the keyboard arrow controls work always, even when using the visualiser @@ -75,15 +75,15 @@ export function Tree(props: { }, }} onFocusItem={(item) => { - instance.hoveredNodes.set([item.index]); + instance.uiState.hoveredNodes.set([item.index]); }} onExpandItem={(item) => { - instance.treeState.update((draft) => { + instance.uiState.treeState.update((draft) => { draft.expandedNodes.push(item.index); }); }} onCollapseItem={(item) => - instance.treeState.update((draft) => { + instance.uiState.treeState.update((draft) => { draft.expandedNodes = draft.expandedNodes.filter( (expandedItemIndex) => expandedItemIndex !== item.index, ); @@ -109,8 +109,8 @@ export function Tree(props: { }, onMouseOver: () => { - if (!instance.isContextMenuOpen.get()) { - instance.hoveredNodes.set([item.index]); + if (!instance.uiState.isContextMenuOpen.get()) { + instance.uiState.hoveredNodes.set([item.index]); } }, }), @@ -200,21 +200,21 @@ type ContextMenuProps = {node: UINode; id: Id; title: string}; const ContextMenu: React.FC = ({id, title, children}) => { const instance = usePlugin(plugin); - const focusedNode = instance.focusedNode.get(); + const focusedNode = instance.uiState.focusedNode.get(); return ( { - instance.isContextMenuOpen.set(visible); + instance.uiState.isContextMenuOpen.set(visible); }} overlay={() => ( - {focusedNode !== head(instance.hoveredNodes.get()) && ( + {focusedNode !== head(instance.uiState.hoveredNodes.get()) && ( { - instance.focusedNode.set(id); + instance.uiState.focusedNode.set(id); }} /> )} @@ -224,7 +224,7 @@ const ContextMenu: React.FC = ({id, title, children}) => { key="remove-focus" text="Remove focus" onClick={() => { - instance.focusedNode.set(undefined); + instance.uiState.focusedNode.set(undefined); }} /> )} diff --git a/desktop/plugins/public/ui-debugger/components/Visualization2D.tsx b/desktop/plugins/public/ui-debugger/components/Visualization2D.tsx index 46b2066a1..e7309d4c6 100644 --- a/desktop/plugins/public/ui-debugger/components/Visualization2D.tsx +++ b/desktop/plugins/public/ui-debugger/components/Visualization2D.tsx @@ -29,7 +29,7 @@ export const Visualization2D: React.FC< const instance = usePlugin(plugin); const snapshot = useValue(instance.snapshot); - const focusedNodeId = useValue(instance.focusedNode); + const focusedNodeId = useValue(instance.uiState.focusedNode); const focusState = useMemo(() => { const rootNode = toNestedNode(rootId, nodes); @@ -40,7 +40,7 @@ export const Visualization2D: React.FC< const mouseListener = throttle((ev: MouseEvent) => { const domRect = rootNodeRef.current?.getBoundingClientRect(); - if (!focusState || !domRect || instance.isContextMenuOpen.get()) { + if (!focusState || !domRect || instance.uiState.isContextMenuOpen.get()) { return; } const rawMouse = {x: ev.clientX, y: ev.clientY}; @@ -63,9 +63,9 @@ export const Visualization2D: React.FC< if ( hitNodes.length > 0 && - !isEqual(hitNodes, instance.hoveredNodes.get()) + !isEqual(hitNodes, instance.uiState.hoveredNodes.get()) ) { - instance.hoveredNodes.set(hitNodes); + instance.uiState.hoveredNodes.set(hitNodes); } }, MouseThrottle); window.addEventListener('mousemove', mouseListener); @@ -73,7 +73,12 @@ export const Visualization2D: React.FC< return () => { window.removeEventListener('mousemove', mouseListener); }; - }, [instance.hoveredNodes, focusState, nodes, instance.isContextMenuOpen]); + }, [ + instance.uiState.hoveredNodes, + focusState, + nodes, + instance.uiState.isContextMenuOpen, + ]); if (!focusState) { return null; @@ -94,8 +99,8 @@ export const Visualization2D: React.FC< onMouseLeave={(e) => { e.stopPropagation(); //the context menu triggers this callback but we dont want to remove hover effect - if (!instance.isContextMenuOpen.get()) { - instance.hoveredNodes.set([]); + if (!instance.uiState.isContextMenuOpen.get()) { + instance.uiState.hoveredNodes.set([]); } }} style={{ @@ -169,11 +174,11 @@ function Visualization2DNode({ setIsHovered(head(newValue) === node.id); } }; - instance.hoveredNodes.subscribe(listener); + instance.uiState.hoveredNodes.subscribe(listener); return () => { - instance.hoveredNodes.unsubscribe(listener); + instance.uiState.hoveredNodes.unsubscribe(listener); }; - }, [instance.hoveredNodes, node.id]); + }, [instance.uiState.hoveredNodes, node.id]); const isSelected = selectedNode === node.id; @@ -224,7 +229,7 @@ function Visualization2DNode({ onClick={(e) => { e.stopPropagation(); - const hoveredNodes = instance.hoveredNodes.get(); + const hoveredNodes = instance.uiState.hoveredNodes.get(); if (hoveredNodes[0] === selectedNode) { onSelectNode(undefined); } else { @@ -241,15 +246,15 @@ function Visualization2DNode({ const ContextMenu: React.FC<{nodes: Map}> = ({children}) => { const instance = usePlugin(plugin); - const focusedNodeId = useValue(instance.focusedNode); - const hoveredNodeId = head(useValue(instance.hoveredNodes)); + const focusedNodeId = useValue(instance.uiState.focusedNode); + const hoveredNodeId = head(useValue(instance.uiState.hoveredNodes)); const nodes = useValue(instance.nodes); const hoveredNode = hoveredNodeId ? nodes.get(hoveredNodeId) : null; return ( { - instance.isContextMenuOpen.set(open); + instance.uiState.isContextMenuOpen.set(open); }} trigger={['contextMenu']} overlay={() => { @@ -260,7 +265,7 @@ const ContextMenu: React.FC<{nodes: Map}> = ({children}) => { key="focus" text={`Focus ${hoveredNode?.name}`} onClick={() => { - instance.focusedNode.set(hoveredNode?.id); + instance.uiState.focusedNode.set(hoveredNode?.id); }} /> )} @@ -269,7 +274,7 @@ const ContextMenu: React.FC<{nodes: Map}> = ({children}) => { key="remove-focus" text="Remove focus" onClick={() => { - instance.focusedNode.set(undefined); + instance.uiState.focusedNode.set(undefined); }} /> )} diff --git a/desktop/plugins/public/ui-debugger/components/main.tsx b/desktop/plugins/public/ui-debugger/components/main.tsx index 80847c52f..17c88141a 100644 --- a/desktop/plugins/public/ui-debugger/components/main.tsx +++ b/desktop/plugins/public/ui-debugger/components/main.tsx @@ -30,7 +30,7 @@ export function Component() { useHotkeys('ctrl+i', () => setShowPerfStats((show) => !show)); - const searchTerm = useValue(instance.searchTerm); + const searchTerm = useValue(instance.uiState.searchTerm); const {ctrlPressed} = useKeyboardModifiers(); function renderSidebar( @@ -55,7 +55,7 @@ export function Component() { instance.searchTerm.set(e.target.value)} + onChange={(e) => instance.uiState.searchTerm.set(e.target.value)} /> = ({text, onClick}) => { const instance = usePlugin(plugin); - const isMenuOpen = useValue(instance.isContextMenuOpen); + const isMenuOpen = useValue(instance.uiState.isContextMenuOpen); /** * The menu is not a controlled component and seems to be a bit slow to close when user clicks on it. * React may rerender the menu before it has time to close resulting in seeing an incorrect context menu for a frame. @@ -37,7 +37,7 @@ export const UIDebuggerMenuItem: React.FC<{ { onClick(); - instance.isContextMenuOpen.set(false); + instance.uiState.isContextMenuOpen.set(false); }}> {text} diff --git a/desktop/plugins/public/ui-debugger/index.tsx b/desktop/plugins/public/ui-debugger/index.tsx index 5bb3e345f..af5796227 100644 --- a/desktop/plugins/public/ui-debugger/index.tsx +++ b/desktop/plugins/public/ui-debugger/index.tsx @@ -23,7 +23,6 @@ import './node_modules/react-complex-tree/lib/style.css'; export function plugin(client: PluginClient) { const rootId = createState(undefined); const metadata = createState>(new Map()); - const searchTerm = createState(''); client.onMessage('init', (event) => { rootId.set(event.rootId); @@ -48,21 +47,23 @@ export function plugin(client: PluginClient) { perfEvents.append(event); }); - //used to disabled hover effects which cause rerenders and mess up the existing context menu - const isContextMenuOpen = createState(false); - - const focusedNode = createState(undefined); - const nodes = createState>(new Map()); const snapshot = createState<{nodeId: Id; base64Image: Snapshot} | null>( null, ); - const treeState = createState({expandedNodes: []}); + const uiState = { + //used to disabled hover effects which cause rerenders and mess up the existing context menu + isContextMenuOpen: createState(false), - //The reason for the array as that user could be hovering multiple overlapping nodes at once in the visualiser. - //The nodes are sorted by area since you most likely want to select the smallest node under your cursor - const hoveredNodes = createState([]); + //The reason for the array as that user could be hovering multiple overlapping nodes at once in the visualiser. + //The nodes are sorted by area since you most likely want to select the smallest node under your cursor + hoveredNodes: createState([]), + + searchTerm: createState(''), + focusedNode: createState(undefined), + treeState: createState({expandedNodes: []}), + }; client.onMessage('coordinateUpdate', (event) => { nodes.update((draft) => { @@ -88,7 +89,7 @@ export function plugin(client: PluginClient) { }); }); - treeState.update((draft) => { + uiState.treeState.update((draft) => { for (const node of event.nodes) { if (!seenNodes.has(node.id)) { draft.expandedNodes.push(node.id); @@ -111,15 +112,11 @@ export function plugin(client: PluginClient) { return { rootId, - isContextMenuOpen, + uiState, nodes, metadata, - focusedNode, snapshot, - hoveredNodes, perfEvents, - treeState, - searchTerm, }; }