@react-native-ohos/flash-list 1.8.3-rc.1 → 1.8.3-rc.2

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.
Files changed (75) hide show
  1. package/README.OpenSource +1 -1
  2. package/README.md +1 -1
  3. package/dist/AnimatedFlashList.d.ts +1 -4
  4. package/dist/AnimatedFlashList.d.ts.map +1 -1
  5. package/dist/FlashList.d.ts +3 -5
  6. package/dist/FlashList.d.ts.map +1 -1
  7. package/dist/FlashList.js +20 -23
  8. package/dist/FlashList.js.map +1 -1
  9. package/dist/GridLayoutProviderWithProps.js +1 -2
  10. package/dist/GridLayoutProviderWithProps.js.map +1 -1
  11. package/dist/MasonryFlashList.d.ts +1 -1
  12. package/dist/MasonryFlashList.d.ts.map +1 -1
  13. package/dist/MasonryFlashList.js.map +1 -1
  14. package/dist/PureComponentWrapper.d.ts +1 -1
  15. package/dist/PureComponentWrapper.js +1 -1
  16. package/dist/PureComponentWrapper.js.map +1 -1
  17. package/dist/benchmark/AutoScrollHelper.js +2 -2
  18. package/dist/benchmark/AutoScrollHelper.js.map +1 -1
  19. package/dist/benchmark/JSFPSMonitor.js.map +1 -1
  20. package/dist/benchmark/roundToDecimalPlaces.js +1 -2
  21. package/dist/benchmark/roundToDecimalPlaces.js.map +1 -1
  22. package/dist/benchmark/useBenchmark.js +2 -3
  23. package/dist/benchmark/useBenchmark.js.map +1 -1
  24. package/dist/benchmark/useBlankAreaTracker.js +1 -2
  25. package/dist/benchmark/useBlankAreaTracker.js.map +1 -1
  26. package/dist/benchmark/useDataMultiplier.js +1 -2
  27. package/dist/benchmark/useDataMultiplier.js.map +1 -1
  28. package/dist/benchmark/useFlatListBenchmark.d.ts +0 -1
  29. package/dist/benchmark/useFlatListBenchmark.d.ts.map +1 -1
  30. package/dist/benchmark/useFlatListBenchmark.js +1 -2
  31. package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
  32. package/dist/errors/CustomError.js.map +1 -1
  33. package/dist/fabric/AutoLayoutNativeComponent.d.ts.map +1 -1
  34. package/dist/fabric/CellContainerNativeComponent.d.ts.map +1 -1
  35. package/dist/index.js +4 -6
  36. package/dist/index.js.map +1 -1
  37. package/dist/native/auto-layout/AutoLayoutView.d.ts +1 -1
  38. package/dist/native/auto-layout/AutoLayoutView.d.ts.map +1 -1
  39. package/dist/native/auto-layout/AutoLayoutView.js +1 -1
  40. package/dist/native/auto-layout/AutoLayoutView.js.map +1 -1
  41. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.d.ts +1 -2
  42. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.android.d.ts.map +1 -1
  43. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.d.ts.map +1 -1
  44. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.harmony.d.ts +1 -2
  45. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.harmony.d.ts.map +1 -1
  46. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.d.ts +1 -2
  47. package/dist/native/auto-layout/AutoLayoutViewNativeComponent.ios.d.ts.map +1 -1
  48. package/dist/native/cell-container/CellContainer.android.d.ts +1 -1
  49. package/dist/native/cell-container/CellContainer.android.d.ts.map +1 -1
  50. package/dist/native/cell-container/CellContainer.d.ts +1 -2
  51. package/dist/native/cell-container/CellContainer.d.ts.map +1 -1
  52. package/dist/native/cell-container/CellContainer.harmony.d.ts +1 -1
  53. package/dist/native/cell-container/CellContainer.harmony.d.ts.map +1 -1
  54. package/dist/native/cell-container/CellContainer.ios.d.ts +1 -1
  55. package/dist/native/cell-container/CellContainer.ios.d.ts.map +1 -1
  56. package/dist/native/cell-container/CellContainer.web.d.ts +1 -2
  57. package/dist/native/cell-container/CellContainer.web.d.ts.map +1 -1
  58. package/dist/native/config/PlatformHelper.android.d.ts.map +1 -1
  59. package/dist/native/config/PlatformHelper.d.ts.map +1 -1
  60. package/dist/native/config/PlatformHelper.harmony.d.ts.map +1 -1
  61. package/dist/native/config/PlatformHelper.ios.d.ts.map +1 -1
  62. package/dist/native/config/PlatformHelper.web.d.ts.map +1 -1
  63. package/dist/tsconfig.tsbuildinfo +1 -1
  64. package/dist/utils/ContentContainerUtils.d.ts.map +1 -1
  65. package/dist/utils/ContentContainerUtils.js.map +1 -1
  66. package/dist/viewability/ViewabilityHelper.js.map +1 -1
  67. package/dist/viewability/ViewabilityManager.d.ts.map +1 -1
  68. package/dist/viewability/ViewabilityManager.js.map +1 -1
  69. package/harmony/flash_list/BuildProfile.ets +1 -1
  70. package/harmony/flash_list/oh-package.json5 +1 -1
  71. package/harmony/flash_list/src/main/cpp/AutoLayoutNode.cpp +106 -29
  72. package/harmony/flash_list.har +0 -0
  73. package/jestSetup.js +0 -1
  74. package/package.json +3 -3
  75. package/src/FlashList.tsx +18 -24
@@ -22,42 +22,119 @@
22
22
  * SOFTWARE.
23
23
  */
24
24
 
25
- #include "AutoLayoutNode.h"
26
- #include <memory>
25
+ #include <react/renderer/components/view/ViewProps.h>
27
26
  #include <glog/logging.h>
27
+ #include <sys/param.h>
28
+ #include <thread>
29
+ #include "AutoLayoutShadow.h"
30
+ #include <random>
28
31
 
29
32
  namespace rnoh {
30
33
 
31
- AutoLayoutNode::AutoLayoutNode()
32
- : ArkUINode(NativeNodeApi::getInstance()->createNode(ArkUI_NodeType::ARKUI_NODE_STACK)) {
33
- maybeThrow(NativeNodeApi::getInstance()->registerNodeEvent(m_nodeHandle, NODE_EVENT_ON_APPEAR, 0, this));
34
- }
35
-
36
- void AutoLayoutNode::insertChild(ArkUINode &child, std::size_t index) {
37
- maybeThrow(NativeNodeApi::getInstance()->insertChildAt(m_nodeHandle, child.getArkUINodeHandle(), index));
38
- }
39
-
40
- void AutoLayoutNode::removeChild(ArkUINode &child) {
41
- maybeThrow(NativeNodeApi::getInstance()->removeChild(m_nodeHandle, child.getArkUINodeHandle()));
42
- }
43
-
44
- void AutoLayoutNode::onNodeEvent(ArkUI_NodeEventType eventType, EventArgs &eventArgs) {
45
- if (eventType == ArkUI_NodeEventType::NODE_EVENT_ON_APPEAR) {
46
- m_autoLayoutNodeDelegate->onAppear();
34
+ /**checks for overlaps or gaps.between adjacent items and then applies a correction (Only Grid layouts with varying
35
+ * spans) Performance: RecyclerListView renders very small number of views and this is not going to trigger multiple
36
+ * layouts on Android side. Not expecting any major perf issu.*/
37
+ void AutoLayoutShadow::clearGapsAndOverlaps(std::vector<CellContainerComponentInstance::Shared> sortedItems) {
38
+ if (sortedItems.empty()) {
39
+ return;
47
40
  }
41
+ Float maxBound = 0;
42
+ Float minBound = INT_MAX;
43
+ Float maxBoundNeighbour = 0;
44
+ lastMaxBoundOverall = 0;
45
+ for (int i = 0; i < sortedItems.size() - 1; i++) {
46
+ auto cell = sortedItems[i];
47
+ auto neighbour = sortedItems[i + 1];
48
+ std::optional<facebook::react::LayoutMetrics> neighbourMetrics;
49
+ // Only apply correction if the next cell is consecutive.
50
+ bool isNeighbourConsecutive = neighbour->getIndex() == cell->getIndex() + 1;
51
+ if (isWithinBounds(cell->getLayoutMetrics())) {
52
+ if (!horizontal) {
53
+ maxBound = MAX(maxBound, cell->getBottom());
54
+ minBound = MIN(minBound, cell->getTop());
55
+ maxBoundNeighbour = maxBound;
56
+ if (isNeighbourConsecutive) {
57
+ neighbourMetrics = neighbour->getLayoutMetrics();
58
+ if (cell->getLeft() < neighbour->getLeft()) {
59
+ if (cell->getRight() != neighbour->getLeft()) {
60
+ neighbourMetrics.value().frame.origin.x = cell->getRight();
61
+ }
62
+ if (cell->getTop() != neighbour->getTop()) {
63
+ neighbourMetrics.value().frame.origin.y = cell->getTop();
64
+ }
65
+ } else {
66
+ neighbourMetrics.value().frame.origin.y = maxBound;
67
+ }
68
+ }
69
+ if (isWithinBounds(*neighbourMetrics)) {
70
+ float bottom = neighbourMetrics->frame.origin.y + neighbourMetrics->frame.size.height;
71
+ maxBoundNeighbour = MAX(maxBound, bottom);
72
+ }
73
+ } else {
74
+ maxBound = MAX(maxBound, cell->getRight());
75
+ minBound = MIN(minBound, cell->getLeft());
76
+ maxBoundNeighbour = maxBound;
77
+ if (isNeighbourConsecutive) {
78
+ neighbourMetrics = neighbour->getLayoutMetrics();
79
+ if (cell->getTop() < neighbour->getTop()) {
80
+ if (cell->getBottom() != neighbour->getTop()) {
81
+ neighbourMetrics.value().frame.origin.y = cell->getBottom();
82
+ }
83
+ if (cell->getLeft() != neighbour->getLeft()) {
84
+ neighbourMetrics.value().frame.origin.x = cell->getLeft();
85
+ }
86
+ } else {
87
+ neighbourMetrics.value().frame.origin.x = maxBound;
88
+ }
89
+ }
90
+ if (isWithinBounds(*neighbourMetrics)) {
91
+ float right = neighbourMetrics->frame.origin.x + neighbourMetrics->frame.size.width;
92
+ maxBoundNeighbour = MAX(maxBound, right);
93
+ }
94
+ }
95
+ }
96
+ if (horizontal) {
97
+ lastMaxBoundOverall = MAX(lastMaxBoundOverall, cell->getRight());
98
+ float right = neighbourMetrics->frame.origin.x + neighbourMetrics->frame.size.width;
99
+ lastMaxBoundOverall = MAX(lastMaxBoundOverall, neighbour->getRight());
100
+ } else {
101
+ lastMaxBoundOverall = MAX(lastMaxBoundOverall, cell->getBottom());
102
+ float bottom = neighbourMetrics->frame.origin.y + neighbourMetrics->frame.size.height;
103
+ lastMaxBoundOverall = MAX(lastMaxBoundOverall, bottom);
104
+ }
105
+ cell->setLayout(cell->getLayoutMetrics());
106
+ neighbour->setLayout(neighbourMetrics ? neighbourMetrics.value() : neighbour->getLayoutMetrics());
107
+ }
108
+ lastMaxBound = maxBoundNeighbour;
109
+ lastMinBound = minBound;
48
110
  }
49
111
 
50
- void AutoLayoutNode::setAutoLayoutNodeDelegate(AutoLayoutNodeDelegate *scrollNodeDelegate) {
51
- m_autoLayoutNodeDelegate = scrollNodeDelegate;
52
- }
53
-
54
- AutoLayoutNode::~AutoLayoutNode() {
55
- NativeNodeApi::getInstance()->unregisterNodeEvent(m_nodeHandle, NODE_EVENT_ON_APPEAR);
112
+ /** Offset provider by react can be one frame behind the real one, it's important that this method is called with
113
+ * offset taken directly from scrollview object*/
114
+ Float AutoLayoutShadow::computeBlankFromGivenOffset(Float actualScrollOffset, Float distanceFromWindowStart,
115
+ Float distanceFromWindowEnd) {
116
+ blankOffsetAtStart = lastMinBound - actualScrollOffset - distanceFromWindowStart;
117
+ blankOffsetAtEnd = actualScrollOffset + windowSize - renderOffset - lastMaxBound - distanceFromWindowEnd;
118
+ return MAX(blankOffsetAtStart, blankOffsetAtEnd);
56
119
  }
57
120
 
58
- void AutoLayoutNode::setAlign(int32_t align) {
59
- ArkUI_NumberValue value[] = {{.i32 = align}};
60
- ArkUI_AttributeItem item = {.value = value, .size = 1};
61
- maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_STACK_ALIGN_CONTENT, &item));
121
+ /**It's importance to aviod correcting views outside the render window. An item that isn't being recycled might
122
+ * still remain in the view tree. If views outside get considered then gaps between unused items will cause
123
+ * algorithm to fail.*/
124
+ bool AutoLayoutShadow::isWithinBounds(const facebook::react::LayoutMetrics& metrics) {
125
+ auto boundsStart = scrollOffset - renderOffset;
126
+ auto boundsEnd = scrollOffset + windowSize;
127
+ float top = metrics.frame.origin.y;
128
+ float bottom = metrics.frame.origin.y + metrics.frame.size.height;
129
+ float left = metrics.frame.origin.x;
130
+ float right = metrics.frame.origin.x + metrics.frame.size.width;
131
+
132
+ if (!this->horizontal) {
133
+ return (top >= boundsStart || bottom >= boundsStart) &&
134
+ (top <= boundsEnd || bottom <= boundsEnd);
135
+ } else {
136
+ return (left >= boundsStart || right >= boundsStart) &&
137
+ (left <= boundsEnd || right <= boundsEnd);
138
+ }
62
139
  }
63
- } // namespace rnoh
140
+ } // namespace rnoh
Binary file
package/jestSetup.js CHANGED
@@ -22,7 +22,6 @@
22
22
  * SOFTWARE.
23
23
  */
24
24
 
25
-
26
25
  jest.mock("@shopify/flash-list", () => {
27
26
  const ActualFlashList = jest.requireActual("@shopify/flash-list").FlashList;
28
27
  class MockFlashList extends ActualFlashList {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-ohos/flash-list",
3
- "version": "1.8.3-rc.1",
3
+ "version": "1.8.3-rc.2",
4
4
  "keywords": [
5
5
  "react-native",
6
6
  "recyclerview",
@@ -22,12 +22,12 @@
22
22
  },
23
23
  "repository": {
24
24
  "type": "git",
25
- "url": "https://github.com/react-native-oh-library/flash-list.git"
25
+ "url": "https://gitcode.com/openharmony-sig/rntpc_flash-list.git"
26
26
  },
27
27
  "description": "FlashList is a more performant FlatList replacement",
28
28
  "author": "shopify",
29
29
  "license": "MIT",
30
- "homepage": "https://shopify.github.io/flash-list/",
30
+ "homepage": "https://gitcode.com/openharmony-sig/rntpc_flash-list/tree/br_rnoh0.77#readme",
31
31
  "main": "dist/index.js",
32
32
  "types": "dist/index.d.ts",
33
33
  "scripts": {
package/src/FlashList.tsx CHANGED
@@ -82,6 +82,7 @@ export interface FlashListState<T> {
82
82
  data?: ReadonlyArray<T> | null;
83
83
  extraData?: ExtraData<unknown>;
84
84
  renderItem?: FlashListProps<T>["renderItem"];
85
+ lastInverted?: boolean;
85
86
  }
86
87
 
87
88
  interface ExtraData<T> {
@@ -95,10 +96,6 @@ class FlashList<T> extends React.PureComponent<
95
96
  private rlvRef?: RecyclerListView<RecyclerListViewProps, any>;
96
97
  private stickyContentContainerRef?: PureComponentWrapper;
97
98
  private listFixedDimensionSize = 0;
98
- private transformStyle = PlatformConfig.invertedTransformStyle;
99
- private transformStyleHorizontal =
100
- PlatformConfig.invertedTransformStyleHorizontal;
101
-
102
99
  private distanceFromWindow = 0;
103
100
  private contentStyle: ContentStyleExplicit = {
104
101
  paddingBottom: 0,
@@ -207,11 +204,13 @@ class FlashList<T> extends React.PureComponent<
207
204
  newState.layoutProvider.shouldRefreshWithAnchoring = Boolean(
208
205
  !prevState.layoutProvider?.hasExpired
209
206
  );
210
-
211
- if (nextProps.data !== prevState.data) {
212
- newState.data = nextProps.data;
207
+ if (nextProps.data !== prevState.data || prevState.lastInverted !== nextProps.inverted) {
208
+ const processedData = nextProps.inverted
209
+ ? (nextProps.data ? [...nextProps.data].reverse() : nextProps.data)
210
+ : nextProps.data;
211
+ newState.data = processedData;
213
212
  newState.dataProvider = prevState.dataProvider.cloneWithRows(
214
- nextProps.data as any[]
213
+ processedData as any[]
215
214
  );
216
215
  if (nextProps.renderItem !== prevState.renderItem) {
217
216
  newState.extraData = { ...prevState.extraData };
@@ -221,6 +220,7 @@ class FlashList<T> extends React.PureComponent<
221
220
  newState.extraData = { value: nextProps.extraData };
222
221
  }
223
222
  newState.renderItem = nextProps.renderItem;
223
+ newState.lastInverted = nextProps.inverted ?? undefined;
224
224
  return newState;
225
225
  }
226
226
 
@@ -287,6 +287,8 @@ class FlashList<T> extends React.PureComponent<
287
287
  numColumns,
288
288
  props.extraData
289
289
  );
290
+ console.log('mutableLayout:', mutableLayout);
291
+
290
292
  return mutableLayout?.size;
291
293
  },
292
294
  flashListProps
@@ -359,8 +361,8 @@ class FlashList<T> extends React.PureComponent<
359
361
  stickyHeaderIndices={stickyHeaderIndices}
360
362
  style={
361
363
  this.props.horizontal
362
- ? { ...this.getTransform() }
363
- : { flex: 1, overflow: "hidden", ...this.getTransform() }
364
+ ? { }
365
+ : { flex: 1, overflow: "hidden" }
364
366
  }
365
367
  >
366
368
  <ProgressiveListView
@@ -533,7 +535,6 @@ class FlashList<T> extends React.PureComponent<
533
535
  ...props.style,
534
536
  flexDirection: this.props.horizontal ? "row" : "column",
535
537
  alignItems: "stretch",
536
- ...this.getTransform(),
537
538
  ...getCellContainerPlatformStyles(this.props.inverted!!, parentProps),
538
539
  }}
539
540
  index={parentProps.index}
@@ -561,13 +562,6 @@ class FlashList<T> extends React.PureComponent<
561
562
  }
562
563
  };
563
564
 
564
- private getTransform() {
565
- const transformStyle = this.props.horizontal
566
- ? this.transformStyleHorizontal
567
- : this.transformStyle;
568
- return (this.props.inverted && transformStyle) || undefined;
569
- }
570
-
571
565
  private separator = (index: number) => {
572
566
  // Make sure we have data and don't read out of bounds
573
567
  if (
@@ -602,7 +596,7 @@ class FlashList<T> extends React.PureComponent<
602
596
  />
603
597
 
604
598
  <View
605
- style={[this.props.ListHeaderComponentStyle, this.getTransform()]}
599
+ style={[this.props.ListHeaderComponentStyle]}
606
600
  >
607
601
  {this.getValidComponent(this.props.ListHeaderComponent)}
608
602
  </View>
@@ -619,7 +613,7 @@ class FlashList<T> extends React.PureComponent<
619
613
  <>
620
614
  <FooterContainer
621
615
  index={-1}
622
- style={[this.props.ListFooterComponentStyle, this.getTransform()]}
616
+ style={[this.props.ListFooterComponentStyle]}
623
617
  >
624
618
  {this.getValidComponent(this.props.ListFooterComponent)}
625
619
  </FooterContainer>
@@ -674,7 +668,7 @@ class FlashList<T> extends React.PureComponent<
674
668
  private rowRendererWithIndex = (index: number, target: RenderTarget) => {
675
669
  // known issue: expected to pass separators which isn't available in RLV
676
670
  return this.props.renderItem?.({
677
- item: this.props.data![index],
671
+ item: this.state.data![index],
678
672
  index,
679
673
  target,
680
674
  extraData: this.state.extraData?.value,
@@ -693,7 +687,6 @@ class FlashList<T> extends React.PureComponent<
693
687
  private getCellContainerChild = (index: number) => {
694
688
  return (
695
689
  <>
696
- {this.props.inverted ? this.separator(index) : null}
697
690
  <View
698
691
  style={{
699
692
  flexDirection:
@@ -704,7 +697,7 @@ class FlashList<T> extends React.PureComponent<
704
697
  >
705
698
  {this.rowRendererWithIndex(index, RenderTargetOptions.Cell)}
706
699
  </View>
707
- {this.props.inverted ? null : this.separator(index)}
700
+ {this.separator(index)}
708
701
  </>
709
702
  );
710
703
  };
@@ -920,7 +913,8 @@ class FlashList<T> extends React.PureComponent<
920
913
  * @returns {Object} The layout of the item at the given index.
921
914
  */
922
915
  public getLayout(index: number) : Layout | undefined {
923
- return this.rlvRef?.getLayout(index);
916
+ const l = this.rlvRef?.getLayout(index);
917
+ return l;
924
918
  }
925
919
 
926
920
  /**