Skip to content

Commit

Permalink
List View: experiment with only rendering a fixed number of items
Browse files Browse the repository at this point in the history
  • Loading branch information
gwwar committed Sep 30, 2021
1 parent d78bbc8 commit 85ebc91
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 19 deletions.
2 changes: 2 additions & 0 deletions packages/block-editor/src/components/list-view/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default function ListViewBlock( {
showBlockMovers,
path,
isExpanded,
style,
} ) {
const cellRef = useRef( null );
const [ isHovered, setIsHovered ] = useState( false );
Expand Down Expand Up @@ -140,6 +141,7 @@ export default function ListViewBlock( {
className="block-editor-list-view-block__contents-cell"
colSpan={ hasRenderedMovers ? undefined : 2 }
ref={ cellRef }
style={ style }
>
{ ( { ref, tabIndex, onFocus } ) => (
<div className="block-editor-list-view-block__contents-container">
Expand Down
86 changes: 69 additions & 17 deletions packages/block-editor/src/components/list-view/branch.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@ import ListViewAppender from './appender';
import { isClientIdSelected } from './utils';
import { useListViewContext } from './context';

function countBlocks( block, expandedState ) {
const isExpanded = expandedState[ block.clientId ] ?? true;
if ( isExpanded ) {
return 1 + block.innerBlocks.reduce( countReducer( expandedState ), 0 );
}
return 1;
}
const countReducer = ( expandedState ) => ( count, block ) => {
const isExpanded = expandedState[ block.clientId ] ?? true;
if ( isExpanded && block.innerBlocks.length > 0 ) {
return count + countBlocks( block, expandedState );
}
return count + 1;
};

const ITEM_HEIGHT = 36;

export default function ListViewBranch( props ) {
const {
blocks,
Expand All @@ -29,6 +46,9 @@ export default function ListViewBranch( props ) {
path = [],
isBranchSelected = false,
isLastOfBranch = false,
listPosition = 0,
measurement,
globalBlockCount,
} = props;

const {
Expand All @@ -50,6 +70,7 @@ export default function ListViewBranch( props ) {
const blockCount = filteredBlocks.length;
const rowCount = hasAppender ? blockCount + 1 : blockCount;
const appenderPosition = rowCount;
let nextPosition = listPosition;

return (
<>
Expand Down Expand Up @@ -102,25 +123,53 @@ export default function ListViewBranch( props ) {
// but asynchronous for any other block.
const isDragged = !! draggedClientIds?.includes( clientId );

if ( index > 0 ) {
nextPosition += countBlocks(
filteredBlocks[ index - 1 ],
expandedState
);
}
const end = measurement.start + measurement.maxVisible;
const blockInView =
measurement.start <= nextPosition &&
nextPosition <= measurement.start + measurement.maxVisible;

const style = {
...( measurement.start === nextPosition
? { paddingTop: ITEM_HEIGHT * measurement.start }
: {} ),
...( globalBlockCount > end && end === nextPosition
? {
paddingBottom:
ITEM_HEIGHT * ( globalBlockCount - end ),
}
: {} ),
};
return (
<AsyncModeProvider key={ clientId } value={ ! isSelected }>
<ListViewBlock
block={ block }
onClick={ selectBlockWithClientId }
onToggleExpanded={ toggleExpanded }
isDragged={ isDragged }
isSelected={ isSelected }
isBranchSelected={ isSelectedBranch }
isLastOfSelectedBranch={ isLastOfSelectedBranch }
level={ level }
position={ position }
rowCount={ rowCount }
siblingBlockCount={ blockCount }
showBlockMovers={ showBlockMovers }
terminatedLevels={ terminatedLevels }
path={ updatedPath }
isExpanded={ isExpanded }
/>
{ blockInView && (
<ListViewBlock
block={ block }
onClick={ selectBlockWithClientId }
onToggleExpanded={ toggleExpanded }
isDragged={ isDragged }
isSelected={ isSelected }
isBranchSelected={ isSelectedBranch }
isLastOfSelectedBranch={
isLastOfSelectedBranch
}
level={ level }
position={ position }
rowCount={ rowCount }
siblingBlockCount={ blockCount }
showBlockMovers={ showBlockMovers }
terminatedLevels={ terminatedLevels }
path={ updatedPath }
isExpanded={ isExpanded }
listPosition={ nextPosition }
style={ style }
/>
) }
{ hasNestedBranch && isExpanded && ! isDragged && (
<ListViewBranch
blocks={ innerBlocks }
Expand All @@ -134,6 +183,9 @@ export default function ListViewBranch( props ) {
level={ level + 1 }
terminatedLevels={ updatedTerminatedLevels }
path={ updatedPath }
listPosition={ nextPosition + 1 }
measurement={ measurement }
globalBlockCount={ globalBlockCount }
/>
) }
</AsyncModeProvider>
Expand Down
51 changes: 49 additions & 2 deletions packages/block-editor/src/components/list-view/index.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
/**
* WordPress dependencies
* External dependencies
*/
import { throttle } from 'lodash';

/**
* WordPress dependencies
*/
import { useMergeRefs } from '@wordpress/compose';
import { __experimentalTreeGrid as TreeGrid } from '@wordpress/components';
import { AsyncModeProvider, useDispatch } from '@wordpress/data';
import { AsyncModeProvider, useDispatch, useSelect } from '@wordpress/data';
import {
useCallback,
useEffect,
useLayoutEffect,
useMemo,
useRef,
useReducer,
useState,
forwardRef,
} from '@wordpress/element';
import { __ } from '@wordpress/i18n';

function measure( scrollContainer, setMeasurement ) {
const maxVisible = Math.ceil( scrollContainer.clientHeight / ITEM_HEIGHT );
const start = Math.floor( scrollContainer.scrollTop / ITEM_HEIGHT );
setMeasurement( {
maxVisible,
start,
} );
}

/**
* Internal dependencies
*/
Expand All @@ -37,6 +52,8 @@ const expanded = ( state, action ) => {
}
};

const ITEM_HEIGHT = 36;

/**
* Wrap `ListViewRows` with `TreeGrid`. ListViewRows is a
* recursive component (it renders itself), so this ensures TreeGrid is only
Expand Down Expand Up @@ -71,6 +88,11 @@ function ListView(
showOnlyCurrentHierarchy,
__experimentalPersistentListViewFeatures
);

const globalBlockCount = useSelect( ( select ) => {
return select( blockEditorStore ).getGlobalBlockCount();
}, [] );

const { selectBlock } = useDispatch( blockEditorStore );
const selectEditorBlock = useCallback(
( clientId ) => {
Expand All @@ -90,6 +112,29 @@ function ListView(
isMounted.current = true;
}, [] );

//TODO: needs tuning for scroll position
const [ scrollHeight, setScrollHeight ] = useState(
ITEM_HEIGHT * globalBlockCount
);
const [ measurement, setMeasurement ] = useState( {
maxVisible: 30,
start: 0,
} );

useLayoutEffect( () => {
const scrollContainer = elementRef.current.parentNode;
measure( scrollContainer, setMeasurement );
const measureListOnScroll = throttle( ( event ) => {
measure( event.target, setMeasurement );
}, 16 );
scrollContainer.addEventListener( 'scroll', measureListOnScroll );
return () =>
scrollContainer.removeEventListener(
'scroll',
measureListOnScroll
);
}, [] );

const expand = useCallback(
( clientId ) => {
if ( ! clientId ) {
Expand Down Expand Up @@ -155,6 +200,8 @@ function ListView(
<ListViewBranch
blocks={ clientIdsTree }
selectBlock={ selectEditorBlock }
measurement={ measurement }
globalBlockCount={ globalBlockCount }
{ ...props }
/>
</ListViewContext.Provider>
Expand Down

0 comments on commit 85ebc91

Please sign in to comment.