diff --git a/desktop/plugins/public/ui-debugger/components/Tree.tsx b/desktop/plugins/public/ui-debugger/components/Tree.tsx index 95604fe9c..23c16ceb4 100644 --- a/desktop/plugins/public/ui-debugger/components/Tree.tsx +++ b/desktop/plugins/public/ui-debugger/components/Tree.tsx @@ -25,12 +25,12 @@ import { useValue, HighlightManager, HighlightProvider, - HighlightContext, useHighlighter, theme, } from 'flipper-plugin'; import {head} from 'lodash'; +import {Dropdown, Menu} from 'antd'; export function Tree(props: { rootId: Id; @@ -40,7 +40,12 @@ export function Tree(props: { }) { const instance = usePlugin(plugin); const expandedItems = useValue(instance.treeState).expandedNodes; - const items = useMemo(() => toComplexTree(props.nodes), [props.nodes]); + const focused = useValue(instance.focusedNode); + + const items = useMemo( + () => toComplexTree(focused || props.rootId, props.nodes), + [focused, props.nodes, props.rootId], + ); const hoveredNodes = useValue(instance.hoveredNodes); const treeEnvRef = useRef(); @@ -109,7 +114,7 @@ export function Tree(props: { }}> @@ -149,58 +154,116 @@ function renderItem({ context.isDraggingOver && 'rct-tree-item-li-dragging-over', context.isSearchMatching && 'rct-tree-item-li-search-match', )}> -
- {arrow} +
- + {arrow} +
+ +
-
+ + {children} ); } +type ContextMenuProps = {node: UINode; id: Id; title: string}; + +const ContextMenu: React.FC = ({id, title, children}) => { + const instance = usePlugin(plugin); + const focusedNode = instance.focusedNode.get(); + + return ( + ( + + {focusedNode !== head(instance.hoveredNodes.get()) && ( + { + instance.focusedNode.set(id); + }}> + Focus {title} + + )} + + {focusedNode && ( + { + instance.focusedNode.set(undefined); + }}> + Remove focus + + )} + + )} + trigger={['contextMenu']}> +
{children}
+
+ ); +}; + function HighlightedText(props: {text: string}) { const highlightManager: HighlightManager = useHighlighter(); return {highlightManager.render(props.text)}; } -function toComplexTree(nodes: Map): Record> { +const FakeNode: UINode = { + id: 'Fakeroot', + qualifiedName: 'Fakeroot', + name: 'Fakeroot', + children: [], + attributes: {}, + bounds: {x: 0, y: 0, height: 0, width: 0}, + tags: [], +}; + +function toComplexTree( + root: Id, + nodes: Map, +): Record> { const res: Record> = {}; for (const node of nodes.values()) { res[node.id] = { index: node.id, - canMove: false, - canRename: false, children: node.children, data: node, hasChildren: node.children.length > 0, }; } + + //the library doesnt render the root node so we insert a fake one which will never be rendered + //https://github.com/lukasbach/react-complex-tree/issues/42 + res[FakeNode.id] = { + index: FakeNode.id, + children: [root], + hasChildren: true, + data: FakeNode, + }; return res; } diff --git a/desktop/plugins/public/ui-debugger/index.tsx b/desktop/plugins/public/ui-debugger/index.tsx index 2cb1247e2..9f6fa540b 100644 --- a/desktop/plugins/public/ui-debugger/index.tsx +++ b/desktop/plugins/public/ui-debugger/index.tsx @@ -48,6 +48,8 @@ export function plugin(client: PluginClient) { perfEvents.append(event); }); + const focusedNode = createState(undefined); + const nodes = createState>(new Map()); const snapshot = createState<{nodeId: Id; base64Image: Snapshot} | null>( null, @@ -108,6 +110,7 @@ export function plugin(client: PluginClient) { rootId, nodes, metadata, + focusedNode, snapshot, hoveredNodes, perfEvents,