diff --git a/desktop/flipper-plugin/src/state/datasource/DataSource.tsx b/desktop/flipper-plugin/src/state/datasource/DataSource.tsx index 9fafa783c..ca5a8d605 100644 --- a/desktop/flipper-plugin/src/state/datasource/DataSource.tsx +++ b/desktop/flipper-plugin/src/state/datasource/DataSource.tsx @@ -91,8 +91,8 @@ export class DataSource< private dataUpdateQueue: DataEvent[] = []; - private windowStart = 0; - private windowEnd = 0; + windowStart = 0; + windowEnd = 0; private outputChangeListener?: (change: OutputChange) => void; diff --git a/desktop/flipper-plugin/src/ui/datatable/DataSourceRenderer.tsx b/desktop/flipper-plugin/src/ui/datatable/DataSourceRenderer.tsx index 2e1aac669..95341961c 100644 --- a/desktop/flipper-plugin/src/ui/datatable/DataSourceRenderer.tsx +++ b/desktop/flipper-plugin/src/ui/datatable/DataSourceRenderer.tsx @@ -55,6 +55,7 @@ type DataSourceProps = { defaultRowHeight: number; onKeyDown?: React.KeyboardEventHandler; virtualizerRef?: MutableRefObject; + onRangeChange?(start: number, end: number, total: number): void; _testHeight?: number; // exposed for unit testing only }; @@ -73,6 +74,7 @@ export const DataSourceRenderer: ( autoScroll, onKeyDown, virtualizerRef, + onRangeChange, _testHeight, }: DataSourceProps) { /** @@ -176,6 +178,9 @@ export const DataSourceRenderer: ( useLayoutEffect(function updateWindow() { const start = virtualizer.virtualItems[0]?.index ?? 0; const end = start + virtualizer.virtualItems.length; + if (start !== dataSource.windowStart && !followOutput.current) { + onRangeChange?.(start, end, dataSource.output.length); + } dataSource.setWindow(start, end); }); diff --git a/desktop/flipper-plugin/src/ui/datatable/DataTable.tsx b/desktop/flipper-plugin/src/ui/datatable/DataTable.tsx index 781ab694c..cc9bd116b 100644 --- a/desktop/flipper-plugin/src/ui/datatable/DataTable.tsx +++ b/desktop/flipper-plugin/src/ui/datatable/DataTable.tsx @@ -12,6 +12,7 @@ import React, { useLayoutEffect, useMemo, useRef, + useState, RefObject, MutableRefObject, } from 'react'; @@ -23,6 +24,8 @@ import {Percentage} from '../utils/widthUtils'; import {DataSourceRenderer, DataSourceVirtualizer} from './DataSourceRenderer'; import {useDataTableManager, TableManager} from './useDataTableManager'; import {TableSearch} from './TableSearch'; +import styled from '@emotion/styled'; +import {theme} from '../theme'; interface DataTableProps { columns: DataTableColumn[]; @@ -161,34 +164,64 @@ export function DataTable(props: DataTableProps) { [selection], ); + /** Range finder */ + const [range, setRange] = useState(''); + const hideRange = useRef(); + + const onRangeChange = useCallback( + (start: number, end: number, total: number) => { + // TODO: figure out if we don't trigger this callback to often hurting perf + setRange(`${start} - ${end} / ${total}`); + clearTimeout(hideRange.current!); + hideRange.current = setTimeout(() => { + setRange(''); + }, 1000); + }, + [], + ); + return ( - - - + + + + + + > + dataSource={dataSource} + autoScroll={props.autoScroll} + useFixedRowHeight={!usesWrapping} + defaultRowHeight={DEFAULT_ROW_HEIGHT} + context={renderingConfig} + itemRenderer={itemRenderer} + onKeyDown={onKeyDown} + virtualizerRef={virtualizerRef} + onRangeChange={onRangeChange} + _testHeight={props._testHeight} /> - - - > - dataSource={dataSource} - autoScroll={props.autoScroll} - useFixedRowHeight={!usesWrapping} - defaultRowHeight={DEFAULT_ROW_HEIGHT} - context={renderingConfig} - itemRenderer={itemRenderer} - onKeyDown={onKeyDown} - virtualizerRef={virtualizerRef} - _testHeight={props._testHeight} - /> - + + {range && {range}} + ); } + +const RangeFinder = styled.div({ + backgroundColor: theme.backgroundWash, + position: 'absolute', + right: 40, + bottom: 20, + padding: '4px 8px', + color: theme.textColorSecondary, + fontSize: '0.8em', +});