Skip to content

Commit

Permalink
Prerender (#40)
Browse files Browse the repository at this point in the history
* feat: update

* feat: update

* feat: update

* feat: add comments

* feat: add `itemOffsetBeforeLayoutReady` support

* feat: update

* feat: update

* feat: update
  • Loading branch information
ryuever authored Jul 2, 2023
1 parent 045be53 commit a22148c
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 69 deletions.
2 changes: 1 addition & 1 deletion packages/data-model/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@x-oasis/default-boolean-value": "^0.1.14",
"@x-oasis/integer-buffer-set": "^0.1.14",
"@x-oasis/is-clamped": "^0.1.14",
"@x-oasis/layout-equal": "^0.1.14",
"@x-oasis/layout-equal": "^0.1.16",
"@x-oasis/noop": "^0.1.14",
"@x-oasis/omit": "^0.1.14",
"@x-oasis/prefix-interval-tree": "^0.1.14",
Expand Down
37 changes: 16 additions & 21 deletions packages/data-model/src/BaseLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ import {
WINDOW_SIZE,
RECYCLE_BUFFERED_COUNT,
LENGTH_PRECISION,
ITEM_OFFSET_BEFORE_LAYOUT_READY,
} from './common';
import SelectValue, {
selectHorizontalValue,
selectVerticalValue,
} from '@x-oasis/select-value';
import { ContainerLayoutGetter, ItemLayout, FillingMode } from './types';
import {
ContainerLayoutGetter,
ItemLayout,
FillingMode,
BaseLayoutProps,
} from './types';

class BaseLayout {
private _layout: ItemLayout = DEFAULT_LAYOUT;
Expand All @@ -32,26 +38,9 @@ class BaseLayout {
readonly _lengthPrecision: number;
private _recycleBufferedCount: number;
private _canIUseRIC: boolean;
private _itemOffsetBeforeLayoutReady: number;

constructor(props: {
id: string;
horizontal?: boolean;
getContainerLayout?: ContainerLayoutGetter;
onEndReachedThreshold?: number;
windowSize?: number;
maxToRenderPerBatch?: number;
initialNumToRender?: number;
persistanceIndices?: Array<number>;
stickyHeaderIndices?: Array<number>;

recycleThreshold?: number;
recycleBufferedCount?: number;
recycleEnabled?: boolean;

canIUseRIC?: boolean;

lengthPrecision?: number;
}) {
constructor(props: BaseLayoutProps) {
const {
id,
recycleThreshold,
Expand All @@ -67,6 +56,7 @@ class BaseLayout {
maxToRenderPerBatch = MAX_TO_RENDER_PER_BATCH,
initialNumToRender = INITIAL_NUM_TO_RENDER,
onEndReachedThreshold = ON_END_REACHED_THRESHOLD,
itemOffsetBeforeLayoutReady = ITEM_OFFSET_BEFORE_LAYOUT_READY,
} = props;

this.id = id;
Expand All @@ -93,6 +83,7 @@ class BaseLayout {
this.stickyHeaderIndices = stickyHeaderIndices;
this._canIUseRIC = canIUseRIC;
this._lengthPrecision = lengthPrecision;
this._itemOffsetBeforeLayoutReady = itemOffsetBeforeLayoutReady;
}

get initialNumToRender() {
Expand All @@ -111,6 +102,10 @@ class BaseLayout {
return this._recycleBufferedCount;
}

get itemOffsetBeforeLayoutReady() {
return this._itemOffsetBeforeLayoutReady;
}

get canIUseRIC() {
return this._canIUseRIC;
}
Expand Down Expand Up @@ -237,7 +232,7 @@ class BaseLayout {
}

normalizeLengthNumber(length: number) {
return +length.toPrecision(this._lengthPrecision);
return +length.toFixed(this._lengthPrecision);
}

normalizeLengthInfo(info: ItemLayout) {
Expand Down
106 changes: 65 additions & 41 deletions packages/data-model/src/ListDimensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
buildStateTokenIndexKey,
DISPATCH_METRICS_THRESHOLD,
DEFAULT_ITEM_APPROXIMATE_LENGTH,
LAYOUT_EQUAL_CORRECTION_VALUE,
} from './common';
import resolveChanged from '@x-oasis/resolve-changed';
import manager from './manager';
Expand Down Expand Up @@ -280,21 +281,6 @@ class ListDimensions<ItemT extends {} = {}> extends BaseDimensions {
this._renderStateListeners = [];
}

// approximateLayoutGetter(data, index) {
// const totalLength = this.getTotalLength() || 0
// const dataLength = this._data.length
// if (typeof totalLength === 'number')
// return {
// length: +(totalLength / dataLength).toPrecision(4),
// index,
// }

// return {
// length: 80,
// index,
// }
// }

resolveInitialActiveValue(active: boolean) {
if (this._deps.length) {
let isActive = true;
Expand Down Expand Up @@ -908,12 +894,16 @@ class ListDimensions<ItemT extends {} = {}> extends BaseDimensions {
// const meta = this.getItemMeta(item, index);

if (!meta) return false;
meta.isApproximateLayout = false;

if (typeof info === 'number') {
let length = this.normalizeLengthNumber(info);
if (this._selectValue.selectLength(meta.getLayout() || {}) !== length) {
if (
Math.abs(
length - (this._selectValue.selectLength(meta.getLayout() || {}) || 0)
) > LAYOUT_EQUAL_CORRECTION_VALUE
) {
this._selectValue.setLength(meta.ensureLayout(), length);
meta.isApproximateLayout = false;

if (index !== this._data.length - 1) {
length = meta.getSeparatorLength() + length;
Expand All @@ -928,11 +918,10 @@ class ListDimensions<ItemT extends {} = {}> extends BaseDimensions {
const _info = this.normalizeLengthInfo(info);

if (
!layoutEqual(
meta.getLayout(),
_info as ItemLayout,
this.horizontal ? ['width'] : ['height']
)
!layoutEqual(meta.getLayout(), _info as ItemLayout, {
keysToCheck: this.horizontal ? ['width'] : ['height'],
correctionValue: LAYOUT_EQUAL_CORRECTION_VALUE,
})
) {
// if (meta.getLayout()) {
// console.warn(
Expand All @@ -948,7 +937,6 @@ class ListDimensions<ItemT extends {} = {}> extends BaseDimensions {
);
let length = this._selectValue.selectLength((_info as ItemLayout) || {});
meta.setLayout(_info as ItemLayout);
meta.isApproximateLayout = false;
// 只有关心的值发生变化时,才会再次触发setIntervalTreeValue
if (currentLength !== length && _update) {
if (index !== this._data.length - 1) {
Expand Down Expand Up @@ -1127,6 +1115,7 @@ class ListDimensions<ItemT extends {} = {}> extends BaseDimensions {
}

getPosition(rowIndex: number, startIndex: number, endIndex: number) {
if (rowIndex < 0) return null;
// 初始化的item不参与absolute替换
if (rowIndex < this.initialNumToRender) return null;
let position = this._bufferSet.getValuePosition(rowIndex);
Expand Down Expand Up @@ -1182,7 +1171,8 @@ class ListDimensions<ItemT extends {} = {}> extends BaseDimensions {
step: number;
}
) {
const { startIndex, safeRange, step, maxCount } = props;
const { startIndex: _startIndex, safeRange, step, maxCount } = props;
const startIndex = Math.max(_startIndex, 0);
let finalIndex = startIndex;
let count = 0;
if (maxCount < 0) return finalIndex;
Expand Down Expand Up @@ -1239,16 +1229,18 @@ class ListDimensions<ItemT extends {} = {}> extends BaseDimensions {
visibleEndIndex,
});

if (visibleEndIndex >= 0) {
for (let index = visibleStartIndex; index <= visibleEndIndex; index++) {
const position = this.getPosition(
index,
safeRange.startIndex,
safeRange.endIndex
);
if (position !== null) targetIndices[position] = index;
}
}
// for (
// let index = visibleStartIndex;
// index <= visibleEndIndex - 4;
// index++
// ) {
// const position = this.getPosition(
// index,
// safeRange.startIndex,
// safeRange.endIndex
// );
// if (position !== null) targetIndices[position] = index;
// }

// const remainingPosition = Math.max(
// this.recycleThreshold - (safeRange.endIndex - safeRange.startIndex + 1),
Expand All @@ -1260,21 +1252,50 @@ class ListDimensions<ItemT extends {} = {}> extends BaseDimensions {
// );

if (this._getItemLayout || this._approximateMode) {
if (Math.abs(velocity) <= 1) {
// if velocity greater than 4, the below on high priority. then start position
// forward 4,
if (velocity > 4) {
this.updateIndices(targetIndices, {
safeRange,
startIndex: visibleStartIndex - 1,
maxCount: 1,
step: -1,
startIndex: visibleStartIndex + 4,
maxCount: visibleEndIndex - visibleStartIndex + 1,
step: 1,
});
// if velocity less than -4, the above on high priority. then start position
// forward 4,
} else if (velocity < -4) {
this.updateIndices(targetIndices, {
safeRange,
startIndex: visibleEndIndex + 1,
maxCount: 1,
startIndex: visibleStartIndex - 4,
maxCount: visibleEndIndex - visibleStartIndex + 1,
step: 1,
});
} else {
// if velocity less than 1, scroll will stop soon, so add 1 element
// on heading and trailing as buffer
if (Math.abs(velocity) <= 1) {
this.updateIndices(targetIndices, {
safeRange,
startIndex: visibleStartIndex - 1,
maxCount: visibleEndIndex - visibleStartIndex + 3,
step: 1,
});
} else {
this.updateIndices(targetIndices, {
safeRange,
startIndex: visibleStartIndex,
maxCount: visibleEndIndex - visibleStartIndex + 1,
step: 1,
});
}
}
} else {
this.updateIndices(targetIndices, {
safeRange,
startIndex: visibleStartIndex,
maxCount: visibleEndIndex - visibleStartIndex + 1,
step: 1,
});
// ********************** commented on 0626 begin ************************//
if (velocity >= 0) {
const maxValue = this._bufferSet.getMaxValue();
Expand Down Expand Up @@ -1428,7 +1449,10 @@ class ListDimensions<ItemT extends {} = {}> extends BaseDimensions {
itemMeta,
viewable: itemMeta.getState().viewable,
// 如果没有offset,说明item是新增的,那么它渲染就在最开始位置好了
offset: itemLength ? indexToOffsetMap[targetIndex] : 0,
offset:
itemLength && !itemMeta.isApproximateLayout
? indexToOffsetMap[targetIndex]
: this.itemOffsetBeforeLayoutReady,
position: 'buffered',
});
});
Expand Down
5 changes: 4 additions & 1 deletion packages/data-model/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const DEFAULT_LAYOUT = {
export const INTERVAL_TREE_INITIAL_SIZE = 16;
export const ON_END_REACHED_TIMEOUT_THRESHOLD = 200;
export const ON_END_REACHED_HANDLER_TIMEOUT_THRESHOLD = 2000;
export const DISPATCH_METRICS_THRESHOLD = 50;
export const DISPATCH_METRICS_THRESHOLD = 16;
export const RECYCLE_BUFFERED_COUNT = 4;
export const LENGTH_PRECISION = 4;
export const DEFAULT_ITEM_APPROXIMATE_LENGTH = 80;
Expand All @@ -22,6 +22,9 @@ export const INITIAL_NUM_TO_RENDER = 10;
export const MAX_TO_RENDER_PER_BATCH = 10;
export const INVALID_LENGTH = 'invalid_length';

export const ITEM_OFFSET_BEFORE_LAYOUT_READY = -4000;
export const LAYOUT_EQUAL_CORRECTION_VALUE = 0.5;

export const removeItemsKeyword = (configKey) =>
(configKey.match(/(.*)[iI]tems/) || [])[1] || configKey;

Expand Down
25 changes: 24 additions & 1 deletion packages/data-model/src/types/Dimensions.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,28 @@ export type GetItemLayout<ItemT> = (
) => { length: number; index: number };
export type KeyExtractor<ItemT> = (item: ItemT, index: number) => string;

export type BaseLayoutProps = {
id: string;
horizontal?: boolean;
getContainerLayout?: ContainerLayoutGetter;
onEndReachedThreshold?: number;
windowSize?: number;
maxToRenderPerBatch?: number;
initialNumToRender?: number;
persistanceIndices?: Array<number>;
stickyHeaderIndices?: Array<number>;

recycleThreshold?: number;
recycleBufferedCount?: number;
recycleEnabled?: boolean;

canIUseRIC?: boolean;

lengthPrecision?: number;

itemOffsetBeforeLayoutReady?: number;
};

export type BaseDimensionsProps = {
id: string;
horizontal?: boolean;
Expand Down Expand Up @@ -94,7 +116,8 @@ export type ListDimensionsProps<ItemT> = {
itemApproximateLength?: number;
useItemApproximateLength?: boolean;
} & BaseDimensionsProps &
OnEndReachedHelperProps;
OnEndReachedHelperProps &
BaseLayoutProps;

export type ItemsDimensionsProps = BaseDimensionsProps;

Expand Down
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a22148c

Please sign in to comment.