From 69de9bc92d254f4abce8080459966cbc2ae1ca3f Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Thu, 15 Apr 2021 07:46:28 -0700 Subject: [PATCH] Initial move to flipper-plugin Summary: This diff moves the core of ElementsInspector to flipper-plugin and decouples it from legacy design system and Electron, without any significant improvements or API changes yet, which will follow later. Colors and docs will be added later in this stack. Reviewed By: passy Differential Revision: D27660300 fbshipit-source-id: 96abfa3b3174fa852cf04ae119c23c3d629fee74 --- desktop/app/src/fb-stubs/IDEFileResolver.tsx | 12 +- desktop/app/src/index.tsx | 23 ++- .../elements-inspector/ElementFramework.tsx | 13 ++ .../elements-inspector/Visualizer.tsx | 6 +- .../components/elements-inspector/sidebar.tsx | 4 +- desktop/app/src/ui/index.tsx | 11 -- .../flipper-plugin/src/__tests__/api.node.tsx | 8 + desktop/flipper-plugin/src/index.ts | 11 ++ desktop/flipper-plugin/src/ui/Layout.tsx | 51 +++--- .../elements-inspector/ElementsInspector.tsx | 10 +- .../src/ui}/elements-inspector/elements.tsx | 160 ++++++++++-------- .../layout/MultipleSelectionSection.tsx | 3 +- docs/extending/flipper-plugin.mdx | 8 + 13 files changed, 183 insertions(+), 137 deletions(-) create mode 100644 desktop/app/src/ui/components/elements-inspector/ElementFramework.tsx rename desktop/{app/src/ui/components => flipper-plugin/src/ui}/elements-inspector/ElementsInspector.tsx (91%) rename desktop/{app/src/ui/components => flipper-plugin/src/ui}/elements-inspector/elements.tsx (85%) diff --git a/desktop/app/src/fb-stubs/IDEFileResolver.tsx b/desktop/app/src/fb-stubs/IDEFileResolver.tsx index bda4cd339..1c5b3c8dc 100644 --- a/desktop/app/src/fb-stubs/IDEFileResolver.tsx +++ b/desktop/app/src/fb-stubs/IDEFileResolver.tsx @@ -7,10 +7,8 @@ * @format */ -import { - ElementFramework, - Element, -} from '../ui/components/elements-inspector/ElementsInspector'; +import {ElementFramework} from '../ui/components/elements-inspector/ElementFramework'; +import {ElementsInspectorElement} from 'flipper-plugin'; export enum IDEType { 'DIFFUSION', @@ -60,13 +58,15 @@ export abstract class IDEFileResolver { } static isElementFromFramework( - _node: Element, + _node: ElementsInspectorElement, _framework: ElementFramework, ): boolean { throw new Error('Method not implemented.'); } - static isElementFromSupportedFramework(_node: Element): boolean { + static isElementFromSupportedFramework( + _node: ElementsInspectorElement, + ): boolean { throw new Error('Method not implemented.'); } } diff --git a/desktop/app/src/index.tsx b/desktop/app/src/index.tsx index 913649221..0493b82a0 100644 --- a/desktop/app/src/index.tsx +++ b/desktop/app/src/index.tsx @@ -173,20 +173,17 @@ export { } from './ui/components/searchable/SearchableTable'; export {default as SearchableTable_immutable} from './ui/components/searchable/SearchableTable_immutable'; export { - ElementID, - ElementData, - ElementFramework, - ElementAttribute, - Element, - ElementSearchResultSet, + ElementsInspector, + ElementsInspectorElement as Element, + // TODO: clean up or create namespace ElementsInspectorProps, -} from './ui/components/elements-inspector/ElementsInspector'; -export { - Elements, - ElementsConstants, -} from './ui/components/elements-inspector/elements'; -export {ContextMenuExtension} from './ui/components/elements-inspector/elements'; -export {default as ElementsInspector} from './ui/components/elements-inspector/ElementsInspector'; + ElementExtraInfo, + ElementAttribute, + ElementData, + ElementSearchResultSet, + ElementID, +} from 'flipper-plugin'; +export {ElementFramework} from './ui/components/elements-inspector/ElementFramework'; export {InspectorSidebar} from './ui/components/elements-inspector/sidebar'; export {default as Sheet} from './ui/components/Sheet'; export {default as FileSelector} from './ui/components/FileSelector'; diff --git a/desktop/app/src/ui/components/elements-inspector/ElementFramework.tsx b/desktop/app/src/ui/components/elements-inspector/ElementFramework.tsx new file mode 100644 index 000000000..0f282382f --- /dev/null +++ b/desktop/app/src/ui/components/elements-inspector/ElementFramework.tsx @@ -0,0 +1,13 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +export enum ElementFramework { + 'LITHO', + 'CK', +} diff --git a/desktop/app/src/ui/components/elements-inspector/Visualizer.tsx b/desktop/app/src/ui/components/elements-inspector/Visualizer.tsx index 02fd4b399..95bbec386 100644 --- a/desktop/app/src/ui/components/elements-inspector/Visualizer.tsx +++ b/desktop/app/src/ui/components/elements-inspector/Visualizer.tsx @@ -9,18 +9,18 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import {Element} from './ElementsInspector'; +import {ElementsInspectorElement} from 'flipper-plugin'; import styled from '@emotion/styled'; export function VisualizerPortal(props: { container: HTMLElement; highlightedElement: string | null; - elements: {[key: string]: Element}; + elements: {[key: string]: ElementsInspectorElement}; screenshotURL: string; screenDimensions: {width: number; height: number}; }) { props.container.style.margin = '0'; - const element: Element | null | '' = + const element: ElementsInspectorElement | null | '' = props.highlightedElement && props.elements[props.highlightedElement]; const position = diff --git a/desktop/app/src/ui/components/elements-inspector/sidebar.tsx b/desktop/app/src/ui/components/elements-inspector/sidebar.tsx index cd12b1f4d..04bf3eca9 100644 --- a/desktop/app/src/ui/components/elements-inspector/sidebar.tsx +++ b/desktop/app/src/ui/components/elements-inspector/sidebar.tsx @@ -7,7 +7,7 @@ * @format */ -import {Element} from './ElementsInspector'; +import {ElementsInspectorElement} from 'flipper-plugin'; import {PluginClient} from '../../../plugin'; import Client from '../../../Client'; import {Logger} from '../../../fb-interfaces/Logger'; @@ -76,7 +76,7 @@ class InspectorSidebarSection extends Component { } type Props = { - element: Element | undefined | null; + element: ElementsInspectorElement | undefined | null; tooltips?: Object; onValueChanged: OnValueChanged | undefined | null; client: PluginClient; diff --git a/desktop/app/src/ui/index.tsx b/desktop/app/src/ui/index.tsx index 48e4f5e46..69a363b3f 100644 --- a/desktop/app/src/ui/index.tsx +++ b/desktop/app/src/ui/index.tsx @@ -141,17 +141,6 @@ export { export {default as SearchableTable_immutable} from './components/searchable/SearchableTable_immutable'; export {SearchableProps} from './components/searchable/Searchable'; -export { - ElementID, - ElementData, - ElementAttribute, - Element, - ElementSearchResultSet, - ElementsInspectorProps, -} from './components/elements-inspector/ElementsInspector'; -export {Elements} from './components/elements-inspector/elements'; -export {ContextMenuExtension} from './components/elements-inspector/elements'; -export {default as ElementsInspector} from './components/elements-inspector/ElementsInspector'; export {InspectorSidebar} from './components/elements-inspector/sidebar'; export {VisualizerPortal} from './components/elements-inspector/Visualizer'; diff --git a/desktop/flipper-plugin/src/__tests__/api.node.tsx b/desktop/flipper-plugin/src/__tests__/api.node.tsx index f99f0fa32..76f1d265e 100644 --- a/desktop/flipper-plugin/src/__tests__/api.node.tsx +++ b/desktop/flipper-plugin/src/__tests__/api.node.tsx @@ -34,6 +34,7 @@ test('Correct top level API exposed', () => { "DataSource", "DataTable", "DetailSidebar", + "ElementsInspector", "Layout", "MarkerTimeline", "NUX", @@ -72,6 +73,13 @@ test('Correct top level API exposed', () => { "DevicePluginClient", "DeviceType", "Draft", + "ElementAttribute", + "ElementData", + "ElementExtraInfo", + "ElementID", + "ElementSearchResultSet", + "ElementsInspectorElement", + "ElementsInspectorProps", "FlipperLib", "HighlightManager", "Idler", diff --git a/desktop/flipper-plugin/src/index.ts b/desktop/flipper-plugin/src/index.ts index 088b902d2..72d960219 100644 --- a/desktop/flipper-plugin/src/index.ts +++ b/desktop/flipper-plugin/src/index.ts @@ -102,6 +102,17 @@ export { export {MarkerTimeline} from './ui/MarkerTimeline'; export {ManagedDataInspector as DataInspector} from './ui/data-inspector/ManagedDataInspector'; +export { + ElementsInspector, + Element as ElementsInspectorElement, + // TODO: clean up or create namespace + ElementsInspectorProps, + ElementExtraInfo, + ElementAttribute, + ElementData, + ElementSearchResultSet, + ElementID, +} from './ui/elements-inspector/ElementsInspector'; export {useMemoize} from './utils/useMemoize'; // It's not ideal that this exists in flipper-plugin sources directly, diff --git a/desktop/flipper-plugin/src/ui/Layout.tsx b/desktop/flipper-plugin/src/ui/Layout.tsx index be1838de5..380f1bbe8 100644 --- a/desktop/flipper-plugin/src/ui/Layout.tsx +++ b/desktop/flipper-plugin/src/ui/Layout.tsx @@ -7,7 +7,7 @@ * @format */ -import React, {CSSProperties} from 'react'; +import React, {CSSProperties, forwardRef} from 'react'; import styled from '@emotion/styled'; import { normalizePadding, @@ -110,28 +110,33 @@ const ScrollChild = styled(Container)<{axis?: ScrollAxis}>(({axis}) => ({ type ScrollAxis = 'x' | 'y' | 'both'; -const ScrollContainer = ({ - children, - horizontal, - vertical, - padv, - padh, - pad, - ...rest -}: React.HTMLAttributes & { - horizontal?: boolean; - vertical?: boolean; -} & PaddingProps) => { - const axis = - horizontal && !vertical ? 'x' : !horizontal && vertical ? 'y' : 'both'; - return ( - - - {children} - - - ) as any; -}; +const ScrollContainer = forwardRef( + ( + { + children, + horizontal, + vertical, + padv, + padh, + pad, + ...rest + }: React.HTMLAttributes & { + horizontal?: boolean; + vertical?: boolean; + } & PaddingProps, + ref: React.ForwardedRef, + ) => { + const axis = + horizontal && !vertical ? 'x' : !horizontal && vertical ? 'y' : 'both'; + return ( + + + {children} + + + ) as any; + }, +); type SplitLayoutProps = { /** diff --git a/desktop/app/src/ui/components/elements-inspector/ElementsInspector.tsx b/desktop/flipper-plugin/src/ui/elements-inspector/ElementsInspector.tsx similarity index 91% rename from desktop/app/src/ui/components/elements-inspector/ElementsInspector.tsx rename to desktop/flipper-plugin/src/ui/elements-inspector/ElementsInspector.tsx index 5251c0d58..591751477 100644 --- a/desktop/app/src/ui/components/elements-inspector/ElementsInspector.tsx +++ b/desktop/flipper-plugin/src/ui/elements-inspector/ElementsInspector.tsx @@ -8,8 +8,7 @@ */ import {Component} from 'react'; -import {Elements, DecorateRow} from './elements'; -import {ContextMenuExtension} from '../../../ui'; +import {Elements, DecorateRow, ContextMenuExtension} from './elements'; import React from 'react'; export type ElementID = string; @@ -32,11 +31,6 @@ export type ElementData = { }; }; -export enum ElementFramework { - 'LITHO', - 'CK', -} - export type ElementAttribute = { name: string; value: string; @@ -80,7 +74,7 @@ export type ElementsInspectorProps = { decorateRow?: DecorateRow; }; -export default class ElementsInspector extends Component { +export class ElementsInspector extends Component { static defaultProps = { alternateRowColor: true, }; diff --git a/desktop/app/src/ui/components/elements-inspector/elements.tsx b/desktop/flipper-plugin/src/ui/elements-inspector/elements.tsx similarity index 85% rename from desktop/app/src/ui/components/elements-inspector/elements.tsx rename to desktop/flipper-plugin/src/ui/elements-inspector/elements.tsx index 37b140f58..21fcf20a1 100644 --- a/desktop/app/src/ui/components/elements-inspector/elements.tsx +++ b/desktop/flipper-plugin/src/ui/elements-inspector/elements.tsx @@ -7,17 +7,17 @@ * @format */ +import {Dropdown, Menu, Typography} from 'antd'; import {ElementID, Element, ElementSearchResultSet} from './ElementsInspector'; -import ContextMenu from '../ContextMenu'; import {PureComponent, ReactElement} from 'react'; -import FlexRow from '../FlexRow'; -import Glyph from '../Glyph'; -import {colors} from '../colors'; -import Text from '../Text'; import styled from '@emotion/styled'; -import {clipboard, MenuItemConstructorOptions} from 'electron'; import React, {MouseEvent, KeyboardEvent} from 'react'; -import {Scrollable} from '../..'; +import {theme} from '../theme'; +import {Layout} from '../Layout'; +import {tryGetFlipperLibImplementation} from 'flipper-plugin/src/plugin/FlipperLib'; +import {DownOutlined, RightOutlined} from '@ant-design/icons'; + +const {Text} = Typography; export const ElementsConstants = { rowHeight: 23, @@ -30,13 +30,13 @@ const backgroundColor = (props: { even: boolean; }) => { if (props.selected) { - return colors.macOSTitleBarIconSelected; + return '#4d84f5'; } else if (props.isQueryMatch) { - return colors.purpleLight; + return '#4d84f5'; } else if (props.focused) { return '#00CF52'; } else if (props.even) { - return colors.light02; + return '#f6f7f9'; } else { return ''; } @@ -44,7 +44,7 @@ const backgroundColor = (props: { const backgroundColorHover = (props: {selected: boolean; focused: boolean}) => { if (props.selected) { - return colors.macOSTitleBarIconSelected; + return '#4d84f5'; } else if (props.focused) { return '#00CF52'; } else { @@ -52,11 +52,11 @@ const backgroundColorHover = (props: {selected: boolean; focused: boolean}) => { } }; -const ElementsRowContainer = styled(ContextMenu)((props) => ({ +const ElementsRowContainer = styled(Layout.Horizontal)((props) => ({ flexDirection: 'row', alignItems: 'center', backgroundColor: backgroundColor(props), - color: props.selected || props.focused ? colors.white : colors.grapeDark3, + color: props.selected || props.focused ? theme.backgroundDefault : '#58409b', flexShrink: 0, flexWrap: 'nowrap', height: ElementsConstants.rowHeight, @@ -65,7 +65,10 @@ const ElementsRowContainer = styled(ContextMenu)((props) => ({ position: 'relative', '& *': { - color: props.selected || props.focused ? `${colors.white} !important` : '', + color: + props.selected || props.focused + ? `${theme.backgroundDefault} !important` + : '', }, '&:hover': { @@ -74,7 +77,7 @@ const ElementsRowContainer = styled(ContextMenu)((props) => ({ })); ElementsRowContainer.displayName = 'Elements:ElementsRowContainer'; -const ElementsRowDecoration = styled(FlexRow)({ +const ElementsRowDecoration = styled(Layout.Horizontal)({ flexShrink: 0, justifyContent: 'flex-end', alignItems: 'center', @@ -86,7 +89,7 @@ const ElementsRowDecoration = styled(FlexRow)({ ElementsRowDecoration.displayName = 'Elements:ElementsRowDecoration'; const ElementsLine = styled.div<{childrenCount: number}>((props) => ({ - backgroundColor: colors.light20, + backgroundColor: '#bec2c9', height: props.childrenCount * ElementsConstants.rowHeight - 4, position: 'absolute', right: 3, @@ -109,11 +112,13 @@ const NoShrinkText = styled(Text)({ flexWrap: 'nowrap', overflow: 'hidden', fontWeight: 400, + font: theme.monospace.fontFamily, + fontSize: theme.monospace.fontSize, }); NoShrinkText.displayName = 'Elements:NoShrinkText'; const ElementsRowAttributeContainer = styled(NoShrinkText)({ - color: colors.dark80, + color: '#333333', fontWeight: 300, marginLeft: 5, }); @@ -121,12 +126,12 @@ ElementsRowAttributeContainer.displayName = 'Elements:ElementsRowAttributeContainer'; const ElementsRowAttributeKey = styled.span({ - color: colors.tomato, + color: '#fb724b', }); ElementsRowAttributeKey.displayName = 'Elements:ElementsRowAttributeKey'; const ElementsRowAttributeValue = styled.span({ - color: colors.slateDark3, + color: '#688694', }); ElementsRowAttributeValue.displayName = 'Elements:ElementsRowAttributeValue'; @@ -137,8 +142,8 @@ class PartialHighlight extends PureComponent<{ content: string; }> { static HighlightedText = styled.span<{selected: boolean}>((props) => ({ - backgroundColor: colors.lemon, - color: props.selected ? `${colors.grapeDark3} !important` : 'auto', + backgroundColor: '#fcd872', + color: props.selected ? `${'#58409b'} !important` : 'auto', })); render() { @@ -180,7 +185,7 @@ class ElementsRowAttribute extends PureComponent<{ render() { const {name, value, matchingSearchQuery, selected} = this.props; return ( - + {name}= { this.state = {hovered: false}; } - getContextMenu = (): Array => { + getContextMenu = () => { const {props} = this; - let items: Array = [ - { - type: 'separator', - }, + let items = [ { label: 'Copy', click: () => { - clipboard.writeText(props.onCopyExpandedTree(props.element, 0)); + tryGetFlipperLibImplementation()?.writeTextToClipboard( + props.onCopyExpandedTree(props.element, 0), + ); }, }, { label: 'Copy expanded child elements', click: () => - clipboard.writeText(props.onCopyExpandedTree(props.element, 255)), + tryGetFlipperLibImplementation()?.writeTextToClipboard( + props.onCopyExpandedTree(props.element, 255), + ), }, { label: props.element.expanded ? 'Collapse' : 'Expand', @@ -274,7 +280,7 @@ class ElementsRow extends PureComponent { return { label: `Copy ${o.name}`, click: () => { - clipboard.writeText(o.value); + tryGetFlipperLibImplementation()?.writeTextToClipboard(o.value); }, }; }), @@ -287,7 +293,15 @@ class ElementsRow extends PureComponent { }); } - return items; + return ( + + {items.map(({label, click}) => ( + + {label} + + ))} + + ); }; onClick = () => { @@ -330,12 +344,15 @@ class ElementsRow extends PureComponent { let arrow; if (hasChildren) { arrow = ( - - + + {element.expanded ? : } ); } @@ -377,35 +394,38 @@ class ElementsRow extends PureComponent { } return ( - - - {line} - {arrow} - - - {decoration} - - - {attributes} - + overlay={this.getContextMenu} + trigger={['contextMenu']}> + + + {line} + {arrow} + + + {decoration} + + + {attributes} + + ); } } @@ -419,7 +439,7 @@ function containsKeyInSearchResults( const ElementsContainer = styled('div')({ display: 'table', - backgroundColor: colors.white, + backgroundColor: theme.backgroundDefault, minHeight: '100%', minWidth: '100%', }); @@ -568,7 +588,9 @@ export class Elements extends PureComponent { ) { e.stopPropagation(); e.preventDefault(); - clipboard.writeText(selectedElement.name); + tryGetFlipperLibImplementation()?.writeTextToClipboard( + selectedElement.name, + ); return; } @@ -735,11 +757,11 @@ export class Elements extends PureComponent { render() { return ( - + {this.state.flatElements.map(this.buildRow)} - + ); } } diff --git a/desktop/plugins/public/layout/MultipleSelectionSection.tsx b/desktop/plugins/public/layout/MultipleSelectionSection.tsx index c37bba360..d767f7484 100644 --- a/desktop/plugins/public/layout/MultipleSelectionSection.tsx +++ b/desktop/plugins/public/layout/MultipleSelectionSection.tsx @@ -11,7 +11,6 @@ import { FlexColumn, FlexBox, Element, - ElementsConstants, ElementID, ElementsInspector, Glyph, @@ -21,7 +20,7 @@ import { import React, {memo, useState} from 'react'; const MultipleSelectorSectionContainer = styled(FlexColumn)({ - maxHeight: 3 * ElementsConstants.rowHeight + 24, + maxHeight: 100, }); const MultipleSelectorSectionTitle = styled(FlexBox)({ diff --git a/docs/extending/flipper-plugin.mdx b/docs/extending/flipper-plugin.mdx index c8cd3e688..95bbb66d9 100644 --- a/docs/extending/flipper-plugin.mdx +++ b/docs/extending/flipper-plugin.mdx @@ -784,6 +784,14 @@ See `View > Flipper Style Guide` inside the Flipper application for more details ### DataInspector ### DataDescription ### MarkerTimeline +### ElementsInspector +### ElementAttribute +### ElementData +### ElementExtraInfo +### ElementID +### ElementSearchResultSet +### ElementsInspectorElement +### ElementsInspectorProps Coming soon.