From 5923759f178fa56f32d1556c7d98b979a5309901 Mon Sep 17 00:00:00 2001 From: alstjr7375 Date: Sun, 24 May 2020 10:31:14 +0900 Subject: [PATCH 1/4] Support Immutable's List with ListDataprovider, ListBaseDataProvider --- package.json | 1 + src/core/RecyclerListView.tsx | 9 +- src/core/VirtualRenderer.ts | 4 +- src/core/dependencies/DataProvider.ts | 151 ++++++++++++++++----- src/core/viewrenderer/BaseViewRenderer.tsx | 5 +- src/index.ts | 4 +- 6 files changed, 130 insertions(+), 44 deletions(-) diff --git a/package.json b/package.json index 8c2ac0f8..48706f0f 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ }, "homepage": "https://github.com/Flipkart/recyclerlistview", "dependencies": { + "immutable": "^4.0.0-rc.12", "lodash.debounce": "4.0.8", "prop-types": "15.5.8", "ts-object-utils": "0.0.5" diff --git a/src/core/RecyclerListView.tsx b/src/core/RecyclerListView.tsx index b46260ba..9c66c262 100644 --- a/src/core/RecyclerListView.tsx +++ b/src/core/RecyclerListView.tsx @@ -21,9 +21,10 @@ import debounce = require("lodash.debounce"); import * as PropTypes from "prop-types"; import * as React from "react"; +import { List } from 'immutable'; import { ObjectUtil, Default } from "ts-object-utils"; import ContextProvider from "./dependencies/ContextProvider"; -import { BaseDataProvider } from "./dependencies/DataProvider"; +import { BaseDataProvider, ListBaseDataProvider } from "./dependencies/DataProvider"; import { Dimension, BaseLayoutProvider } from "./dependencies/LayoutProvider"; import CustomError from "./exceptions/CustomError"; import RecyclerListViewExceptions from "./exceptions/RecyclerListViewExceptions"; @@ -78,8 +79,8 @@ export interface OnRecreateParams { export interface RecyclerListViewProps { layoutProvider: BaseLayoutProvider; - dataProvider: BaseDataProvider; - rowRenderer: (type: string | number, data: any, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | null; + dataProvider: BaseDataProvider | ListBaseDataProvider; + rowRenderer: (type: string | number, data: any, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | List | null; contextProvider?: ContextProvider; renderAheadOffset?: number; isHorizontal?: boolean; @@ -671,7 +672,7 @@ RecyclerListView.propTypes = { layoutProvider: PropTypes.instanceOf(BaseLayoutProvider).isRequired, //Refer the sample - dataProvider: PropTypes.instanceOf(BaseDataProvider).isRequired, + dataProvider: PropTypes.oneOf([PropTypes.instanceOf(BaseDataProvider).isRequired, PropTypes.instanceOf(ListBaseDataProvider).isRequired]), //Used to maintain scroll position in case view gets destroyed e.g, cases of back navigation contextProvider: PropTypes.instanceOf(ContextProvider), diff --git a/src/core/VirtualRenderer.ts b/src/core/VirtualRenderer.ts index c6cdfc95..dbb801f2 100644 --- a/src/core/VirtualRenderer.ts +++ b/src/core/VirtualRenderer.ts @@ -6,7 +6,7 @@ import { Point, LayoutManager } from "./layoutmanager/LayoutManager"; import ViewabilityTracker, { TOnItemStatusChanged, WindowCorrection } from "./ViewabilityTracker"; import { ObjectUtil, Default } from "ts-object-utils"; import TSCast from "../utils/TSCast"; -import { BaseDataProvider } from "./dependencies/DataProvider"; +import { BaseDataProvider, ListBaseDataProvider } from "./dependencies/DataProvider"; /*** * Renderer which keeps track of recyclable items and the currently rendered items. Notifies list view to re render if something changes, like scroll offset @@ -248,7 +248,7 @@ export default class VirtualRenderer { } //Further optimize in later revision, pretty fast for now considering this is a low frequency event - public handleDataSetChange(newDataProvider: BaseDataProvider, shouldOptimizeForAnimations?: boolean): void { + public handleDataSetChange(newDataProvider: BaseDataProvider | ListBaseDataProvider, shouldOptimizeForAnimations?: boolean): void { const getStableId = newDataProvider.getStableId; const maxIndex = newDataProvider.getSize() - 1; const activeStableIds: { [key: string]: number } = {}; diff --git a/src/core/dependencies/DataProvider.ts b/src/core/dependencies/DataProvider.ts index 5fffb4ea..89d96159 100644 --- a/src/core/dependencies/DataProvider.ts +++ b/src/core/dependencies/DataProvider.ts @@ -1,37 +1,41 @@ +import { List } from 'immutable'; import { ObjectUtil } from "ts-object-utils"; /*** * You can create a new instance or inherit and override default methods * Allows access to data and size. Clone with rows creates a new data provider and let listview know where to calculate row layout from. */ -export abstract class BaseDataProvider { - public rowHasChanged: (r1: any, r2: any) => boolean; - - // In JS context make sure stable id is a string - public getStableId: (index: number) => string; - private _firstIndexToProcess: number = 0; - private _size: number = 0; - private _data: any[] = []; - private _hasStableIds = false; - private _requiresDataChangeHandling = false; - - constructor(rowHasChanged: (r1: any, r2: any) => boolean, getStableId?: (index: number) => string) { +export abstract class GenericDataProvider { + protected _data: K; // Require Init Data + public rowHasChanged: (r1: T, r2: T) => boolean; + public getStableId: (index: number) => string; // In JS context make sure stable id is a string + + protected _firstIndexToProcess: number = 0; + protected _size: number = 0; + protected _hasStableIds = false; + protected _requiresDataChangeHandling = false; + + constructor(initData: K, + rowHasChanged: (r1: T, r2: T ) => boolean, + getStableId?: (index: number ) => string ) { + this._data = initData; this.rowHasChanged = rowHasChanged; if (getStableId) { - this.getStableId = getStableId; + this.getStableId = getStableId; this._hasStableIds = true; } else { this.getStableId = (index) => index.toString(); } } - public abstract newInstance(rowHasChanged: (r1: any, r2: any) => boolean, getStableId?: (index: number) => string): BaseDataProvider; - - public getDataForIndex(index: number): any { - return this._data[index]; - } + public abstract newInstance( + rowHasChanged: (r1: T, r2: T) => boolean, + getStableId?: (index: number) => string ): GenericDataProvider; + public abstract getDataForIndex(index: number): T | undefined; + public abstract cloneWithRows(newData: K, + firstModifiedIndex?: number): DataProvider | ListDataProvider; - public getAllData(): any[] { + public getAllData(): K { return this._data; } @@ -50,24 +54,44 @@ export abstract class BaseDataProvider { public getFirstIndexToProcessInternal(): number { return this._firstIndexToProcess; } +} + + +export abstract class BaseDataProvider extends GenericDataProvider { + constructor(rowHasChanged: (r1: any, r2: any ) => boolean, + getStableId?: (index: number) => string) { + super([], rowHasChanged, getStableId); + } + + public abstract newInstance( + rowHasChanged: (r1: any, r2: any ) => boolean, + getStableId?: (index: number) => string ): BaseDataProvider; + + public getDataForIndex(index: number): any | undefined { + return this._data[index]; + } + + private getFirstIndexChange(newData: any[], newSize: number): number { + const iterCount = Math.min(this._size, newSize); + let i = 0; + for (i = 0; i < iterCount; i++) { + if (this.rowHasChanged(this._data[i], newData[i])) { + break; + } + } + return i; + } //No need to override this one //If you already know the first row where rowHasChanged will be false pass it upfront to avoid loop public cloneWithRows(newData: any[], firstModifiedIndex?: number): DataProvider { - const dp = this.newInstance(this.rowHasChanged, this.getStableId); + const dp = this.newInstance(this.rowHasChanged, this.getStableId); const newSize = newData.length; - const iterCount = Math.min(this._size, newSize); - if (ObjectUtil.isNullOrUndefined(firstModifiedIndex)) { - let i = 0; - for (i = 0; i < iterCount; i++) { - if (this.rowHasChanged(this._data[i], newData[i])) { - break; - } - } - dp._firstIndexToProcess = i; - } else { - dp._firstIndexToProcess = Math.max(Math.min(firstModifiedIndex, this._data.length), 0); - } + + dp._firstIndexToProcess = ObjectUtil.isNullOrUndefined(firstModifiedIndex) + ? this.getFirstIndexChange(newData, newSize) + : Math.max(Math.min(firstModifiedIndex, this._data.length), 0); + if (dp._firstIndexToProcess !== this._data.length) { dp._requiresDataChangeHandling = true; } @@ -77,8 +101,65 @@ export abstract class BaseDataProvider { } } -export default class DataProvider extends BaseDataProvider { - public newInstance(rowHasChanged: (r1: any, r2: any) => boolean, getStableId?: ((index: number) => string) | undefined): BaseDataProvider { - return new DataProvider(rowHasChanged, getStableId); +export abstract class ListBaseDataProvider extends GenericDataProvider> { + constructor(rowHasChanged: (r1: any, r2: any ) => boolean, + getStableId?: (index: number) => string) { + super(List([]), rowHasChanged, getStableId); + } + + public abstract newInstance( + rowHasChanged: (r1: any, r2: any) => boolean, + getStableId?: (index: number) => string ): ListBaseDataProvider; + + public getDataForIndex(index: number): any | undefined { + return this._data.get(index); + } + + private getFirstIndexChange(newData: List, newSize: number): number { + if(this._data.equals(newData)) { + return this._size; + } + + if(this._size > newSize) { + const sizeData = newData.setSize(this._size); + return (this._data as List) + .findIndex((value, index) => this.rowHasChanged(value, sizeData.get(index)!)); + } else { + const sizeData = this._data.setSize(newSize); + return (sizeData as List) + .findIndex((value, index) => this.rowHasChanged(value, newData.get(index )!)); + } } + + //No need to override this one + //If you already know the first row where rowHasChanged will be false pass it upfront to avoid loop + public cloneWithRows(newData: List, firstModifiedIndex?: number): ListDataProvider { + const dp = this.newInstance(this.rowHasChanged, this.getStableId); + const newSize = newData.size; + + dp._firstIndexToProcess = ObjectUtil.isNullOrUndefined(firstModifiedIndex) + ? this.getFirstIndexChange(newData, newSize) + : Math.max(Math.min(firstModifiedIndex, this._data.size), 0); + + if (dp._firstIndexToProcess !== this._data.size) { + dp._requiresDataChangeHandling = true; + } + dp._data = newData; + dp._size = newSize; + return dp; + } + } + +export default class DataProvider extends BaseDataProvider { + public newInstance(rowHasChanged: (r1: any, r2: any) => boolean, + getStableId?: ((index: number) => string) | undefined): BaseDataProvider { + return new DataProvider(rowHasChanged, getStableId); + } +} + +export class ListDataProvider extends ListBaseDataProvider { + public newInstance(rowHasChanged: (r1: any, r2: any) => boolean, + getStableId?: ((index: number) => string) | undefined): ListBaseDataProvider { + return new ListDataProvider(rowHasChanged, getStableId); + } } diff --git a/src/core/viewrenderer/BaseViewRenderer.tsx b/src/core/viewrenderer/BaseViewRenderer.tsx index 30fe4751..14aca921 100644 --- a/src/core/viewrenderer/BaseViewRenderer.tsx +++ b/src/core/viewrenderer/BaseViewRenderer.tsx @@ -1,4 +1,5 @@ import * as React from "react"; +import { List } from 'immutable'; import { Dimension, BaseLayoutProvider } from "../dependencies/LayoutProvider"; import ItemAnimator from "../ItemAnimator"; import { LayoutManager } from "../layoutmanager/LayoutManager"; @@ -15,7 +16,7 @@ export interface ViewRendererProps { y: number; height: number; width: number; - childRenderer: (type: string | number, data: T, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | null; + childRenderer: (type: string | number, data: T, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | List | null; layoutType: string | number; dataHasChanged: (r1: T, r2: T) => boolean; onSizeChanged: (dim: Dimension, index: number) => void; @@ -61,7 +62,7 @@ export default abstract class BaseViewRenderer extends ComponentCompat | null { return this.props.childRenderer(this.props.layoutType, this.props.data, this.props.index, this.props.extendedState); } } diff --git a/src/index.ts b/src/index.ts index e1344c4e..073a03da 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import ContextProvider from "./core/dependencies/ContextProvider"; -import DataProvider, { BaseDataProvider } from "./core/dependencies/DataProvider"; +import DataProvider, { BaseDataProvider, ListDataProvider, ListBaseDataProvider } from "./core/dependencies/DataProvider"; import { BaseLayoutProvider, Dimension, LayoutProvider } from "./core/dependencies/LayoutProvider"; import { GridLayoutProvider } from "./core/dependencies/GridLayoutProvider"; import RecyclerListView, { OnRecreateParams } from "./core/RecyclerListView"; @@ -15,6 +15,7 @@ import { ComponentCompat } from "./utils/ComponentCompat"; export { ContextProvider, DataProvider, + ListDataProvider, LayoutProvider, BaseLayoutProvider, LayoutManager, @@ -32,5 +33,6 @@ export { OnRecreateParams, DebugHandlers, BaseDataProvider, + ListBaseDataProvider, ComponentCompat, }; From 9ec179ab51f96f1b5fcf36ad10a945fe17311857 Mon Sep 17 00:00:00 2001 From: alstjr7375 Date: Sun, 24 May 2020 11:31:01 +0900 Subject: [PATCH 2/4] Fix tslint --- src/core/RecyclerListView.tsx | 20 +++--- src/core/dependencies/DataProvider.ts | 77 +++++++++++----------- src/core/viewrenderer/BaseViewRenderer.tsx | 2 +- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/core/RecyclerListView.tsx b/src/core/RecyclerListView.tsx index 9c66c262..2f45adac 100644 --- a/src/core/RecyclerListView.tsx +++ b/src/core/RecyclerListView.tsx @@ -21,7 +21,7 @@ import debounce = require("lodash.debounce"); import * as PropTypes from "prop-types"; import * as React from "react"; -import { List } from 'immutable'; +import { List } from "immutable"; import { ObjectUtil, Default } from "ts-object-utils"; import ContextProvider from "./dependencies/ContextProvider"; import { BaseDataProvider, ListBaseDataProvider } from "./dependencies/DataProvider"; @@ -39,11 +39,11 @@ import ItemAnimator, { BaseItemAnimator } from "./ItemAnimator"; import { DebugHandlers } from ".."; import { ComponentCompat } from "../utils/ComponentCompat"; //#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"; +//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,10 +51,10 @@ 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"; -//const IS_WEB = true; +import ScrollComponent from "../platform/web/scrollcomponent/ScrollComponent"; +import ViewRenderer from "../platform/web/viewrenderer/ViewRenderer"; +import { DefaultWebItemAnimator as DefaultItemAnimator } from "../platform/web/itemanimators/DefaultWebItemAnimator"; +const IS_WEB = true; //#endif /*** diff --git a/src/core/dependencies/DataProvider.ts b/src/core/dependencies/DataProvider.ts index 89d96159..c4e42454 100644 --- a/src/core/dependencies/DataProvider.ts +++ b/src/core/dependencies/DataProvider.ts @@ -1,4 +1,4 @@ -import { List } from 'immutable'; +import { List } from "immutable"; import { ObjectUtil } from "ts-object-utils"; /*** @@ -6,9 +6,9 @@ import { ObjectUtil } from "ts-object-utils"; * Allows access to data and size. Clone with rows creates a new data provider and let listview know where to calculate row layout from. */ export abstract class GenericDataProvider { - protected _data: K; // Require Init Data public rowHasChanged: (r1: T, r2: T) => boolean; - public getStableId: (index: number) => string; // In JS context make sure stable id is a string + public getStableId: (index: number) => string; // In JS context make sure stable id is a string + protected _data: K; // Require Init Data protected _firstIndexToProcess: number = 0; protected _size: number = 0; @@ -16,8 +16,8 @@ export abstract class GenericDataProvider { protected _requiresDataChangeHandling = false; constructor(initData: K, - rowHasChanged: (r1: T, r2: T ) => boolean, - getStableId?: (index: number ) => string ) { + rowHasChanged: (r1: T, r2: T) => boolean, + getStableId?: (index: number) => string ) { this._data = initData; this.rowHasChanged = rowHasChanged; if (getStableId) { @@ -56,32 +56,20 @@ export abstract class GenericDataProvider { } } - export abstract class BaseDataProvider extends GenericDataProvider { - constructor(rowHasChanged: (r1: any, r2: any ) => boolean, - getStableId?: (index: number) => string) { + constructor(rowHasChanged: (r1: any, r2: any) => boolean, + getStableId?: (index: number) => string) { super([], rowHasChanged, getStableId); } public abstract newInstance( - rowHasChanged: (r1: any, r2: any ) => boolean, - getStableId?: (index: number) => string ): BaseDataProvider; + rowHasChanged: (r1: any, r2: any) => boolean, + getStableId?: (index: number) => string): BaseDataProvider; public getDataForIndex(index: number): any | undefined { return this._data[index]; } - private getFirstIndexChange(newData: any[], newSize: number): number { - const iterCount = Math.min(this._size, newSize); - let i = 0; - for (i = 0; i < iterCount; i++) { - if (this.rowHasChanged(this._data[i], newData[i])) { - break; - } - } - return i; - } - //No need to override this one //If you already know the first row where rowHasChanged will be false pass it upfront to avoid loop public cloneWithRows(newData: any[], firstModifiedIndex?: number): DataProvider { @@ -99,38 +87,33 @@ export abstract class BaseDataProvider extends GenericDataProvider { dp._size = newSize; return dp; } + + private getFirstIndexChange(newData: any[], newSize: number): number { + const iterCount = Math.min(this._size, newSize); + let i = 0; + for (i = 0; i < iterCount; i++) { + if (this.rowHasChanged(this._data[i], newData[i])) { + break; + } + } + return i; + } } export abstract class ListBaseDataProvider extends GenericDataProvider> { constructor(rowHasChanged: (r1: any, r2: any ) => boolean, - getStableId?: (index: number) => string) { + getStableId?: (index: number) => string) { super(List([]), rowHasChanged, getStableId); } public abstract newInstance( rowHasChanged: (r1: any, r2: any) => boolean, - getStableId?: (index: number) => string ): ListBaseDataProvider; + getStableId?: (index: number) => string): ListBaseDataProvider; public getDataForIndex(index: number): any | undefined { return this._data.get(index); } - private getFirstIndexChange(newData: List, newSize: number): number { - if(this._data.equals(newData)) { - return this._size; - } - - if(this._size > newSize) { - const sizeData = newData.setSize(this._size); - return (this._data as List) - .findIndex((value, index) => this.rowHasChanged(value, sizeData.get(index)!)); - } else { - const sizeData = this._data.setSize(newSize); - return (sizeData as List) - .findIndex((value, index) => this.rowHasChanged(value, newData.get(index )!)); - } - } - //No need to override this one //If you already know the first row where rowHasChanged will be false pass it upfront to avoid loop public cloneWithRows(newData: List, firstModifiedIndex?: number): ListDataProvider { @@ -148,6 +131,22 @@ export abstract class ListBaseDataProvider extends GenericDataProvider, newSize: number): number { + if (this._data.equals(newData)) { + return this._size; + } + + if (this._size > newSize) { + const sizeData = newData.setSize(this._size); + return (this._data as List) + .findIndex((value, index) => this.rowHasChanged(value, sizeData.get(index)!)); + } else { + const sizeData = this._data.setSize(newSize); + return (sizeData as List) + .findIndex((value, index) => this.rowHasChanged(value, newData.get(index )!)); + } + } } export default class DataProvider extends BaseDataProvider { diff --git a/src/core/viewrenderer/BaseViewRenderer.tsx b/src/core/viewrenderer/BaseViewRenderer.tsx index 14aca921..fddee790 100644 --- a/src/core/viewrenderer/BaseViewRenderer.tsx +++ b/src/core/viewrenderer/BaseViewRenderer.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { List } from 'immutable'; +import { List } from "immutable"; import { Dimension, BaseLayoutProvider } from "../dependencies/LayoutProvider"; import ItemAnimator from "../ItemAnimator"; import { LayoutManager } from "../layoutmanager/LayoutManager"; From 4a83eea8e9ff7c24c18cdb90ed06d88cf3cf98b6 Mon Sep 17 00:00:00 2001 From: alstjr7375 Date: Sun, 24 May 2020 12:00:58 +0900 Subject: [PATCH 3/4] Fix List type --- src/core/RecyclerListView.tsx | 18 +++++++++--------- src/core/StickyContainer.tsx | 12 +++++++----- src/core/sticky/StickyObject.tsx | 10 ++++++---- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/core/RecyclerListView.tsx b/src/core/RecyclerListView.tsx index 2f45adac..4bb8c5a0 100644 --- a/src/core/RecyclerListView.tsx +++ b/src/core/RecyclerListView.tsx @@ -39,11 +39,11 @@ import ItemAnimator, { BaseItemAnimator } from "./ItemAnimator"; import { DebugHandlers } from ".."; import { ComponentCompat } from "../utils/ComponentCompat"; //#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"; +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,10 +51,10 @@ import { ComponentCompat } from "../utils/ComponentCompat"; */ //#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"; -const IS_WEB = true; +//import ScrollComponent from "../platform/web/scrollcomponent/ScrollComponent"; +//import ViewRenderer from "../platform/web/viewrenderer/ViewRenderer"; +//import { DefaultWebItemAnimator as DefaultItemAnimator } from "../platform/web/itemanimators/DefaultWebItemAnimator"; +//const IS_WEB = true; //#endif /*** diff --git a/src/core/StickyContainer.tsx b/src/core/StickyContainer.tsx index c78ff3a6..c089d818 100644 --- a/src/core/StickyContainer.tsx +++ b/src/core/StickyContainer.tsx @@ -5,6 +5,7 @@ import * as React from "react"; import * as PropTypes from "prop-types"; import { StyleProp, View, ViewStyle } from "react-native"; +import { List } from "immutable"; import RecyclerListView, { RecyclerListViewState, RecyclerListViewProps } from "./RecyclerListView"; import { ScrollEvent } from "./scrollcomponent/BaseScrollView"; import StickyObject, { StickyObjectProps } from "./sticky/StickyObject"; @@ -14,7 +15,7 @@ import CustomError from "./exceptions/CustomError"; import RecyclerListViewExceptions from "./exceptions/RecyclerListViewExceptions"; import { Layout } from "./layoutmanager/LayoutManager"; import { BaseLayoutProvider, Dimension } from "./dependencies/LayoutProvider"; -import { BaseDataProvider } from "./dependencies/DataProvider"; +import { BaseDataProvider, ListBaseDataProvider } from "./dependencies/DataProvider"; import { ReactElement } from "react"; import { ComponentCompat } from "../utils/ComponentCompat"; import { WindowCorrection } from "./ViewabilityTracker"; @@ -23,7 +24,8 @@ export interface StickyContainerProps { children: RecyclerChild; stickyHeaderIndices?: number[]; stickyFooterIndices?: number[]; - overrideRowRenderer?: (type: string | number | undefined, data: any, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | null; + overrideRowRenderer?: (type: string | number | undefined, + data: any, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | List | null; applyWindowCorrection?: (offsetX: number, offsetY: number, winowCorrection: WindowCorrection) => void; renderStickyContainer?: (stickyContent: JSX.Element, index: number, extendedState?: object) => JSX.Element | null; style?: StyleProp; @@ -35,10 +37,10 @@ export interface RecyclerChild extends React.ReactElement export default class StickyContainer

extends ComponentCompat

{ public static propTypes = {}; private _recyclerRef: RecyclerListView | undefined = undefined; - private _dataProvider: BaseDataProvider; + private _dataProvider: BaseDataProvider | ListBaseDataProvider; private _layoutProvider: BaseLayoutProvider; private _extendedState: object | undefined; - private _rowRenderer: ((type: string | number, data: any, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | null); + private _rowRenderer: ((type: string | number, data: any, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | List | null); private _stickyHeaderRef: StickyHeader | null = null; private _stickyFooterRef: StickyFooter | null = null; private _visibleIndicesAll: number[] = []; @@ -204,7 +206,7 @@ export default class StickyContainer

extends Com } private _getRowRenderer = (): ((type: string | number, data: any, index: number, extendedState?: object) - => JSX.Element | JSX.Element[] | null) => { + => JSX.Element | JSX.Element[] | List | null) => { return this._rowRenderer; } diff --git a/src/core/sticky/StickyObject.tsx b/src/core/sticky/StickyObject.tsx index 53164861..113bc7a4 100644 --- a/src/core/sticky/StickyObject.tsx +++ b/src/core/sticky/StickyObject.tsx @@ -4,6 +4,7 @@ import * as React from "react"; import { Animated, StyleProp, ViewStyle } from "react-native"; +import { List } from "immutable"; import { Layout } from "../layoutmanager/LayoutManager"; import { Dimension } from "../dependencies/LayoutProvider"; import RecyclerListViewExceptions from "../exceptions/RecyclerListViewExceptions"; @@ -23,8 +24,9 @@ export interface StickyObjectProps { getExtendedState: () => object | undefined; getRLVRenderedSize: () => Dimension | undefined; getContentDimension: () => Dimension | undefined; - getRowRenderer: () => ((type: string | number, data: any, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | null); - overrideRowRenderer?: (type: string | number | undefined, data: any, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | null; + getRowRenderer: () => ((type: string | number, data: any, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | List | null); + overrideRowRenderer?: (type: string | number | undefined, + data: any, index: number, extendedState?: object) => JSX.Element | JSX.Element[] | List | null; renderContainer?: ((rowContent: JSX.Element, index: number, extendState?: object) => JSX.Element | null); getWindowCorrection?: () => WindowCorrection; } @@ -229,12 +231,12 @@ export default abstract class StickyObject

extends this._largestVisibleIndex = indicesArray[indicesArray.length - 1]; } - private _renderSticky(): JSX.Element | JSX.Element[] | null { + private _renderSticky(): JSX.Element | JSX.Element[] | List | null { const _stickyData: any = this.props.getDataForIndex(this.currentStickyIndex); const _stickyLayoutType: string | number = this.props.getLayoutTypeForIndex(this.currentStickyIndex); const _extendedState: object | undefined = this.props.getExtendedState(); const _rowRenderer: ((type: string | number, data: any, index: number, extendedState?: object) - => JSX.Element | JSX.Element[] | null) = this.props.getRowRenderer(); + => JSX.Element | JSX.Element[] | List | null) = this.props.getRowRenderer(); if (this.props.overrideRowRenderer) { return this.props.overrideRowRenderer(_stickyLayoutType, _stickyData, this.currentStickyIndex, _extendedState); } else { From 2aa0e013dba7b25f91d42697f1caded162b7f71b Mon Sep 17 00:00:00 2001 From: alstjr7375 Date: Mon, 25 May 2020 03:29:57 +0900 Subject: [PATCH 4/4] Clean code style --- src/core/dependencies/DataProvider.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/dependencies/DataProvider.ts b/src/core/dependencies/DataProvider.ts index c4e42454..9783e34a 100644 --- a/src/core/dependencies/DataProvider.ts +++ b/src/core/dependencies/DataProvider.ts @@ -30,7 +30,7 @@ export abstract class GenericDataProvider { public abstract newInstance( rowHasChanged: (r1: T, r2: T) => boolean, - getStableId?: (index: number) => string ): GenericDataProvider; + getStableId?: (index: number) => string ): GenericDataProvider; public abstract getDataForIndex(index: number): T | undefined; public abstract cloneWithRows(newData: K, firstModifiedIndex?: number): DataProvider | ListDataProvider; @@ -58,13 +58,13 @@ export abstract class GenericDataProvider { export abstract class BaseDataProvider extends GenericDataProvider { constructor(rowHasChanged: (r1: any, r2: any) => boolean, - getStableId?: (index: number) => string) { + getStableId?: (index: number) => string ) { super([], rowHasChanged, getStableId); } public abstract newInstance( rowHasChanged: (r1: any, r2: any) => boolean, - getStableId?: (index: number) => string): BaseDataProvider; + getStableId?: (index: number) => string ): BaseDataProvider; public getDataForIndex(index: number): any | undefined { return this._data[index]; @@ -102,13 +102,13 @@ export abstract class BaseDataProvider extends GenericDataProvider { export abstract class ListBaseDataProvider extends GenericDataProvider> { constructor(rowHasChanged: (r1: any, r2: any ) => boolean, - getStableId?: (index: number) => string) { + getStableId?: (index: number) => string ) { super(List([]), rowHasChanged, getStableId); } public abstract newInstance( rowHasChanged: (r1: any, r2: any) => boolean, - getStableId?: (index: number) => string): ListBaseDataProvider; + getStableId?: (index: number) => string ): ListBaseDataProvider; public getDataForIndex(index: number): any | undefined { return this._data.get(index); @@ -151,14 +151,14 @@ export abstract class ListBaseDataProvider extends GenericDataProvider boolean, - getStableId?: ((index: number) => string) | undefined): BaseDataProvider { + getStableId?: ((index: number) => string ) | undefined): BaseDataProvider { return new DataProvider(rowHasChanged, getStableId); } } export class ListDataProvider extends ListBaseDataProvider { public newInstance(rowHasChanged: (r1: any, r2: any) => boolean, - getStableId?: ((index: number) => string) | undefined): ListBaseDataProvider { + getStableId?: ((index: number) => string ) | undefined): ListBaseDataProvider { return new ListDataProvider(rowHasChanged, getStableId); } }