diff --git a/desktop/plugins/public/fresco/ImagesCacheOverview.tsx b/desktop/plugins/public/fresco/ImagesCacheOverview.tsx index d4b163ab7..4be7f49de 100644 --- a/desktop/plugins/public/fresco/ImagesCacheOverview.tsx +++ b/desktop/plugins/public/fresco/ImagesCacheOverview.tsx @@ -10,23 +10,22 @@ import {CacheInfo, ImageId, ImageData, ImagesList} from './api'; import {ImageEventWithId} from './index'; +import {styled, Layout, Toolbar, theme} from 'flipper-plugin'; import { - Toolbar, Button, - Spacer, - colors, - FlexBox, - FlexRow, - FlexColumn, - LoadingIndicator, - styled, - ToggleButton, - Text, -} from 'flipper'; + Switch, + Empty, + Skeleton, + Typography, + Image, + Row, + Col, + Badge, +} from 'antd'; import MultipleSelect from './MultipleSelect'; import {ImagesMap} from './ImagePool'; -import {clipboard} from 'electron'; -import React, {ChangeEvent, KeyboardEvent, PureComponent} from 'react'; +import React, {PureComponent} from 'react'; +import {DeleteFilled} from '@ant-design/icons'; function formatMB(bytes: number) { return Math.floor(bytes / (1024 * 1024)) + 'MB'; @@ -42,26 +41,16 @@ type ToggleProps = { toggled: boolean; }; -const ToolbarToggleButton = styled(ToggleButton)(() => ({ - alignSelf: 'center', - marginRight: 4, - minWidth: 30, -})); - -const ToggleLabel = styled(Text)(() => ({ - whiteSpace: 'nowrap', -})); - function Toggle(props: ToggleProps) { return ( <> - { props.onClick && props.onClick(!props.toggled); }} - toggled={props.toggled} + checked={props.toggled} /> - {props.label} + {props.label} ); } @@ -104,39 +93,11 @@ export default class ImagesCacheOverview extends PureComponent< size: 150, }; - static Container = styled(FlexColumn)({ - backgroundColor: colors.white, - }); - - static Content = styled(FlexColumn)({ - flex: 1, - overflow: 'auto', - }); - - static Empty = styled(FlexBox)({ - alignItems: 'center', - height: '100%', - justifyContent: 'center', - width: '100%', - }); - onImageSelected = (selectedImage: ImageId) => { this.setState({selectedImage}); this.props.onImageSelected(selectedImage); }; - onKeyDown = (e: KeyboardEvent) => { - const selectedImage = this.state.selectedImage; - const imagesMap = this.props.imagesMap; - - if (selectedImage) { - if ((e.ctrlKey || e.metaKey) && e.key === 'c') { - clipboard.writeText(String(imagesMap[selectedImage])); - e.preventDefault(); - } - } - }; - onEnableDebugOverlayToggled = () => { this.props.onEnableDebugOverlay(!this.props.isDebugOverlayEnabled); }; @@ -145,9 +106,6 @@ export default class ImagesCacheOverview extends PureComponent< this.props.onEnableAutoRefresh(!this.props.isAutoRefreshEnabled); }; - onChangeSize = (e: ChangeEvent) => - this.setState({size: parseInt(e.target.value, 10)}); - onSurfaceOptionsChange = (selectedItem: string, checked: boolean) => { const {allSurfacesOption, surfaceOptions} = this.props; const selectedSurfaces = new Set([...this.props.selectedSurfaces]); @@ -190,12 +148,11 @@ export default class ImagesCacheOverview extends PureComponent< ) > 0; return ( - - - @@ -230,21 +187,13 @@ export default class ImagesCacheOverview extends PureComponent< onClick={this.props.onShowDiskImages} label="Show Disk Images" /> - - {!hasImages ? ( - - - + + + ) : ( - + {this.props.images.map((data: CacheInfo, index: number) => { const maxSize = data.maxSizeBytes; const subtitle = maxSize @@ -263,15 +212,14 @@ export default class ImagesCacheOverview extends PureComponent< onImageSelected={this.onImageSelected} selectedImage={this.state.selectedImage} imagesMap={this.props.imagesMap} - size={this.state.size} events={this.props.events} onClear={onClear} /> ); })} - + )} - + ); } } @@ -284,7 +232,6 @@ class ImageGrid extends PureComponent<{ onImageSelected: (image: ImageId) => void; onClear: (() => void) | undefined; imagesMap: ImagesMap; - size: number; events: Array; }> { static Content = styled.div({ @@ -298,31 +245,48 @@ class ImageGrid extends PureComponent<{ return null; } + const ROW_SIZE = 6; + const imageRows = Array(Math.ceil(images.length / ROW_SIZE)) + .fill(0) + .map((_, index) => index * ROW_SIZE) + .map((begin) => images.slice(begin, begin + ROW_SIZE)); + return ( - <> + - - {images.map((imageId) => ( - e.imageIds.includes(imageId)) - .length - } - /> + + + {imageRows.map((row, rowIndex) => ( + + + {row.map((imageId, colIndex) => ( + + + e.imageIds.includes(imageId), + ).length + } + /> + + ))} + + ))} - - + + ); } } @@ -332,56 +296,23 @@ class ImageGridHeader extends PureComponent<{ subtitle: string; onClear: (() => void) | undefined; }> { - static Container = styled(FlexRow)({ - color: colors.dark70, - paddingTop: 10, - paddingBottom: 10, - marginLeft: 15, - marginRight: 15, - marginBottom: 15, - borderBottom: `1px solid ${colors.light10}`, - flexShrink: 0, - alignItems: 'center', - position: 'sticky', - top: 0, - left: 0, - right: 0, - backgroundColor: colors.white, - zIndex: 3, - }); - - static Heading = styled.span({ - fontSize: 22, - fontWeight: 600, - }); - static Subtitle = styled.span({ fontSize: 22, fontWeight: 300, - marginLeft: 15, - }); - - static ClearButton = styled(Button)({ - alignSelf: 'center', - height: 30, - marginLeft: 'auto', - width: 100, }); render() { return ( - - {this.props.title} + + {this.props.title} {this.props.subtitle} - + {this.props.onClear ? ( - - Clear Cache - + ) : null} - + ); } } @@ -394,36 +325,16 @@ class ImageItem extends PureComponent<{ size: number; numberOfRequests: number; }> { - static Container = styled(FlexBox)<{size: number}>((props) => ({ - float: 'left', - alignItems: 'center', - justifyContent: 'center', - flexShrink: 0, - height: props.size, - width: props.size, - borderRadius: 4, - marginRight: 15, - marginBottom: 15, - backgroundColor: colors.light02, - })); - - static Image = styled.img({ - borderRadius: 4, - maxHeight: '100%', - maxWidth: '100%', - objectFit: 'contain', - }); - - static Loading = styled.span({ - padding: '0 0', - }); + static defaultProps = { + size: 150, + }; static SelectedHighlight = styled.div<{selected: boolean}>((props) => ({ - borderColor: colors.highlight, + borderColor: theme.primaryColor, borderStyle: 'solid', borderWidth: props.selected ? 3 : 0, borderRadius: 4, - boxShadow: props.selected ? `inset 0 0 0 1px ${colors.white}` : 'none', + boxShadow: props.selected ? `inset 0 0 0 1px ${theme.white}` : 'none', bottom: 0, left: 0, position: 'absolute', @@ -431,25 +342,26 @@ class ImageItem extends PureComponent<{ top: 0, })); - static HoverOverlay = styled(FlexColumn)<{selected: boolean; size: number}>( - (props) => ({ - alignItems: 'center', - backgroundColor: colors.whiteAlpha80, - bottom: props.selected ? 4 : 0, - fontSize: props.size > 100 ? 16 : 11, - justifyContent: 'center', - left: props.selected ? 4 : 0, - opacity: 0, - position: 'absolute', - right: props.selected ? 4 : 0, - top: props.selected ? 4 : 0, - overflow: 'hidden', - transition: '.1s opacity', - '&:hover': { - opacity: 1, - }, - }), - ); + static HoverOverlay = styled(Layout.Container)<{ + selected: boolean; + size: number; + }>((props) => ({ + alignItems: 'center', + backgroundColor: 'rgba(255,255,255,0.8)', + bottom: props.selected ? 4 : 0, + fontSize: props.size > 100 ? 16 : 11, + justifyContent: 'center', + left: props.selected ? 4 : 0, + opacity: 0, + position: 'absolute', + right: props.selected ? 4 : 0, + top: props.selected ? 4 : 0, + overflow: 'hidden', + transition: '.1s opacity', + '&:hover': { + opacity: 1, + }, + })); static MemoryLabel = styled.span({ fontWeight: 600, @@ -460,25 +372,13 @@ class ImageItem extends PureComponent<{ fontWeight: 300, }); - static Events = styled.div({ + static EventBadge = styled(Badge)({ position: 'absolute', - top: -5, - right: -5, - color: colors.white, - backgroundColor: colors.highlight, - fontWeight: 600, - borderRadius: 10, - fontSize: '0.85em', - zIndex: 2, - lineHeight: '20px', - width: 20, - textAlign: 'center', + top: 0, + right: 0, + zIndex: 1, }); - static defaultProps = { - size: 150, - }; - onClick = () => { this.props.onSelected(this.props.imageId); }; @@ -487,14 +387,14 @@ class ImageItem extends PureComponent<{ const {image, selected, size, numberOfRequests} = this.props; return ( - + {numberOfRequests > 0 && image != null && ( - {numberOfRequests} + )} {image != null ? ( - + ) : ( - + )} {image != null && ( @@ -507,7 +407,7 @@ class ImageItem extends PureComponent<{ )} - + ); } } diff --git a/desktop/plugins/public/fresco/ImagesSidebar.tsx b/desktop/plugins/public/fresco/ImagesSidebar.tsx index da36fcf59..9caa626b7 100644 --- a/desktop/plugins/public/fresco/ImagesSidebar.tsx +++ b/desktop/plugins/public/fresco/ImagesSidebar.tsx @@ -9,20 +9,15 @@ import {ImageData} from './api'; import {ImageEventWithId} from './index'; +import React, {Component} from 'react'; import { - Component, - ContextMenu, - DataDescription, - Text, - Panel, - ManagedDataInspector, - FlexColumn, - FlexRow, - colors, + Layout, + theme, styled, -} from 'flipper'; -import React from 'react'; -import {clipboard, MenuItemConstructorOptions} from 'electron'; + DataDescription, + Panel, + DataInspector, +} from 'flipper-plugin'; type ImagesSidebarProps = { image: ImageData; @@ -32,10 +27,10 @@ type ImagesSidebarProps = { type ImagesSidebarState = {}; const DataDescriptionKey = styled.span({ - color: colors.grapeDark1, + color: theme.textColorPrimary, }); -const WordBreakFlexColumn = styled(FlexColumn)({ +const WordBreakFlexColumn = styled(Layout.Container)({ wordBreak: 'break-all', }); @@ -62,37 +57,22 @@ export default class ImagesSidebar extends Component< return null; } - const contextMenuItems: MenuItemConstructorOptions[] = [ - { - label: 'Copy URI', - click: () => clipboard.writeText(this.props.image.uri!), - }, - ]; - return ( - - - - URI - - - - - - - - - - + + + + URI: + + + ); } } - class EventDetails extends Component<{ event: ImageEventWithId; }> { @@ -100,11 +80,11 @@ class EventDetails extends Component<{ const {event} = this.props; return ( - } floating={false} padded> +

Attribution : - +

Time start @@ -163,24 +143,11 @@ class EventDetails extends Component<{ } } -class RequestHeader extends Component<{ - event: ImageEventWithId; -}> { - dateString = (timestamp: number) => { - const date = new Date(timestamp); - return `${date.toTimeString().split(' ')[0]}.${( - '000' + date.getMilliseconds() - ).substr(-3)}`; - }; +function requestHeader(event: ImageEventWithId) { + const date = new Date(event.startTime); + const dateString = `${date.toTimeString().split(' ')[0]}.${( + '000' + date.getMilliseconds() + ).substr(-3)}`; - render() { - const {event} = this.props; - const durationMs = event.endTime - event.startTime; - return ( - - {event.viewport ? 'Request' : 'Prefetch'} at{' '} - {this.dateString(event.startTime)} ({durationMs}ms) - - ); - } + return (event.viewport ? 'Request' : 'Prefetch') + ' at ' + dateString; } diff --git a/desktop/plugins/public/fresco/MultipleSelect.tsx b/desktop/plugins/public/fresco/MultipleSelect.tsx index 858d1968b..e0a1b5647 100644 --- a/desktop/plugins/public/fresco/MultipleSelect.tsx +++ b/desktop/plugins/public/fresco/MultipleSelect.tsx @@ -7,105 +7,47 @@ * @format */ -import {Block, Button, colors, FlexColumn, styled, Glyph} from 'flipper'; -import React, {ChangeEvent, Component} from 'react'; +import React, {Component} from 'react'; +import {Layout} from 'flipper-plugin'; +import {Button, Menu, Checkbox, Dropdown} from 'antd'; +import {DownOutlined} from '@ant-design/icons'; +import type {CheckboxChangeEvent} from 'antd/lib/checkbox'; -const Container = styled(Block)({ - position: 'relative', - marginLeft: '10px', -}); - -const List = styled(FlexColumn)<{visibleList: boolean}>((props) => ({ - display: props.visibleList ? 'flex' : 'none', - position: 'absolute', - top: '32px', - left: 0, - zIndex: 4, - width: 'auto', - minWidth: '200px', - backgroundColor: colors.white, - borderWidth: '1px', - borderStyle: 'solid', - borderColor: colors.macOSTitleBarButtonBorderBottom, - borderRadius: 4, -})); - -const ListItem = styled.label({ - cursor: 'pointer', - display: 'flex', - alignItems: 'center', - width: '100%', - color: colors.light50, - fontSize: '11px', - padding: '0 5px', - '&:hover': { - backgroundColor: colors.macOSTitleBarButtonBackgroundActiveHighlight, - }, -}); - -const Checkbox = styled.input({ - display: 'inline-block', - marginRight: 5, - verticalAlign: 'middle', -}); - -const StyledGlyph = styled(Glyph)({ - marginLeft: '4px', -}); - -type State = { - visibleList: boolean; -}; - -export default class MultipleSelect extends Component< - { - selected: Set; - - options: Set; - - onChange: (selectedItem: string, checked: boolean) => void; - - label: string; - }, - State -> { - state = { - visibleList: false, +export default class MultipleSelect extends Component<{ + selected: Set; + options: Set; + label: string; + onChange: (selectedItem: string, checked: boolean) => void; +}> { + handleOnChange = (option: string, event: CheckboxChangeEvent) => { + this.props.onChange(option, event.target.checked); }; - handleOnChange = (event: ChangeEvent) => { - const { - target: {value, checked}, - } = event; - this.props.onChange(value, checked); + menu = () => { + return ( +

+ {Array.from(this.props.options).map((option, index) => ( + + this.handleOnChange(option, e)} + checked={this.props.selected.has(option)} + />{' '} + {option} + + ))} + + ); }; - toggleList = () => this.setState({visibleList: !this.state.visibleList}); - render() { - const {selected, label, options} = this.props; - const {visibleList} = this.state; - const icon = visibleList ? 'chevron-up' : 'chevron-down'; - return ( - - - - {Array.from(options).map((option, index) => ( - - - {option} - - ))} - - + + + + + ); } } diff --git a/desktop/plugins/public/fresco/index.tsx b/desktop/plugins/public/fresco/index.tsx index 0c98d432d..8753a69dd 100644 --- a/desktop/plugins/public/fresco/index.tsx +++ b/desktop/plugins/public/fresco/index.tsx @@ -17,19 +17,21 @@ import { AndroidCloseableReferenceLeakEvent, CacheInfo, } from './api'; -import {Fragment} from 'react'; import {ImagesMap} from './ImagePool'; -import {PluginClient, createState, usePlugin, useValue} from 'flipper-plugin'; +import { + PluginClient, + createState, + usePlugin, + useValue, + DetailSidebar, + Layout, +} from 'flipper-plugin'; import React from 'react'; import ImagesCacheOverview from './ImagesCacheOverview'; -import { - FlexRow, - Text, - DetailSidebar, - colors, - styled, - isProduction, -} from 'flipper'; +import {isProduction} from 'flipper'; + +import {Typography} from 'antd'; + import ImagesSidebar from './ImagesSidebar'; import ImagePool from './ImagePool'; @@ -38,18 +40,6 @@ export type AllImageEventsInfo = { events: Array; }; -const EmptySidebar = styled(FlexRow)({ - alignItems: 'center', - justifyContent: 'center', - color: colors.light30, - padding: 15, - fontSize: 16, -}); - -export const InlineFlexRow = styled(FlexRow)({ - display: 'inline-block', -}); - const surfaceDefaultText = 'SELECT ALL SURFACES'; const debugLog = (...args: any[]) => { @@ -113,18 +103,17 @@ export function plugin(client: PluginClient) { id: event.identityHashCode, title: `Leaked CloseableReference: ${event.className}`, message: ( - - - CloseableReference leaked for {event.className} + + CloseableReference leaked for + {event.className} + (identity hashcode: {event.identityHashCode}). - - - Stacktrace: - - - {event.stacktrace || ''} - - + + Stacktrace: + + {event.stacktrace || ''} + + ), severity: 'error', category: 'closeablereference_leak', @@ -465,11 +454,11 @@ function Sidebar() { if (currentSelectedImage == null) { return ( - - + + Select an image to see the events associated with it. - - + + ); }