@react-native-oh/react-native-harmony 0.72.28 → 0.72.29
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TurboModule } from "react-native/Libraries/TurboModule/RCTExport";
|
|
2
|
-
import { TurboModuleRegistry, View, ViewProps } from "react-native";
|
|
2
|
+
import { Dimensions, TurboModuleRegistry, View, ViewProps } from "react-native";
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
4
|
import React from "react";
|
|
5
5
|
|
|
@@ -22,23 +22,68 @@ const safeAreaTurboModule = TurboModuleRegistry.get<Spec>(
|
|
|
22
22
|
"SafeAreaTurboModule"
|
|
23
23
|
)!;
|
|
24
24
|
|
|
25
|
+
const getPaddingTop = (inset: number, pageY: number) => {
|
|
26
|
+
return Math.max(0, inset - (pageY < 0 ? pageY * -1 : pageY));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const getPaddingBottom = (insetBottom: number, insetTop: number, paddingTop: number, height: number, windowHeight: number, pageY: number, positionY: number): number => {
|
|
30
|
+
// if SafeArea is not visible or outside the viewport or topped and not full height
|
|
31
|
+
if (height === 0 || (pageY === 0 && height < windowHeight)) {
|
|
32
|
+
return Math.max(0, insetBottom - (Math.round(windowHeight) - Math.round(height)));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// if SafeAreaView is not topped and not full height and not visible
|
|
36
|
+
if (pageY < windowHeight && pageY > height && positionY === 0) {
|
|
37
|
+
return 0;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
// if SafeAreaView is topped, check for full height
|
|
42
|
+
if (Math.round(height) >= Math.round(windowHeight) && pageY === 0) {
|
|
43
|
+
// if SafeAreaView is full height and at the top without any offset
|
|
44
|
+
return positionY === 0 ? insetBottom : 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// if SafeAreaView is topped with margin and not full height
|
|
48
|
+
if (height < windowHeight && positionY === 0 && pageY <= insetTop) {
|
|
49
|
+
return Math.max(0, insetBottom - (windowHeight - (height + pageY)));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (height < windowHeight && pageY < windowHeight && pageY > 0 && positionY > 0) {
|
|
53
|
+
return Math.max(0, insetBottom - (windowHeight - pageY));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// if SafeAreaView is not topped and not full height and is nested
|
|
57
|
+
if (height < windowHeight && pageY > 0 && pageY > windowHeight) {
|
|
58
|
+
return Math.max(0, insetBottom);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Default case handling scenarios not captured above
|
|
62
|
+
return Math.max(0, insetBottom - (windowHeight - height + paddingTop));
|
|
63
|
+
}
|
|
64
|
+
|
|
25
65
|
export default React.forwardRef<View, ViewProps>(
|
|
26
66
|
({ children, style, ...otherProps }, ref) => {
|
|
27
|
-
const [topInset, setTopInset] = useState(
|
|
28
|
-
safeAreaTurboModule.getInitialInsets().top
|
|
29
|
-
);
|
|
30
|
-
const [leftInset, setLeftInset] = useState(
|
|
31
|
-
safeAreaTurboModule.getInitialInsets().left
|
|
32
|
-
);
|
|
33
|
-
const [rightInset, setRightInset] = useState(
|
|
34
|
-
safeAreaTurboModule.getInitialInsets().right
|
|
35
|
-
);
|
|
36
|
-
const [bottomInset, setBottomInset] = useState(
|
|
37
|
-
safeAreaTurboModule.getInitialInsets().bottom
|
|
38
|
-
);
|
|
39
67
|
|
|
68
|
+
const safeAreaViewRef = React.useRef<View>(null);
|
|
69
|
+
|
|
70
|
+
const [topInset, setTopInset] = useState(safeAreaTurboModule.getInitialInsets().top);
|
|
71
|
+
const [leftInset, setLeftInset] = useState(safeAreaTurboModule.getInitialInsets().left);
|
|
72
|
+
const [rightInset, setRightInset] = useState(safeAreaTurboModule.getInitialInsets().right);
|
|
73
|
+
const [bottomInset, setBottomInset] = useState(safeAreaTurboModule.getInitialInsets().bottom);
|
|
74
|
+
|
|
75
|
+
const [measurement, setMeasurement] = useState({ x: 0, y: 0, width: 0, height: 0, pageX: 0, pageY: -1 });
|
|
76
|
+
const [layout, setLayout] = useState({ x: 0, y: 0, width: 0, height: 0 });
|
|
77
|
+
|
|
78
|
+
const measureView = () => {
|
|
79
|
+
safeAreaViewRef?.current?.measure((x, y, width, height, pageX, pageY) => {
|
|
80
|
+
setMeasurement({ x, y, width, height, pageX, pageY });
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
40
84
|
useEffect(
|
|
41
85
|
function subscribeToSafeAreaChanges() {
|
|
86
|
+
|
|
42
87
|
const subscription = (RCTDeviceEventEmitter as any).addListener(
|
|
43
88
|
"SAFE_AREA_INSETS_CHANGE",
|
|
44
89
|
(insets: SafeAreaInsets) => {
|
|
@@ -52,21 +97,39 @@ export default React.forwardRef<View, ViewProps>(
|
|
|
52
97
|
subscription.remove();
|
|
53
98
|
};
|
|
54
99
|
},
|
|
55
|
-
[setTopInset, setLeftInset, setRightInset, setBottomInset]
|
|
100
|
+
[setTopInset, setLeftInset, setRightInset, setBottomInset, measurement.pageY]
|
|
56
101
|
);
|
|
57
102
|
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
measureView();
|
|
105
|
+
}, []);
|
|
106
|
+
|
|
107
|
+
const isPaddingBottomExplicit = style?.paddingBottom !== undefined;
|
|
108
|
+
const isPaddingTopExplicit = style?.paddingTop !== undefined;
|
|
109
|
+
const isPaddingLeftExplicit = style?.paddingLeft !== undefined;
|
|
110
|
+
const isPaddingRightExplicit = style?.paddingRight !== undefined;
|
|
111
|
+
|
|
112
|
+
const windowHeight = Dimensions.get('window').height;
|
|
113
|
+
const paddingTop = getPaddingTop(topInset, measurement.pageY);
|
|
114
|
+
const paddingBottom = getPaddingBottom(bottomInset, topInset, paddingTop, measurement.height, windowHeight, measurement.pageY, layout.y);
|
|
115
|
+
|
|
58
116
|
return (
|
|
59
117
|
<View
|
|
60
|
-
ref={
|
|
118
|
+
ref={safeAreaViewRef}
|
|
61
119
|
style={[
|
|
62
120
|
style,
|
|
63
121
|
{
|
|
64
|
-
paddingTop:
|
|
65
|
-
paddingLeft: leftInset,
|
|
66
|
-
paddingRight: rightInset,
|
|
67
|
-
paddingBottom:
|
|
122
|
+
paddingTop: isPaddingTopExplicit ? style.paddingBottom : paddingTop,
|
|
123
|
+
paddingLeft: isPaddingLeftExplicit ? style.paddingLeft : leftInset,
|
|
124
|
+
paddingRight: isPaddingRightExplicit ? style.paddingRight : rightInset,
|
|
125
|
+
paddingBottom: isPaddingBottomExplicit ? style.paddingBottom : paddingBottom,
|
|
68
126
|
},
|
|
69
127
|
]}
|
|
128
|
+
onLayout={(event) => {
|
|
129
|
+
setLayout(event.nativeEvent.layout);
|
|
130
|
+
measureView();
|
|
131
|
+
otherProps?.onLayout && otherProps.onLayout(event);
|
|
132
|
+
}}
|
|
70
133
|
{...otherProps}
|
|
71
134
|
>
|
|
72
135
|
{children}
|
|
@@ -684,8 +684,6 @@ type State = {|
|
|
|
684
684
|
// RNOH patch - resolving flashScrollIndicators command on the JS side
|
|
685
685
|
// as it is currently not feasible on the native side
|
|
686
686
|
showScrollIndicator: boolean,
|
|
687
|
-
contentOffset: ?number,
|
|
688
|
-
contentHeight: ?number,
|
|
689
687
|
|};
|
|
690
688
|
|
|
691
689
|
const IS_ANIMATING_TOUCH_START_THRESHOLD_MS = 16;
|
|
@@ -774,8 +772,6 @@ class ScrollView extends React.Component<Props, State> {
|
|
|
774
772
|
// RNOH patch - resolving flashScrollIndicators command on the JS side
|
|
775
773
|
// as it is currently not feasible on the native side
|
|
776
774
|
showScrollIndicator: false,
|
|
777
|
-
contentOffset: null,
|
|
778
|
-
contentHeight: null,
|
|
779
775
|
};
|
|
780
776
|
|
|
781
777
|
componentDidMount() {
|
|
@@ -1192,15 +1188,14 @@ class ScrollView extends React.Component<Props, State> {
|
|
|
1192
1188
|
);
|
|
1193
1189
|
}
|
|
1194
1190
|
}
|
|
1195
|
-
this.setState({
|
|
1196
|
-
contentOffset: e.nativeEvent.contentOffset.y
|
|
1197
|
-
});
|
|
1198
1191
|
this._observedScrollSinceBecomingResponder = true;
|
|
1199
1192
|
this.props.onScroll && this.props.onScroll(e);
|
|
1200
1193
|
};
|
|
1201
1194
|
|
|
1202
1195
|
_handleLayout = (e: LayoutEvent) => {
|
|
1203
|
-
this.
|
|
1196
|
+
if (this.props.invertStickyHeaders === true) {
|
|
1197
|
+
this.setState({ layoutHeight: e.nativeEvent.layout.height });
|
|
1198
|
+
}
|
|
1204
1199
|
if (this.props.onLayout) {
|
|
1205
1200
|
this.props.onLayout(e);
|
|
1206
1201
|
}
|
|
@@ -1208,26 +1203,6 @@ class ScrollView extends React.Component<Props, State> {
|
|
|
1208
1203
|
|
|
1209
1204
|
_handleContentOnLayout = (e: LayoutEvent) => {
|
|
1210
1205
|
const { width, height } = e.nativeEvent.layout;
|
|
1211
|
-
/**
|
|
1212
|
-
* RNOH patch - Fixed the issue where sticky headers are in disordered position after foldable phone is expanded/folded.
|
|
1213
|
-
* When a foldable phone is expanded/folded, the height of the list items often changes,
|
|
1214
|
-
* causing the content height of the ScrollView to change.
|
|
1215
|
-
* But since the scroll event is not triggered, the position of the sticky headers is
|
|
1216
|
-
* still offset according to the original content height.
|
|
1217
|
-
* So we should recalculate the contentOffset based on the new contentHeight and trigger
|
|
1218
|
-
* the scroll event to fix the position of sticky headers
|
|
1219
|
-
*/
|
|
1220
|
-
let { contentOffset, contentHeight, layoutHeight } = this.state;
|
|
1221
|
-
if (contentOffset && contentHeight) {
|
|
1222
|
-
contentOffset *= (height - layoutHeight) / (contentHeight - layoutHeight);
|
|
1223
|
-
(contentOffset < 0) && (contentOffset = 0);
|
|
1224
|
-
this.scrollTo({ y: contentOffset, animated: false });
|
|
1225
|
-
this._scrollAnimatedValue.setValue(contentOffset);
|
|
1226
|
-
}
|
|
1227
|
-
this.setState({
|
|
1228
|
-
contentOffset,
|
|
1229
|
-
contentHeight: height
|
|
1230
|
-
});
|
|
1231
1206
|
this.props.onContentSizeChange &&
|
|
1232
1207
|
this.props.onContentSizeChange(width, height);
|
|
1233
1208
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-native-oh/react-native-harmony",
|
|
3
|
-
"version": "0.72.
|
|
3
|
+
"version": "0.72.29",
|
|
4
4
|
"description": "",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"./*.har"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@react-native-oh/react-native-harmony-cli": "^0.0.26-
|
|
52
|
+
"@react-native-oh/react-native-harmony-cli": "^0.0.26-20",
|
|
53
53
|
"colors": "^1.4.0",
|
|
54
54
|
"fs-extra": "^11.1.1",
|
|
55
55
|
"metro": "^0.76.3",
|
|
index 5e2274c..6f4d7b1 100644
|
|
|
Binary file
|