@shopify/flash-list 2.0.0-rc.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -97
- package/dist/AnimatedFlashList.js +2 -2
- package/dist/AnimatedFlashList.js.map +1 -1
- package/dist/FlashList.d.ts +1 -167
- package/dist/FlashList.d.ts.map +1 -1
- package/dist/FlashList.js +3 -595
- package/dist/FlashList.js.map +1 -1
- package/dist/FlashListProps.d.ts +7 -63
- package/dist/FlashListProps.d.ts.map +1 -1
- package/dist/FlashListProps.js.map +1 -1
- package/dist/__tests__/LayoutCommitObserver.test.d.ts +2 -0
- package/dist/__tests__/LayoutCommitObserver.test.d.ts.map +1 -0
- package/dist/__tests__/LayoutCommitObserver.test.js +35 -0
- package/dist/__tests__/LayoutCommitObserver.test.js.map +1 -0
- package/dist/__tests__/ViewabilityHelper.test.js +3 -4
- package/dist/__tests__/ViewabilityHelper.test.js.map +1 -1
- package/dist/benchmark/JSFPSMonitor.d.ts.map +1 -1
- package/dist/benchmark/JSFPSMonitor.js +2 -1
- package/dist/benchmark/JSFPSMonitor.js.map +1 -1
- package/dist/benchmark/useBenchmark.d.ts +2 -4
- package/dist/benchmark/useBenchmark.d.ts.map +1 -1
- package/dist/benchmark/useBenchmark.js +12 -49
- package/dist/benchmark/useBenchmark.js.map +1 -1
- package/dist/benchmark/useFlatListBenchmark.d.ts.map +1 -1
- package/dist/benchmark/useFlatListBenchmark.js +2 -1
- package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
- package/dist/errors/ErrorMessages.d.ts +16 -0
- package/dist/errors/ErrorMessages.d.ts.map +1 -0
- package/dist/errors/ErrorMessages.js +19 -0
- package/dist/errors/ErrorMessages.js.map +1 -0
- package/dist/errors/WarningMessages.d.ts +4 -0
- package/dist/errors/WarningMessages.d.ts.map +1 -0
- package/dist/errors/WarningMessages.js +7 -0
- package/dist/errors/WarningMessages.js.map +1 -0
- package/dist/index.d.ts +4 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -29
- package/dist/index.js.map +1 -1
- package/dist/isNewArch.d.ts +2 -0
- package/dist/isNewArch.d.ts.map +1 -0
- package/dist/isNewArch.js +25 -0
- package/dist/isNewArch.js.map +1 -0
- package/dist/native/config/PlatformHelper.android.d.ts +1 -22
- package/dist/native/config/PlatformHelper.android.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.android.js +1 -16
- package/dist/native/config/PlatformHelper.android.js.map +1 -1
- package/dist/native/config/PlatformHelper.d.ts +1 -22
- package/dist/native/config/PlatformHelper.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.ios.d.ts +1 -22
- package/dist/native/config/PlatformHelper.ios.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.ios.js +1 -15
- package/dist/native/config/PlatformHelper.ios.js.map +1 -1
- package/dist/native/config/PlatformHelper.js +1 -16
- package/dist/native/config/PlatformHelper.js.map +1 -1
- package/dist/native/config/PlatformHelper.web.d.ts +1 -23
- package/dist/native/config/PlatformHelper.web.d.ts.map +1 -1
- package/dist/native/config/PlatformHelper.web.js +1 -18
- package/dist/native/config/PlatformHelper.web.js.map +1 -1
- package/dist/recyclerview/LayoutCommitObserver.d.ts +12 -0
- package/dist/recyclerview/LayoutCommitObserver.d.ts.map +1 -0
- package/dist/recyclerview/LayoutCommitObserver.js +62 -0
- package/dist/recyclerview/LayoutCommitObserver.js.map +1 -0
- package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerView.js +20 -9
- package/dist/recyclerview/RecyclerView.js.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.d.ts +4 -1
- package/dist/recyclerview/RecyclerViewManager.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.js +43 -34
- package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
- package/dist/recyclerview/RecyclerViewProps.d.ts +1 -8
- package/dist/recyclerview/RecyclerViewProps.d.ts.map +1 -1
- package/dist/recyclerview/ViewHolderCollection.d.ts +6 -2
- package/dist/recyclerview/ViewHolderCollection.d.ts.map +1 -1
- package/dist/recyclerview/ViewHolderCollection.js +3 -1
- package/dist/recyclerview/ViewHolderCollection.js.map +1 -1
- package/dist/recyclerview/hooks/useBoundDetection.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useBoundDetection.js +38 -7
- package/dist/recyclerview/hooks/useBoundDetection.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.js +16 -9
- package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
- package/dist/recyclerview/layout-managers/LayoutManager.d.ts.map +1 -1
- package/dist/recyclerview/layout-managers/LayoutManager.js +2 -1
- package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
- package/dist/recyclerview/viewability/ViewToken.d.ts.map +1 -0
- package/dist/recyclerview/viewability/ViewToken.js.map +1 -0
- package/dist/{viewability → recyclerview/viewability}/ViewabilityHelper.d.ts +2 -2
- package/dist/recyclerview/viewability/ViewabilityHelper.d.ts.map +1 -0
- package/dist/{viewability → recyclerview/viewability}/ViewabilityHelper.js +2 -4
- package/dist/{viewability → recyclerview/viewability}/ViewabilityHelper.js.map +1 -1
- package/dist/{viewability → recyclerview/viewability}/ViewabilityManager.d.ts +3 -3
- package/dist/recyclerview/viewability/ViewabilityManager.d.ts.map +1 -0
- package/dist/{viewability → recyclerview/viewability}/ViewabilityManager.js +16 -16
- package/dist/recyclerview/viewability/ViewabilityManager.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -14
- package/src/AnimatedFlashList.ts +2 -2
- package/src/FlashList.ts +1 -0
- package/src/FlashListProps.ts +8 -79
- package/src/__tests__/LayoutCommitObserver.test.tsx +60 -0
- package/src/__tests__/ViewabilityHelper.test.ts +13 -14
- package/src/benchmark/JSFPSMonitor.ts +3 -3
- package/src/benchmark/useBenchmark.ts +12 -77
- package/src/benchmark/useFlatListBenchmark.ts +3 -1
- package/src/errors/ErrorMessages.ts +26 -0
- package/src/errors/WarningMessages.ts +4 -0
- package/src/index.ts +11 -43
- package/src/isNewArch.ts +25 -0
- package/src/native/config/PlatformHelper.android.ts +1 -25
- package/src/native/config/PlatformHelper.ios.ts +1 -24
- package/src/native/config/PlatformHelper.ts +1 -25
- package/src/native/config/PlatformHelper.web.ts +1 -30
- package/src/recyclerview/LayoutCommitObserver.tsx +74 -0
- package/src/recyclerview/RecyclerView.tsx +25 -12
- package/src/recyclerview/RecyclerViewManager.ts +40 -40
- package/src/recyclerview/RecyclerViewProps.ts +1 -11
- package/src/recyclerview/ViewHolderCollection.tsx +9 -2
- package/src/recyclerview/hooks/useBoundDetection.ts +48 -6
- package/src/recyclerview/hooks/useRecyclerViewController.tsx +19 -14
- package/src/recyclerview/layout-managers/LayoutManager.ts +2 -1
- package/src/{viewability → recyclerview/viewability}/ViewabilityHelper.ts +8 -9
- package/src/{viewability → recyclerview/viewability}/ViewabilityManager.ts +18 -20
- package/RNFlashList.podspec +0 -37
- package/android/build.gradle +0 -89
- package/android/src/main/AndroidManifest.xml +0 -3
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutShadow.kt +0 -105
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutView.kt +0 -158
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/AutoLayoutViewManager.kt +0 -70
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/BlankAreaEvent.kt +0 -29
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainer.java +0 -16
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerImpl.kt +0 -16
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/CellContainerManager.kt +0 -34
- package/android/src/main/kotlin/com/shopify/reactnative/flash_list/FlashListPackage.kt +0 -19
- package/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerDelegate.java +0 -47
- package/android/src/paper/java/com/facebook/react/viewmanagers/AutoLayoutViewManagerInterface.java +0 -21
- package/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerDelegate.java +0 -32
- package/android/src/paper/java/com/facebook/react/viewmanagers/CellContainerManagerInterface.java +0 -16
- package/android/src/test/java/com/shopify/reactnative/flash_list/AutoLayoutShadowTest.kt +0 -147
- package/android/src/test/java/com/shopify/reactnative/flash_list/models/Rect.kt +0 -61
- package/android/src/test/java/com/shopify/reactnative/flash_list/models/TestCollection.kt +0 -6
- package/android/src/test/java/com/shopify/reactnative/flash_list/models/TestDataModel.kt +0 -8
- package/android/src/test/resources/LayoutTestData.json +0 -788
- package/dist/GridLayoutProviderWithProps.d.ts +0 -42
- package/dist/GridLayoutProviderWithProps.d.ts.map +0 -1
- package/dist/GridLayoutProviderWithProps.js +0 -114
- package/dist/GridLayoutProviderWithProps.js.map +0 -1
- package/dist/MasonryFlashList.d.ts +0 -51
- package/dist/MasonryFlashList.d.ts.map +0 -1
- package/dist/MasonryFlashList.js +0 -252
- package/dist/MasonryFlashList.js.map +0 -1
- package/dist/PureComponentWrapper.d.ts +0 -22
- package/dist/PureComponentWrapper.d.ts.map +0 -1
- package/dist/PureComponentWrapper.js +0 -37
- package/dist/PureComponentWrapper.js.map +0 -1
- package/dist/__tests__/ContentContainerUtils.test.d.ts +0 -2
- package/dist/__tests__/ContentContainerUtils.test.d.ts.map +0 -1
- package/dist/__tests__/ContentContainerUtils.test.js +0 -85
- package/dist/__tests__/ContentContainerUtils.test.js.map +0 -1
- package/dist/__tests__/FlashList.test.d.ts +0 -2
- package/dist/__tests__/FlashList.test.d.ts.map +0 -1
- package/dist/__tests__/FlashList.test.js +0 -902
- package/dist/__tests__/FlashList.test.js.map +0 -1
- package/dist/__tests__/GridLayoutProviderWithProps.test.d.ts +0 -2
- package/dist/__tests__/GridLayoutProviderWithProps.test.d.ts.map +0 -1
- package/dist/__tests__/GridLayoutProviderWithProps.test.js +0 -143
- package/dist/__tests__/GridLayoutProviderWithProps.test.js.map +0 -1
- package/dist/__tests__/MasonryFlashList.test.d.ts +0 -2
- package/dist/__tests__/MasonryFlashList.test.d.ts.map +0 -1
- package/dist/__tests__/MasonryFlashList.test.js +0 -254
- package/dist/__tests__/MasonryFlashList.test.js.map +0 -1
- package/dist/__tests__/PlatformHelper.web.test.d.ts +0 -2
- package/dist/__tests__/PlatformHelper.web.test.d.ts.map +0 -1
- package/dist/__tests__/PlatformHelper.web.test.js +0 -33
- package/dist/__tests__/PlatformHelper.web.test.js.map +0 -1
- package/dist/__tests__/helpers/mountFlashList.d.ts +0 -19
- package/dist/__tests__/helpers/mountFlashList.d.ts.map +0 -1
- package/dist/__tests__/helpers/mountFlashList.js +0 -44
- package/dist/__tests__/helpers/mountFlashList.js.map +0 -1
- package/dist/__tests__/helpers/mountMasonryFlashList.d.ts +0 -18
- package/dist/__tests__/helpers/mountMasonryFlashList.d.ts.map +0 -1
- package/dist/__tests__/helpers/mountMasonryFlashList.js +0 -49
- package/dist/__tests__/helpers/mountMasonryFlashList.js.map +0 -1
- package/dist/__tests__/useBlankAreaTracker.test.d.ts +0 -2
- package/dist/__tests__/useBlankAreaTracker.test.d.ts.map +0 -1
- package/dist/__tests__/useBlankAreaTracker.test.js +0 -179
- package/dist/__tests__/useBlankAreaTracker.test.js.map +0 -1
- package/dist/benchmark/useBlankAreaTracker.d.ts +0 -34
- package/dist/benchmark/useBlankAreaTracker.d.ts.map +0 -1
- package/dist/benchmark/useBlankAreaTracker.js +0 -66
- package/dist/benchmark/useBlankAreaTracker.js.map +0 -1
- package/dist/enableNewCore.d.ts +0 -3
- package/dist/enableNewCore.d.ts.map +0 -1
- package/dist/enableNewCore.js +0 -25
- package/dist/enableNewCore.js.map +0 -1
- package/dist/errors/CustomError.d.ts +0 -8
- package/dist/errors/CustomError.d.ts.map +0 -1
- package/dist/errors/CustomError.js +0 -14
- package/dist/errors/CustomError.js.map +0 -1
- package/dist/errors/ExceptionList.d.ts +0 -24
- package/dist/errors/ExceptionList.d.ts.map +0 -1
- package/dist/errors/ExceptionList.js +0 -26
- package/dist/errors/ExceptionList.js.map +0 -1
- package/dist/errors/Warnings.d.ts +0 -9
- package/dist/errors/Warnings.d.ts.map +0 -1
- package/dist/errors/Warnings.js +0 -13
- package/dist/errors/Warnings.js.map +0 -1
- package/dist/native/auto-layout/AutoLayoutView.d.ts +0 -22
- package/dist/native/auto-layout/AutoLayoutView.d.ts.map +0 -1
- package/dist/native/auto-layout/AutoLayoutView.js +0 -48
- package/dist/native/auto-layout/AutoLayoutView.js.map +0 -1
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.d.ts +0 -4
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.d.ts.map +0 -1
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.js +0 -6
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.js.map +0 -1
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.d.ts +0 -5
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.d.ts.map +0 -1
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.d.ts +0 -4
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.d.ts.map +0 -1
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.js +0 -6
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.js.map +0 -1
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.js +0 -6
- package/dist/native/auto-layout/AutoLayoutViewNativeComponent.js.map +0 -1
- package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.d.ts +0 -16
- package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.d.ts.map +0 -1
- package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.js +0 -3
- package/dist/native/auto-layout/AutoLayoutViewNativeComponentProps.js.map +0 -1
- package/dist/native/cell-container/CellContainer.android.d.ts +0 -6
- package/dist/native/cell-container/CellContainer.android.d.ts.map +0 -1
- package/dist/native/cell-container/CellContainer.android.js +0 -9
- package/dist/native/cell-container/CellContainer.android.js.map +0 -1
- package/dist/native/cell-container/CellContainer.d.ts +0 -8
- package/dist/native/cell-container/CellContainer.d.ts.map +0 -1
- package/dist/native/cell-container/CellContainer.ios.d.ts +0 -6
- package/dist/native/cell-container/CellContainer.ios.d.ts.map +0 -1
- package/dist/native/cell-container/CellContainer.ios.js +0 -9
- package/dist/native/cell-container/CellContainer.ios.js.map +0 -1
- package/dist/native/cell-container/CellContainer.js +0 -11
- package/dist/native/cell-container/CellContainer.js.map +0 -1
- package/dist/native/cell-container/CellContainer.web.d.ts +0 -7
- package/dist/native/cell-container/CellContainer.web.d.ts.map +0 -1
- package/dist/native/cell-container/CellContainer.web.js +0 -13
- package/dist/native/cell-container/CellContainer.web.js.map +0 -1
- package/dist/specs/AutoLayoutNativeComponent.d.ts +0 -18
- package/dist/specs/AutoLayoutNativeComponent.d.ts.map +0 -1
- package/dist/specs/AutoLayoutNativeComponent.js +0 -6
- package/dist/specs/AutoLayoutNativeComponent.js.map +0 -1
- package/dist/specs/CellContainerNativeComponent.d.ts +0 -8
- package/dist/specs/CellContainerNativeComponent.d.ts.map +0 -1
- package/dist/specs/CellContainerNativeComponent.js +0 -6
- package/dist/specs/CellContainerNativeComponent.js.map +0 -1
- package/dist/utils/ContentContainerUtils.d.ts +0 -27
- package/dist/utils/ContentContainerUtils.d.ts.map +0 -1
- package/dist/utils/ContentContainerUtils.js +0 -48
- package/dist/utils/ContentContainerUtils.js.map +0 -1
- package/dist/viewability/ViewToken.d.ts.map +0 -1
- package/dist/viewability/ViewToken.js.map +0 -1
- package/dist/viewability/ViewabilityHelper.d.ts.map +0 -1
- package/dist/viewability/ViewabilityManager.d.ts.map +0 -1
- package/dist/viewability/ViewabilityManager.js.map +0 -1
- package/ios/RNFlashList.xcodeproj/project.pbxproj +0 -3
- package/ios/RNFlashList.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -4
- package/ios/Sources/AutoLayoutView.swift +0 -294
- package/ios/Sources/AutoLayoutViewComponentView.h +0 -16
- package/ios/Sources/AutoLayoutViewComponentView.mm +0 -90
- package/ios/Sources/AutoLayoutViewManager.mm +0 -14
- package/ios/Sources/AutoLayoutViewManager.swift +0 -12
- package/ios/Sources/CellContainerComponentView.h +0 -18
- package/ios/Sources/CellContainerComponentView.mm +0 -62
- package/ios/Sources/CellContainerManager.mm +0 -8
- package/ios/Sources/CellContainerManager.swift +0 -12
- package/ios/Sources/FlatListPro-Bridging-Header.h +0 -11
- package/ios/Tests/AutoLayoutViewTests.swift +0 -113
- package/src/FlashList.tsx +0 -953
- package/src/GridLayoutProviderWithProps.ts +0 -180
- package/src/MasonryFlashList.tsx +0 -476
- package/src/PureComponentWrapper.tsx +0 -42
- package/src/__tests__/ContentContainerUtils.test.ts +0 -130
- package/src/__tests__/FlashList.test.tsx +0 -1001
- package/src/__tests__/GridLayoutProviderWithProps.test.ts +0 -179
- package/src/__tests__/MasonryFlashList.test.ts +0 -292
- package/src/__tests__/PlatformHelper.web.test.ts +0 -45
- package/src/__tests__/helpers/mountFlashList.tsx +0 -62
- package/src/__tests__/helpers/mountMasonryFlashList.tsx +0 -70
- package/src/__tests__/useBlankAreaTracker.test.tsx +0 -206
- package/src/benchmark/useBlankAreaTracker.ts +0 -117
- package/src/enableNewCore.ts +0 -24
- package/src/errors/CustomError.ts +0 -10
- package/src/errors/ExceptionList.ts +0 -28
- package/src/errors/Warnings.ts +0 -15
- package/src/native/auto-layout/AutoLayoutView.tsx +0 -73
- package/src/native/auto-layout/AutoLayoutViewNativeComponent.android.ts +0 -7
- package/src/native/auto-layout/AutoLayoutViewNativeComponent.ios.ts +0 -7
- package/src/native/auto-layout/AutoLayoutViewNativeComponent.ts +0 -7
- package/src/native/auto-layout/AutoLayoutViewNativeComponentProps.ts +0 -17
- package/src/native/cell-container/CellContainer.android.ts +0 -7
- package/src/native/cell-container/CellContainer.ios.ts +0 -7
- package/src/native/cell-container/CellContainer.tsx +0 -14
- package/src/native/cell-container/CellContainer.web.tsx +0 -9
- package/src/specs/AutoLayoutNativeComponent.ts +0 -24
- package/src/specs/CellContainerNativeComponent.ts +0 -9
- package/src/utils/ContentContainerUtils.ts +0 -92
- /package/dist/{viewability → recyclerview/viewability}/ViewToken.d.ts +0 -0
- /package/dist/{viewability → recyclerview/viewability}/ViewToken.js +0 -0
- /package/src/{viewability → recyclerview/viewability}/ViewToken.ts +0 -0
|
@@ -21,6 +21,7 @@ import { adjustOffsetForRTL } from "../utils/adjustOffsetForRTL";
|
|
|
21
21
|
import { RVLayout } from "../layout-managers/LayoutManager";
|
|
22
22
|
import { ScrollAnchorRef } from "../components/ScrollAnchor";
|
|
23
23
|
import { PlatformConfig } from "../../native/config/PlatformHelper";
|
|
24
|
+
import { WarningMessages } from "../../errors/WarningMessages";
|
|
24
25
|
|
|
25
26
|
import { useUnmountFlag } from "./useUnmountFlag";
|
|
26
27
|
import { useUnmountAwareTimeout } from "./useUnmountAwareCallbacks";
|
|
@@ -90,10 +91,9 @@ export function useRecyclerViewController<T>(
|
|
|
90
91
|
);
|
|
91
92
|
|
|
92
93
|
const computeFirstVisibleIndexForOffsetCorrection = useCallback(() => {
|
|
93
|
-
const { data, keyExtractor } = recyclerViewManager.props;
|
|
94
94
|
if (
|
|
95
95
|
recyclerViewManager.getIsFirstLayoutComplete() &&
|
|
96
|
-
|
|
96
|
+
recyclerViewManager.hasStableDataKeys() &&
|
|
97
97
|
recyclerViewManager.getDataLength() > 0 &&
|
|
98
98
|
recyclerViewManager.shouldMaintainVisibleContentPosition()
|
|
99
99
|
) {
|
|
@@ -103,10 +103,8 @@ export function useRecyclerViewController<T>(
|
|
|
103
103
|
recyclerViewManager.computeVisibleIndices().startIndex
|
|
104
104
|
);
|
|
105
105
|
if (firstVisibleIndex !== undefined && firstVisibleIndex >= 0) {
|
|
106
|
-
firstVisibleItemKey.current =
|
|
107
|
-
|
|
108
|
-
firstVisibleIndex
|
|
109
|
-
);
|
|
106
|
+
firstVisibleItemKey.current =
|
|
107
|
+
recyclerViewManager.getDataKey(firstVisibleIndex);
|
|
110
108
|
firstVisibleItemLayout.current = {
|
|
111
109
|
...recyclerViewManager.getLayout(firstVisibleIndex),
|
|
112
110
|
};
|
|
@@ -120,7 +118,7 @@ export function useRecyclerViewController<T>(
|
|
|
120
118
|
* the user's current view position when new messages are added.
|
|
121
119
|
*/
|
|
122
120
|
const applyOffsetCorrection = useCallback(() => {
|
|
123
|
-
const { horizontal, data
|
|
121
|
+
const { horizontal, data } = recyclerViewManager.props;
|
|
124
122
|
|
|
125
123
|
// Execute all pending callbacks from previous scroll offset updates
|
|
126
124
|
// This ensures any scroll operations that were waiting for render are completed
|
|
@@ -132,7 +130,7 @@ export function useRecyclerViewController<T>(
|
|
|
132
130
|
|
|
133
131
|
if (
|
|
134
132
|
recyclerViewManager.getIsFirstLayoutComplete() &&
|
|
135
|
-
|
|
133
|
+
recyclerViewManager.hasStableDataKeys() &&
|
|
136
134
|
currentDataLength > 0 &&
|
|
137
135
|
recyclerViewManager.shouldMaintainVisibleContentPosition()
|
|
138
136
|
) {
|
|
@@ -144,13 +142,14 @@ export function useRecyclerViewController<T>(
|
|
|
144
142
|
.getEngagedIndices()
|
|
145
143
|
.findValue(
|
|
146
144
|
(index) =>
|
|
147
|
-
|
|
145
|
+
recyclerViewManager.getDataKey(index) ===
|
|
148
146
|
firstVisibleItemKey.current
|
|
149
147
|
) ??
|
|
150
148
|
(hasDataChanged
|
|
151
149
|
? data?.findIndex(
|
|
152
150
|
(item, index) =>
|
|
153
|
-
|
|
151
|
+
recyclerViewManager.getDataKey(index) ===
|
|
152
|
+
firstVisibleItemKey.current
|
|
154
153
|
)
|
|
155
154
|
: undefined);
|
|
156
155
|
|
|
@@ -281,10 +280,13 @@ export function useRecyclerViewController<T>(
|
|
|
281
280
|
scrollToEnd: async ({ animated }: ScrollToEdgeParams = {}) => {
|
|
282
281
|
const { data } = recyclerViewManager.props;
|
|
283
282
|
if (data && data.length > 0) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
283
|
+
const lastIndex = data.length - 1;
|
|
284
|
+
if (!recyclerViewManager.getEngagedIndices().includes(lastIndex)) {
|
|
285
|
+
await handlerMethods.scrollToIndex({
|
|
286
|
+
index: lastIndex,
|
|
287
|
+
animated,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
288
290
|
}
|
|
289
291
|
setTimeout(() => {
|
|
290
292
|
scrollViewRef.current!.scrollToEnd({ animated });
|
|
@@ -547,6 +549,9 @@ export function useRecyclerViewController<T>(
|
|
|
547
549
|
* Disables item recycling in preparation for layout animations.
|
|
548
550
|
*/
|
|
549
551
|
prepareForLayoutAnimationRender: () => {
|
|
552
|
+
if (!recyclerViewManager.props.keyExtractor) {
|
|
553
|
+
console.warn(WarningMessages.keyExtractorNotDefinedForAnimation);
|
|
554
|
+
}
|
|
550
555
|
recyclerViewManager.animationOptimizationsEnabled = true;
|
|
551
556
|
},
|
|
552
557
|
};
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
findLastVisibleIndex,
|
|
8
8
|
} from "../utils/findVisibleIndex";
|
|
9
9
|
import { areDimensionsNotEqual } from "../utils/measureLayout";
|
|
10
|
+
import { ErrorMessages } from "../../errors/ErrorMessages";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Base abstract class for layout managers in the recycler view system.
|
|
@@ -224,7 +225,7 @@ export abstract class RVLayoutManager {
|
|
|
224
225
|
*/
|
|
225
226
|
getLayout(index: number): RVLayout {
|
|
226
227
|
if (index >= this.layouts.length) {
|
|
227
|
-
throw new Error(
|
|
228
|
+
throw new Error(ErrorMessages.indexOutOfBounds);
|
|
228
229
|
}
|
|
229
230
|
let layout = this.layouts[index];
|
|
230
231
|
if (!layout) {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { ViewabilityConfig } from "react-native";
|
|
2
|
-
import { Dimension, Layout } from "recyclerlistview";
|
|
3
2
|
|
|
4
|
-
import
|
|
5
|
-
import
|
|
3
|
+
import { RVDimension, RVLayout } from "../layout-managers/LayoutManager";
|
|
4
|
+
import { ErrorMessages } from "../../errors/ErrorMessages";
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Helper class for computing viewable items based on the passed `viewabilityConfig`.
|
|
@@ -48,8 +47,8 @@ class ViewabilityHelper {
|
|
|
48
47
|
public updateViewableItems(
|
|
49
48
|
horizontal: boolean,
|
|
50
49
|
scrollOffset: number,
|
|
51
|
-
listSize:
|
|
52
|
-
getLayout: (index: number) =>
|
|
50
|
+
listSize: RVDimension,
|
|
51
|
+
getLayout: (index: number) => RVLayout | undefined,
|
|
53
52
|
viewableIndices?: number[]
|
|
54
53
|
) {
|
|
55
54
|
if (viewableIndices !== undefined) {
|
|
@@ -61,8 +60,8 @@ class ViewabilityHelper {
|
|
|
61
60
|
this.viewabilityConfig?.viewAreaCoveragePercentThreshold !== null &&
|
|
62
61
|
this.viewabilityConfig?.viewAreaCoveragePercentThreshold !== undefined
|
|
63
62
|
) {
|
|
64
|
-
throw new
|
|
65
|
-
|
|
63
|
+
throw new Error(
|
|
64
|
+
ErrorMessages.multipleViewabilityThresholdTypesNotSupported
|
|
66
65
|
);
|
|
67
66
|
}
|
|
68
67
|
if (
|
|
@@ -126,10 +125,10 @@ class ViewabilityHelper {
|
|
|
126
125
|
index: number,
|
|
127
126
|
horizontal: boolean,
|
|
128
127
|
scrollOffset: number,
|
|
129
|
-
listSize:
|
|
128
|
+
listSize: RVDimension,
|
|
130
129
|
viewAreaCoveragePercentThreshold: number | null | undefined,
|
|
131
130
|
itemVisiblePercentThreshold: number | null | undefined,
|
|
132
|
-
getLayout: (index: number) =>
|
|
131
|
+
getLayout: (index: number) => RVLayout | undefined
|
|
133
132
|
) {
|
|
134
133
|
const itemLayout = getLayout(index);
|
|
135
134
|
if (itemLayout === undefined) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ViewabilityConfig } from "react-native";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { RecyclerViewManager } from "../RecyclerViewManager";
|
|
4
4
|
|
|
5
5
|
import ViewabilityHelper from "./ViewabilityHelper";
|
|
6
6
|
import ViewToken from "./ViewToken";
|
|
@@ -9,31 +9,31 @@ import ViewToken from "./ViewToken";
|
|
|
9
9
|
* Manager for viewability tracking. It holds multiple viewability callback pairs and keeps them updated.
|
|
10
10
|
*/
|
|
11
11
|
export default class ViewabilityManager<T> {
|
|
12
|
-
private
|
|
12
|
+
private rvManager: RecyclerViewManager<T>;
|
|
13
13
|
private viewabilityHelpers: ViewabilityHelper[] = [];
|
|
14
14
|
private hasInteracted = false;
|
|
15
15
|
|
|
16
|
-
constructor(
|
|
17
|
-
this.
|
|
16
|
+
constructor(rvManager: RecyclerViewManager<T>) {
|
|
17
|
+
this.rvManager = rvManager;
|
|
18
18
|
if (
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
rvManager.props.onViewableItemsChanged !== null &&
|
|
20
|
+
rvManager.props.onViewableItemsChanged !== undefined
|
|
21
21
|
) {
|
|
22
22
|
this.viewabilityHelpers.push(
|
|
23
23
|
this.createViewabilityHelper(
|
|
24
|
-
|
|
24
|
+
rvManager.props.viewabilityConfig,
|
|
25
25
|
(info) => {
|
|
26
|
-
|
|
26
|
+
rvManager.props.onViewableItemsChanged?.(info);
|
|
27
27
|
}
|
|
28
28
|
)
|
|
29
29
|
);
|
|
30
30
|
}
|
|
31
|
-
(
|
|
31
|
+
(rvManager.props.viewabilityConfigCallbackPairs ?? []).forEach(
|
|
32
32
|
(pair, index) => {
|
|
33
33
|
this.viewabilityHelpers.push(
|
|
34
34
|
this.createViewabilityHelper(pair.viewabilityConfig, (info) => {
|
|
35
35
|
const callback =
|
|
36
|
-
|
|
36
|
+
rvManager.props.viewabilityConfigCallbackPairs?.[index]
|
|
37
37
|
?.onViewableItemsChanged;
|
|
38
38
|
callback?.(info);
|
|
39
39
|
})
|
|
@@ -71,21 +71,19 @@ export default class ViewabilityManager<T> {
|
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
public updateViewableItems = (newViewableIndices?: number[]) => {
|
|
74
|
-
const listSize =
|
|
75
|
-
this.flashListRef.getWindowSize() ??
|
|
76
|
-
this.flashListRef.props.estimatedListSize;
|
|
74
|
+
const listSize = this.rvManager.getWindowSize();
|
|
77
75
|
if (listSize === undefined || !this.shouldListenToVisibleIndices) {
|
|
78
76
|
return;
|
|
79
77
|
}
|
|
80
78
|
const scrollOffset =
|
|
81
|
-
(this.
|
|
82
|
-
this.
|
|
79
|
+
(this.rvManager.getAbsoluteLastScrollOffset() ?? 0) -
|
|
80
|
+
this.rvManager.firstItemOffset;
|
|
83
81
|
this.viewabilityHelpers.forEach((viewabilityHelper) => {
|
|
84
82
|
viewabilityHelper.updateViewableItems(
|
|
85
|
-
this.
|
|
83
|
+
this.rvManager.props.horizontal ?? false,
|
|
86
84
|
scrollOffset,
|
|
87
85
|
listSize,
|
|
88
|
-
(index: number) => this.
|
|
86
|
+
(index: number) => this.rvManager.getLayout(index),
|
|
89
87
|
newViewableIndices
|
|
90
88
|
);
|
|
91
89
|
});
|
|
@@ -117,11 +115,11 @@ export default class ViewabilityManager<T> {
|
|
|
117
115
|
index: number,
|
|
118
116
|
isViewable: boolean
|
|
119
117
|
) => {
|
|
120
|
-
const item = this.
|
|
118
|
+
const item = this.rvManager.props.data![index];
|
|
121
119
|
const key =
|
|
122
|
-
item === undefined || this.
|
|
120
|
+
item === undefined || this.rvManager.props.keyExtractor === undefined
|
|
123
121
|
? index.toString()
|
|
124
|
-
: this.
|
|
122
|
+
: this.rvManager.props.keyExtractor(item, index);
|
|
125
123
|
return {
|
|
126
124
|
index,
|
|
127
125
|
isViewable,
|
package/RNFlashList.podspec
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
require 'json'
|
|
2
|
-
|
|
3
|
-
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
-
new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED']
|
|
5
|
-
|
|
6
|
-
Pod::Spec.new do |s|
|
|
7
|
-
s.name = 'RNFlashList'
|
|
8
|
-
s.version = package['version']
|
|
9
|
-
s.summary = package['description']
|
|
10
|
-
s.homepage = package['homepage']
|
|
11
|
-
s.license = package['license']
|
|
12
|
-
s.author = package['author']
|
|
13
|
-
s.platforms = { :ios => '11.0', :tvos => '12.0' }
|
|
14
|
-
s.source = { git: 'https://github.com/shopify/flash-list.git', tag: "v#{s.version}" }
|
|
15
|
-
s.source_files = 'ios/Sources/**/*'
|
|
16
|
-
s.requires_arc = true
|
|
17
|
-
s.swift_version = '5.0'
|
|
18
|
-
|
|
19
|
-
if new_arch_enabled
|
|
20
|
-
s.pod_target_xcconfig = {
|
|
21
|
-
'OTHER_SWIFT_FLAGS' => '-D RCT_NEW_ARCH_ENABLED',
|
|
22
|
-
}
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# install_modules_dependencies is available since RN 0.71
|
|
26
|
-
if respond_to?(:install_modules_dependencies, true)
|
|
27
|
-
install_modules_dependencies(s)
|
|
28
|
-
else
|
|
29
|
-
s.dependency "React-Core"
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Tests spec
|
|
33
|
-
s.test_spec 'Tests' do |test_spec|
|
|
34
|
-
test_spec.source_files = 'ios/Tests/**/*'
|
|
35
|
-
test_spec.framework = 'XCTest'
|
|
36
|
-
end
|
|
37
|
-
end
|
package/android/build.gradle
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
def isNewArchitectureEnabled() {
|
|
2
|
-
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
apply plugin: 'com.android.library'
|
|
6
|
-
|
|
7
|
-
apply plugin: 'kotlin-android'
|
|
8
|
-
|
|
9
|
-
if (isNewArchitectureEnabled()) {
|
|
10
|
-
apply plugin: 'com.facebook.react'
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
def _ext = rootProject.ext
|
|
14
|
-
|
|
15
|
-
def _reactNativeVersion = _ext.has('reactNative') ? _ext.reactNative : '+'
|
|
16
|
-
def _compileSdkVersion = _ext.has('compileSdkVersion') ? _ext.compileSdkVersion : 30
|
|
17
|
-
def _buildToolsVersion = _ext.has('buildToolsVersion') ? _ext.buildToolsVersion : '30.0.2'
|
|
18
|
-
def _minSdkVersion = _ext.has('minSdkVersion') ? _ext.minSdkVersion : 21
|
|
19
|
-
def _targetSdkVersion = _ext.has('targetSdkVersion') ? _ext.targetSdkVersion : 30
|
|
20
|
-
def _junitVersion = _ext.has('junitVersion') ? _ext.junitVersion : '4.13.2'
|
|
21
|
-
def _mockitoVersion = _ext.has('mockitoVersion') ? _ext.mockitoVersion : '3.2.0'
|
|
22
|
-
def _androidTestRunnerVersion = _ext.has('androidTestRunnerVersion') ? _ext.androidTestRunnerVersion : '1.1.0'
|
|
23
|
-
|
|
24
|
-
buildscript {
|
|
25
|
-
// buildscript is evaluated before any other task is executed, so this must be defined here
|
|
26
|
-
ext._kotlinVersion = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get('kotlinVersion') : '1.8.10'
|
|
27
|
-
|
|
28
|
-
repositories {
|
|
29
|
-
mavenCentral()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
dependencies {
|
|
33
|
-
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${_kotlinVersion}")
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
android {
|
|
38
|
-
compileSdkVersion _compileSdkVersion
|
|
39
|
-
buildToolsVersion _buildToolsVersion
|
|
40
|
-
|
|
41
|
-
// Conditional for compatibility with AGP <4.2.
|
|
42
|
-
if (project.android.hasProperty("namespace")) {
|
|
43
|
-
namespace = "com.shopify.reactnative.flash_list"
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
compileOptions {
|
|
47
|
-
sourceCompatibility JavaVersion.VERSION_1_8
|
|
48
|
-
targetCompatibility JavaVersion.VERSION_1_8
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
sourceSets {
|
|
52
|
-
main.java.srcDirs += 'src/main/kotlin'
|
|
53
|
-
debug.java.srcDirs += 'src/debug/kotlin'
|
|
54
|
-
test.java.srcDirs += 'src/test/kotlin'
|
|
55
|
-
androidTest.java.srcDirs += 'src/androidTest/kotlin'
|
|
56
|
-
|
|
57
|
-
if (!isNewArchitectureEnabled()) {
|
|
58
|
-
main.java.srcDirs += ['src/paper/java']
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
defaultConfig {
|
|
63
|
-
minSdkVersion _minSdkVersion
|
|
64
|
-
targetSdkVersion _targetSdkVersion
|
|
65
|
-
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
66
|
-
versionCode 1
|
|
67
|
-
versionName "1.0"
|
|
68
|
-
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
lintOptions {
|
|
72
|
-
abortOnError false
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
testOptions {
|
|
76
|
-
unitTests.returnDefaultValues = true
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
dependencies {
|
|
81
|
-
compileOnly "com.facebook.react:react-native:${_reactNativeVersion}"
|
|
82
|
-
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${_kotlinVersion}"
|
|
83
|
-
testImplementation "junit:junit:${_junitVersion}"
|
|
84
|
-
testImplementation "org.mockito.kotlin:mockito-kotlin:${_mockitoVersion}"
|
|
85
|
-
testImplementation "org.mockito:mockito-inline:${_mockitoVersion}"
|
|
86
|
-
testImplementation 'com.google.code.gson:gson:2.8.9'
|
|
87
|
-
androidTestImplementation("androidx.test:runner:${_androidTestRunnerVersion}")
|
|
88
|
-
androidTestImplementation("androidx.test:rules:${_androidTestRunnerVersion}")
|
|
89
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
package com.shopify.reactnative.flash_list
|
|
2
|
-
|
|
3
|
-
class AutoLayoutShadow {
|
|
4
|
-
var horizontal: Boolean = false
|
|
5
|
-
var scrollOffset: Int = 0
|
|
6
|
-
var offsetFromStart: Int = 0
|
|
7
|
-
var windowSize: Int = 0
|
|
8
|
-
var renderOffset = 0
|
|
9
|
-
|
|
10
|
-
var blankOffsetAtStart = 0 // Tracks blank area from the top
|
|
11
|
-
var blankOffsetAtEnd = 0 // Tracks blank area from the bottom
|
|
12
|
-
|
|
13
|
-
var lastMaxBoundOverall = 0 // Tracks where the last pixel is drawn in the overall
|
|
14
|
-
|
|
15
|
-
private var lastMaxBound = 0 // Tracks where the last pixel is drawn in the visible window
|
|
16
|
-
private var lastMinBound = 0 // Tracks where first pixel is drawn in the visible window
|
|
17
|
-
|
|
18
|
-
/** Checks for overlaps or gaps between adjacent items and then applies a correction (Only Grid layouts with varying spans)
|
|
19
|
-
* Performance: RecyclerListView renders very small number of views and this is not going to trigger multiple layouts on Android side. Not expecting any major perf issue. */
|
|
20
|
-
fun clearGapsAndOverlaps(sortedItems: Array<CellContainer>) {
|
|
21
|
-
var maxBound = 0
|
|
22
|
-
var minBound = Int.MAX_VALUE
|
|
23
|
-
var maxBoundNeighbour = 0
|
|
24
|
-
lastMaxBoundOverall = 0
|
|
25
|
-
for (i in 0 until sortedItems.size - 1) {
|
|
26
|
-
val cell = sortedItems[i]
|
|
27
|
-
val neighbour = sortedItems[i + 1]
|
|
28
|
-
// Only apply correction if the next cell is consecutive.
|
|
29
|
-
val isNeighbourConsecutive = neighbour.index == cell.index + 1
|
|
30
|
-
if (isWithinBounds(cell) || isWithinBounds(neighbour)) {
|
|
31
|
-
if (!horizontal) {
|
|
32
|
-
maxBound = kotlin.math.max(maxBound, cell.bottom);
|
|
33
|
-
minBound = kotlin.math.min(minBound, cell.top);
|
|
34
|
-
maxBoundNeighbour = maxBound
|
|
35
|
-
if (isNeighbourConsecutive) {
|
|
36
|
-
if (cell.left < neighbour.left) {
|
|
37
|
-
if (cell.right != neighbour.left) {
|
|
38
|
-
neighbour.right = cell.right + neighbour.width
|
|
39
|
-
neighbour.left = cell.right
|
|
40
|
-
}
|
|
41
|
-
if (cell.top != neighbour.top) {
|
|
42
|
-
neighbour.bottom = cell.top + neighbour.height
|
|
43
|
-
neighbour.top = cell.top
|
|
44
|
-
}
|
|
45
|
-
} else {
|
|
46
|
-
neighbour.bottom = maxBound + neighbour.height
|
|
47
|
-
neighbour.top = maxBound
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
if (isWithinBounds(neighbour)) {
|
|
51
|
-
maxBoundNeighbour = kotlin.math.max(maxBound, neighbour.bottom)
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
maxBound = kotlin.math.max(maxBound, cell.right);
|
|
55
|
-
minBound = kotlin.math.min(minBound, cell.left);
|
|
56
|
-
maxBoundNeighbour = maxBound
|
|
57
|
-
if (isNeighbourConsecutive) {
|
|
58
|
-
if (cell.top < neighbour.top) {
|
|
59
|
-
if (cell.bottom != neighbour.top) {
|
|
60
|
-
neighbour.bottom = cell.bottom + neighbour.height
|
|
61
|
-
neighbour.top = cell.bottom
|
|
62
|
-
}
|
|
63
|
-
if (cell.left != neighbour.left) {
|
|
64
|
-
neighbour.right = cell.left + neighbour.width
|
|
65
|
-
neighbour.left = cell.left
|
|
66
|
-
}
|
|
67
|
-
} else {
|
|
68
|
-
neighbour.right = maxBound + neighbour.width
|
|
69
|
-
neighbour.left = maxBound
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (isWithinBounds(neighbour)) {
|
|
73
|
-
maxBoundNeighbour = kotlin.math.max(maxBound, neighbour.right)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
lastMaxBoundOverall = kotlin.math.max(lastMaxBoundOverall, if (horizontal) cell.right else cell.bottom)
|
|
78
|
-
lastMaxBoundOverall = kotlin.math.max(lastMaxBoundOverall, if (horizontal) neighbour.right else neighbour.bottom)
|
|
79
|
-
}
|
|
80
|
-
lastMaxBound = maxBoundNeighbour
|
|
81
|
-
lastMinBound = minBound
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** Offset provided by react can be one frame behind the real one, it's important that this method is called with offset taken directly from
|
|
85
|
-
* scrollview object */
|
|
86
|
-
fun computeBlankFromGivenOffset(actualScrollOffset: Int, distanceFromWindowStart: Int, distanceFromWindowEnd: Int): Int {
|
|
87
|
-
val actualScrollOffset = actualScrollOffset - offsetFromStart;
|
|
88
|
-
blankOffsetAtStart = lastMinBound - actualScrollOffset - distanceFromWindowStart
|
|
89
|
-
blankOffsetAtEnd = actualScrollOffset + windowSize - renderOffset - lastMaxBound - distanceFromWindowEnd
|
|
90
|
-
return kotlin.math.max(blankOffsetAtStart, blankOffsetAtEnd)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** It's important to avoid correcting views outside the render window. An item that isn't being recycled might still remain in the view tree. If views outside get considered then gaps between
|
|
94
|
-
* unused items will cause algorithm to fail.*/
|
|
95
|
-
private fun isWithinBounds(cell: CellContainer): Boolean {
|
|
96
|
-
val scrollOffset = scrollOffset - offsetFromStart;
|
|
97
|
-
return if (!horizontal) {
|
|
98
|
-
(cell.top >= (scrollOffset - renderOffset) || cell.bottom >= (scrollOffset - renderOffset)) &&
|
|
99
|
-
(cell.top <= scrollOffset + windowSize || cell.bottom <= scrollOffset + windowSize)
|
|
100
|
-
} else {
|
|
101
|
-
(cell.left >= (scrollOffset - renderOffset) || cell.right >= (scrollOffset - renderOffset)) &&
|
|
102
|
-
(cell.left <= scrollOffset + windowSize || cell.right <= scrollOffset + windowSize)
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
package com.shopify.reactnative.flash_list
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import android.graphics.Canvas
|
|
5
|
-
import android.util.DisplayMetrics
|
|
6
|
-
import android.util.Log
|
|
7
|
-
import android.view.View
|
|
8
|
-
import android.view.ViewGroup
|
|
9
|
-
import android.widget.HorizontalScrollView
|
|
10
|
-
import android.widget.ScrollView
|
|
11
|
-
import com.facebook.react.bridge.Arguments
|
|
12
|
-
import com.facebook.react.bridge.ReactContext
|
|
13
|
-
import com.facebook.react.bridge.WritableMap
|
|
14
|
-
import com.facebook.react.uimanager.UIManagerHelper
|
|
15
|
-
import com.facebook.react.uimanager.events.EventDispatcher
|
|
16
|
-
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
17
|
-
import com.facebook.react.views.view.ReactViewGroup
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/** Container for all RecyclerListView children. This will automatically remove all gaps and overlaps for GridLayouts with flexible spans.
|
|
21
|
-
* Note: This cannot work for masonry layouts i.e, pinterest like layout */
|
|
22
|
-
class AutoLayoutView(context: Context) : ReactViewGroup(context) {
|
|
23
|
-
val alShadow = AutoLayoutShadow()
|
|
24
|
-
var enableInstrumentation = false
|
|
25
|
-
var disableAutoLayout = false
|
|
26
|
-
|
|
27
|
-
var pixelDensity = 1.0;
|
|
28
|
-
|
|
29
|
-
/** Overriding draw instead of onLayout. RecyclerListView uses absolute positions for each and every item which means that changes in child layouts may not trigger onLayout on this container. The same layout
|
|
30
|
-
* can still cause views to overlap. Therefore, it makes sense to override draw to do correction. */
|
|
31
|
-
override fun dispatchDraw(canvas: Canvas) {
|
|
32
|
-
fixLayout()
|
|
33
|
-
fixFooter()
|
|
34
|
-
super.dispatchDraw(canvas)
|
|
35
|
-
|
|
36
|
-
val parentScrollView = getParentScrollView()
|
|
37
|
-
if (enableInstrumentation && parentScrollView != null) {
|
|
38
|
-
/** Since we need to call this method with scrollOffset on the UI thread and not with the one react has we're querying parent's parent
|
|
39
|
-
directly which will be a ScrollView. If it isn't reported values will be incorrect but the component will not break.
|
|
40
|
-
RecyclerListView is expected not to change the hierarchy of children. */
|
|
41
|
-
|
|
42
|
-
val scrollContainerSize = if (alShadow.horizontal) parentScrollView.width else parentScrollView.height
|
|
43
|
-
|
|
44
|
-
val scrollOffset = if (alShadow.horizontal) parentScrollView.scrollX else parentScrollView.scrollY
|
|
45
|
-
|
|
46
|
-
val startOffset = if (alShadow.horizontal) left else top
|
|
47
|
-
val endOffset = if (alShadow.horizontal) right else bottom
|
|
48
|
-
|
|
49
|
-
val distanceFromWindowStart = kotlin.math.max(startOffset - scrollOffset, 0)
|
|
50
|
-
val distanceFromWindowEnd = kotlin.math.max(scrollOffset + scrollContainerSize - endOffset, 0)
|
|
51
|
-
|
|
52
|
-
alShadow.computeBlankFromGivenOffset(scrollOffset, distanceFromWindowStart, distanceFromWindowEnd)
|
|
53
|
-
emitBlankAreaEvent()
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** Sorts views by index and then invokes clearGaps which does the correction.
|
|
58
|
-
* Performance: Sort is needed. Given relatively low number of views in RecyclerListView render tree this should be a non issue.*/
|
|
59
|
-
private fun fixLayout() {
|
|
60
|
-
if (childCount > 1 && !disableAutoLayout) {
|
|
61
|
-
val positionSortedViews: Array<CellContainer> = Array(childCount) {
|
|
62
|
-
val child = getChildAt(it)
|
|
63
|
-
if (child is CellContainer) {
|
|
64
|
-
child
|
|
65
|
-
} else {
|
|
66
|
-
throw IllegalStateException("CellRendererComponent outer view should always be CellContainer. Learn more here: https://shopify.github.io/flash-list/docs/usage#cellrenderercomponent.")
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
positionSortedViews.sortBy { it.index }
|
|
70
|
-
alShadow.offsetFromStart = if (alShadow.horizontal) left else top
|
|
71
|
-
alShadow.clearGapsAndOverlaps(positionSortedViews)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** Fixes footer position along with rest of the items */
|
|
76
|
-
private fun fixFooter() {
|
|
77
|
-
val parentScrollView = getParentScrollView()
|
|
78
|
-
if (disableAutoLayout || parentScrollView == null) {
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
val isAutoLayoutEndVisible = if (alShadow.horizontal) right <= parentScrollView.width else bottom <= parentScrollView.height
|
|
82
|
-
if (!isAutoLayoutEndVisible) {
|
|
83
|
-
return
|
|
84
|
-
}
|
|
85
|
-
val autoLayoutParent = parent as? View
|
|
86
|
-
val footer = getFooter();
|
|
87
|
-
val diff = getFooterDiff()
|
|
88
|
-
if (diff == 0 || footer == null || autoLayoutParent == null) {
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (alShadow.horizontal) {
|
|
93
|
-
footer.offsetLeftAndRight(diff)
|
|
94
|
-
right += diff
|
|
95
|
-
autoLayoutParent.right += diff
|
|
96
|
-
} else {
|
|
97
|
-
footer.offsetTopAndBottom(diff)
|
|
98
|
-
bottom += diff
|
|
99
|
-
autoLayoutParent.bottom += diff
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private fun getFooterDiff(): Int {
|
|
104
|
-
if (childCount == 0) {
|
|
105
|
-
alShadow.lastMaxBoundOverall = 0
|
|
106
|
-
} else if (childCount == 1) {
|
|
107
|
-
val firstChild = getChildAt(0)
|
|
108
|
-
alShadow.lastMaxBoundOverall = if (alShadow.horizontal) {
|
|
109
|
-
firstChild.right
|
|
110
|
-
} else {
|
|
111
|
-
firstChild.bottom
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
val autoLayoutEnd = if (alShadow.horizontal) right - left else bottom - top
|
|
115
|
-
return alShadow.lastMaxBoundOverall - autoLayoutEnd
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
private fun getFooter(): View? {
|
|
119
|
-
return (parent as? ViewGroup)?.let {
|
|
120
|
-
for (i in 0 until it.childCount) {
|
|
121
|
-
val view = it.getChildAt(i)
|
|
122
|
-
if (view is CellContainer && view.index == -1) {
|
|
123
|
-
return@let view
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return@let null
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
private fun getParentScrollView(): View? {
|
|
131
|
-
var autoLayoutParent = parent;
|
|
132
|
-
while (autoLayoutParent != null) {
|
|
133
|
-
if (autoLayoutParent is ScrollView || autoLayoutParent is HorizontalScrollView) {
|
|
134
|
-
return autoLayoutParent as View
|
|
135
|
-
}
|
|
136
|
-
autoLayoutParent = autoLayoutParent.parent;
|
|
137
|
-
}
|
|
138
|
-
return null
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
private fun emitBlankAreaEvent() {
|
|
143
|
-
val eventDispatcher: EventDispatcher? =
|
|
144
|
-
UIManagerHelper.getEventDispatcherForReactTag(context as ReactContext, id)
|
|
145
|
-
|
|
146
|
-
if (eventDispatcher != null) {
|
|
147
|
-
val surfaceId = UIManagerHelper.getSurfaceId(context as ReactContext)
|
|
148
|
-
eventDispatcher.dispatchEvent(
|
|
149
|
-
BlankAreaEvent(
|
|
150
|
-
surfaceId,
|
|
151
|
-
viewTag = id,
|
|
152
|
-
offsetStart = alShadow.blankOffsetAtStart / pixelDensity,
|
|
153
|
-
offsetEnd = alShadow.blankOffsetAtEnd / pixelDensity
|
|
154
|
-
)
|
|
155
|
-
)
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|