From 84ab6d1ea5e0e22de6e116f633aa8af89e64a244 Mon Sep 17 00:00:00 2001 From: adnaan1703 Date: Thu, 11 Oct 2018 10:03:18 +0530 Subject: [PATCH] Support for debugging of difference in cell dimension (#253) * [FINE] added support for debug config where clients can receive callback in case there is non-deterministic heights and there is a discrepancy in it. * [FINE] made the debug handler pluggable. * [FINE] made debugHandler container of other handlers. * [FINE] not using I coding style for the interface. --- scripts/clean.sh | 1 + src/core/RecyclerListView.tsx | 49 ++++++++++++------- .../devutils/debughandlers/DebugHandlers.ts | 6 +++ .../resize/DefaultResizeDebugHandler.ts | 29 +++++++++++ .../resize/ResizeDebugHandler.ts | 5 ++ src/index.ts | 7 ++- 6 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 src/core/devutils/debughandlers/DebugHandlers.ts create mode 100644 src/core/devutils/debughandlers/resize/DefaultResizeDebugHandler.ts create mode 100644 src/core/devutils/debughandlers/resize/ResizeDebugHandler.ts diff --git a/scripts/clean.sh b/scripts/clean.sh index c181a806..4c57590d 100644 --- a/scripts/clean.sh +++ b/scripts/clean.sh @@ -1,3 +1,4 @@ +#!/usr/bin/env bash set -e echo "Deleting old packages..." diff --git a/src/core/RecyclerListView.tsx b/src/core/RecyclerListView.tsx index 84b69f46..2ebb043a 100644 --- a/src/core/RecyclerListView.tsx +++ b/src/core/RecyclerListView.tsx @@ -35,12 +35,14 @@ import BaseScrollView, { ScrollEvent, ScrollViewDefaultProps } from "./scrollcom import { TOnItemStatusChanged } from "./ViewabilityTracker"; import VirtualRenderer, { RenderStack, RenderStackItem, RenderStackParams } from "./VirtualRenderer"; import ItemAnimator, { BaseItemAnimator } from "./ItemAnimator"; +import { DebugHandlers } from ".."; //#if [REACT-NATIVE] import ScrollComponent from "../platform/reactnative/scrollcomponent/ScrollComponent"; import ViewRenderer from "../platform/reactnative/viewrenderer/ViewRenderer"; import { DefaultJSItemAnimator as DefaultItemAnimator } from "../platform/reactnative/itemanimators/defaultjsanimator/DefaultJSItemAnimator"; import { Platform } from "react-native"; + const IS_WEB = !Platform || Platform.OS === "web"; //#endif @@ -51,7 +53,7 @@ const IS_WEB = !Platform || Platform.OS === "web"; //#if [WEB] //import ScrollComponent from "../platform/web/scrollcomponent/ScrollComponent"; //import ViewRenderer from "../platform/web/viewrenderer/ViewRenderer"; -//import { DefaultWebItemAnimator as DefaultItemAnimator} from "../platform/web/itemanimators/DefaultWebItemAnimator"; +//import { DefaultWebItemAnimator as DefaultItemAnimator } from "../platform/web/itemanimators/DefaultWebItemAnimator"; //const IS_WEB = true; //#endif @@ -78,6 +80,7 @@ const refreshRequestDebouncer = debounce((executable: () => void) => { export interface OnRecreateParams { lastOffset?: number; } + export interface RecyclerListViewProps { layoutProvider: BaseLayoutProvider; dataProvider: DataProvider; @@ -104,11 +107,13 @@ export interface RecyclerListViewProps { itemAnimator?: ItemAnimator; optimizeForInsertDeleteAnimations?: boolean; style?: object; + debugHandlers?: DebugHandlers; //For all props that need to be proxied to inner/external scrollview. Put them in an object and they'll be spread //and passed down. For better typescript support. scrollViewProps?: object; } + export interface RecyclerListViewState { renderStack: RenderStack; } @@ -481,21 +486,21 @@ export default class RecyclerListView

(this.props.itemAnimator, this._defaultItemAnimator)} - extendedState={this.props.extendedState} /> + dataHasChanged={this._dataHasChanged} + x={itemRect.x} + y={itemRect.y} + layoutType={type} + index={dataIndex} + styleOverrides={styleOverrides} + layoutProvider={this.props.layoutProvider} + forceNonDeterministicRendering={this.props.forceNonDeterministicRendering} + isHorizontal={this.props.isHorizontal} + onSizeChanged={this._onViewContainerSizeChange} + childRenderer={this.props.rowRenderer} + height={itemRect.height} + width={itemRect.width} + itemAnimator={Default.value(this.props.itemAnimator, this._defaultItemAnimator)} + extendedState={this.props.extendedState}/> ); } return null; @@ -503,7 +508,17 @@ export default class RecyclerListView

{ //Cannot be null here - (this._virtualRenderer.getLayoutManager() as LayoutManager).overrideLayout(index, dim); + const layoutManager: LayoutManager = this._virtualRenderer.getLayoutManager() as LayoutManager; + + if (this.props.debugHandlers && this.props.debugHandlers.resizeDebugHandler) { + const itemRect = layoutManager.getLayouts()[index]; + this.props.debugHandlers.resizeDebugHandler.resizeDebug({ + width: itemRect.width, + height: itemRect.height, + }, dim, index); + } + + layoutManager.overrideLayout(index, dim); if (this._relayoutReqIndex === -1) { this._relayoutReqIndex = index; } else { diff --git a/src/core/devutils/debughandlers/DebugHandlers.ts b/src/core/devutils/debughandlers/DebugHandlers.ts new file mode 100644 index 00000000..51e046ee --- /dev/null +++ b/src/core/devutils/debughandlers/DebugHandlers.ts @@ -0,0 +1,6 @@ +import ResizeDebugHandler from "./resize/ResizeDebugHandler"; + +// It is basically container of all debugHandlers. +export interface DebugHandlers { + resizeDebugHandler?: ResizeDebugHandler; +} diff --git a/src/core/devutils/debughandlers/resize/DefaultResizeDebugHandler.ts b/src/core/devutils/debughandlers/resize/DefaultResizeDebugHandler.ts new file mode 100644 index 00000000..46fff0ac --- /dev/null +++ b/src/core/devutils/debughandlers/resize/DefaultResizeDebugHandler.ts @@ -0,0 +1,29 @@ +import { Dimension } from "../../../.."; +import ResizeDebugHandler from "./ResizeDebugHandler"; + +export default class DefaultResizeDebugHandler implements ResizeDebugHandler { + private readonly relaxation: Dimension; + private readonly onRelaxationViolation: (expectedDim: Dimension, actualDim: Dimension, index: number) => void; + + // Relaxation is the Dimension object where it accepts the relaxation to allow for each dimension. + // Any of the dimension (height or width) whose value for relaxation is less than 0 would be ignored. + public constructor(relaxation: Dimension, onRelaxationViolation: (expectedDim: Dimension, actualDim: Dimension, index: number) => void) { + this.relaxation = relaxation; + this.onRelaxationViolation = onRelaxationViolation; + } + + public resizeDebug(oldDim: Dimension, newDim: Dimension, index: number): void { + let isViolated: boolean = false; + if (this.relaxation.height >= 0 && Math.abs(newDim.height - oldDim.height) >= this.relaxation.height) { + isViolated = true; + } + + if (!isViolated && this.relaxation.width >= 0 && Math.abs(newDim.width - oldDim.width) >= this.relaxation.width) { + isViolated = true; + } + + if (isViolated) { + this.onRelaxationViolation(oldDim, newDim, index); + } + } +} diff --git a/src/core/devutils/debughandlers/resize/ResizeDebugHandler.ts b/src/core/devutils/debughandlers/resize/ResizeDebugHandler.ts new file mode 100644 index 00000000..c6aa1539 --- /dev/null +++ b/src/core/devutils/debughandlers/resize/ResizeDebugHandler.ts @@ -0,0 +1,5 @@ +import { Dimension } from "../../../.."; + +export default interface ResizeDebugHandler { + resizeDebug(oldDim: Dimension, newDim: Dimension, index: number): void; +} diff --git a/src/index.ts b/src/index.ts index dec46c7e..6544933c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,14 @@ import ContextProvider from "./core/dependencies/ContextProvider"; import DataProvider from "./core/dependencies/DataProvider"; -import { LayoutProvider, BaseLayoutProvider, Dimension } from "./core/dependencies/LayoutProvider"; +import { BaseLayoutProvider, Dimension, LayoutProvider } from "./core/dependencies/LayoutProvider"; import RecyclerListView, { OnRecreateParams } from "./core/RecyclerListView"; import BaseScrollView from "./core/scrollcomponent/BaseScrollView"; import { BaseItemAnimator } from "./core/ItemAnimator"; import { AutoScroll } from "./utils/AutoScroll"; -import { LayoutManager, WrapGridLayoutManager, Point, Layout } from "./core/layoutmanager/LayoutManager"; +import { Layout, LayoutManager, Point, WrapGridLayoutManager } from "./core/layoutmanager/LayoutManager"; import ProgressiveListView from "./core/ProgressiveListView"; +import { DebugHandlers } from "./core/devutils/debughandlers/DebugHandlers"; + export { ContextProvider, DataProvider, @@ -23,4 +25,5 @@ export { Point, Layout, OnRecreateParams, + DebugHandlers, };