8
8
*/
9
9
10
10
import type { Fiber } from 'react-reconciler/src/ReactFiber' ;
11
+ import type { TouchedViewDataAtPoint , InspectorData } from './ReactNativeTypes' ;
11
12
12
13
import {
13
14
findCurrentHostFiber ,
@@ -27,6 +28,7 @@ if (__DEV__) {
27
28
}
28
29
29
30
let getInspectorDataForViewTag ;
31
+ let getInspectorDataForViewAtPoint ;
30
32
31
33
if ( __DEV__ ) {
32
34
const traverseOwnerTreeUp = function ( hierarchy , instance : any ) {
@@ -80,15 +82,68 @@ if (__DEV__) {
80
82
const createHierarchy = function ( fiberHierarchy ) {
81
83
return fiberHierarchy . map ( fiber => ( {
82
84
name : getComponentName ( fiber . type ) ,
83
- getInspectorData : findNodeHandle => ( {
84
- measure : callback =>
85
- UIManager . measure ( getHostNode ( fiber , findNodeHandle ) , callback ) ,
86
- props : getHostProps ( fiber ) ,
87
- source : fiber . _debugSource ,
88
- } ) ,
85
+ getInspectorData : findNodeHandle => {
86
+ return {
87
+ props : getHostProps ( fiber ) ,
88
+ source : fiber . _debugSource ,
89
+ measure : callback => {
90
+ // If this is Fabric, we'll find a ShadowNode and use that to measure.
91
+ const hostFiber = findCurrentHostFiber ( fiber ) ;
92
+ const shadowNode =
93
+ hostFiber != null &&
94
+ hostFiber . stateNode !== null &&
95
+ hostFiber . stateNode . node ;
96
+
97
+ if ( shadowNode ) {
98
+ nativeFabricUIManager . measure ( shadowNode , function (
99
+ x ,
100
+ y ,
101
+ width ,
102
+ height ,
103
+ pageX ,
104
+ pageY ,
105
+ ) {
106
+ callback ( x , y , width , height , pageX , pageY ) ;
107
+ } ) ;
108
+ } else {
109
+ return UIManager . measure (
110
+ getHostNode ( fiber , findNodeHandle ) ,
111
+ callback ,
112
+ ) ;
113
+ }
114
+ } ,
115
+ } ;
116
+ } ,
89
117
} ) ) ;
90
118
} ;
91
119
120
+ const getInspectorDataForInstance = function ( closestInstance ) : InspectorData {
121
+ // Handle case where user clicks outside of ReactNative
122
+ if ( ! closestInstance ) {
123
+ return {
124
+ hierarchy : [ ] ,
125
+ props : emptyObject ,
126
+ selection : null ,
127
+ source : null ,
128
+ } ;
129
+ }
130
+
131
+ const fiber = findCurrentFiberUsingSlowPath ( closestInstance ) ;
132
+ const fiberHierarchy = getOwnerHierarchy ( fiber ) ;
133
+ const instance = lastNonHostInstance ( fiberHierarchy ) ;
134
+ const hierarchy = createHierarchy ( fiberHierarchy ) ;
135
+ const props = getHostProps ( instance ) ;
136
+ const source = instance . _debugSource ;
137
+ const selection = fiberHierarchy . indexOf ( instance ) ;
138
+
139
+ return {
140
+ hierarchy,
141
+ props,
142
+ selection,
143
+ source,
144
+ } ;
145
+ } ;
146
+
92
147
getInspectorDataForViewTag = function ( viewTag : number ) : Object {
93
148
const closestInstance = getClosestInstanceFromNode ( viewTag ) ;
94
149
@@ -117,13 +172,90 @@ if (__DEV__) {
117
172
source,
118
173
} ;
119
174
} ;
175
+
176
+ getInspectorDataForViewAtPoint = function (
177
+ findNodeHandle : ( componentOrHandle : any ) = > ?number ,
178
+ inspectedView : Object ,
179
+ locationX : number ,
180
+ locationY : number ,
181
+ callback : ( viewData : TouchedViewDataAtPoint ) = > mixed ,
182
+ ) : void {
183
+ let closestInstance = null ;
184
+
185
+ if ( inspectedView . _internalInstanceHandle != null ) {
186
+ // For Fabric we can look up the instance handle directly and measure it.
187
+ nativeFabricUIManager . findNodeAtPoint (
188
+ inspectedView . _internalInstanceHandle . stateNode . node ,
189
+ locationX ,
190
+ locationY ,
191
+ internalInstanceHandle => {
192
+ if ( internalInstanceHandle == null ) {
193
+ callback ( {
194
+ pointerY : locationY ,
195
+ frame : { left : 0 , top : 0 , width : 0 , height : 0 } ,
196
+ ...getInspectorDataForInstance ( closestInstance ) ,
197
+ } ) ;
198
+ }
199
+
200
+ closestInstance =
201
+ internalInstanceHandle . stateNode . canonical . _internalInstanceHandle ;
202
+ nativeFabricUIManager . measure (
203
+ internalInstanceHandle . stateNode . node ,
204
+ ( x , y , width , height , pageX , pageY ) => {
205
+ callback ( {
206
+ pointerY : locationY ,
207
+ frame : { left : pageX , top : pageY , width, height} ,
208
+ ...getInspectorDataForInstance ( closestInstance ) ,
209
+ } ) ;
210
+ } ,
211
+ ) ;
212
+ } ,
213
+ ) ;
214
+ } else if ( inspectedView . _internalFiberInstanceHandle != null ) {
215
+ // For Paper we fall back to the old strategy using the React tag.
216
+ UIManager . findSubviewIn (
217
+ findNodeHandle ( inspectedView ) ,
218
+ [ locationX , locationY ] ,
219
+ ( nativeViewTag , left , top , width , height ) => {
220
+ const inspectorData = getInspectorDataForInstance (
221
+ getClosestInstanceFromNode ( nativeViewTag ) ,
222
+ ) ;
223
+ callback ( {
224
+ ...inspectorData ,
225
+ pointerY : locationY ,
226
+ frame : { left, top, width, height} ,
227
+ touchedViewTag : nativeViewTag ,
228
+ } ) ;
229
+ } ,
230
+ ) ;
231
+ } else if ( __DEV__ ) {
232
+ console . error (
233
+ 'getInspectorDataForViewAtPoint expects to receieve a host component' ,
234
+ ) ;
235
+
236
+ return ;
237
+ }
238
+ } ;
120
239
} else {
121
240
getInspectorDataForViewTag = ( ) => {
122
241
invariant (
123
242
false ,
124
243
'getInspectorDataForViewTag() is not available in production' ,
125
244
) ;
126
245
} ;
246
+
247
+ getInspectorDataForViewAtPoint = (
248
+ findNodeHandle : ( componentOrHandle : any ) = > ?number ,
249
+ inspectedView : Object ,
250
+ locationX : number ,
251
+ locationY : number ,
252
+ callback : ( viewData : TouchedViewDataAtPoint ) => mixed ,
253
+ ) : void => {
254
+ invariant (
255
+ false ,
256
+ 'getInspectorDataForViewAtPoint() is not available in production.' ,
257
+ ) ;
258
+ } ;
127
259
}
128
260
129
- export { getInspectorDataForViewTag } ;
261
+ export { getInspectorDataForViewAtPoint , getInspectorDataForViewTag } ;
0 commit comments