11import {
2+ Animated ,
23 PanResponder ,
4+ Pressable ,
5+ Text as RNText ,
36 UIManager ,
47 View ,
5- Text as RNText ,
6- Pressable ,
7- Animated ,
88} from 'react-native' ;
99import { Fiber } from 'react-reconciler' ;
10+ import { Measurement , MeasurementValue , ReactScanInternals } from '../..' ;
1011import { instrument , Render } from '../instrumentation' ;
1112import { getNearestHostFiber } from '../instrumentation/fiber' ;
12- import { Measurement , MeasurementValue , ReactScanInternals } from '../..' ;
1313import { getCopiedActiveOutlines , getLabelText } from '../utils' ;
1414
15- import React , { useEffect , useRef , useSyncExternalStore } from 'react' ;
16- import { Dimensions , Platform } from 'react-native' ;
1715import {
1816 Canvas ,
1917 Group ,
18+ matchFont ,
2019 Rect ,
2120 Text ,
22- matchFont ,
2321} from '@shopify/react-native-skia' ;
24- import {
25- useSharedValue ,
26- useDerivedValue ,
27- withTiming ,
28- } from 'react-native-reanimated' ;
29- import { PendingOutline } from '../web/outline' ;
22+ import React , { useEffect , useRef , useState } from 'react' ;
23+ import { Dimensions , Platform } from 'react-native' ;
24+ import { useDerivedValue , useSharedValue } from 'react-native-reanimated' ;
25+ import { ActiveOutline , PendingOutline } from '../web/outline' ;
3026
31- export const genId = ( ) : string => {
32- const timeStamp = Date . now ( ) . toString ( 36 ) ;
33- const array = new Uint8Array ( 16 ) ;
34- crypto . getRandomValues ( array ) ;
35- const randomPart = Array . from ( array )
36- . map ( ( byte ) => byte . toString ( 16 ) . padStart ( 2 , '0' ) )
37- . join ( '' ) ;
38- return `${ timeStamp } -${ randomPart } ` ;
27+ export const genId = ( ) => {
28+ const timeStamp : number = performance . now ( ) ;
29+ const randomNum : number = Math . floor ( Math . random ( ) * 1000 ) ;
30+ return `${ timeStamp } -${ randomNum } ` ;
3931} ;
4032
4133export const measureFiber = (
@@ -44,6 +36,8 @@ export const measureFiber = (
4436) : Promise < MeasurementValue | null > => {
4537 return new Promise ( ( resolve ) => {
4638 const handleMeasurement = (
39+ x : number ,
40+ y : number ,
4741 width : number ,
4842 height : number ,
4943 pageX : number ,
@@ -64,27 +58,27 @@ export const measureFiber = (
6458 return ;
6559 }
6660
67- // // this probably doesn't do anything
68- // if (measurableNode.stateNode?._nativeTag) {
69- // // console.log("B");
70- // UIManager.measure(
71- // measurableNode.stateNode._nativeTag,
72- // handleMeasurement
73- // );
74- // return;
75- // }
61+ // this probably doesn't do anything
62+ if ( measurableNode . stateNode ?. _nativeTag ) {
63+ // console.log("B");
64+ UIManager . measure (
65+ measurableNode . stateNode . _nativeTag ,
66+ handleMeasurement ,
67+ ) ;
68+ return ;
69+ }
7670
77- // // this probably doesn't do anything
78- // if (measurableNode.stateNode?.measureInWindow) {
79- // // console.log("C");
80- // measurableNode.stateNode.measureInWindow(
81- // (x: number, y: number, width: number, height: number) => {
82- // // measureInWindow doesn't provide pageX/pageY, so they're same as x/y
83- // handleMeasurement(x, y, width, height, x, y);
84- // }
85- // );
86- // return;
87- // }
71+ // this probably doesn't do anything
72+ if ( measurableNode . stateNode ?. measureInWindow ) {
73+ // console.log("C");
74+ measurableNode . stateNode . measureInWindow (
75+ ( x : number , y : number , width : number , height : number ) => {
76+ // measureInWindow doesn't provide pageX/pageY, so they're same as x/y
77+ handleMeasurement ( x , y , width , height , x , y ) ;
78+ } ,
79+ ) ;
80+ return ;
81+ }
8882
8983 // If no measurement method found, try the first child
9084 measurableNode = measurableNode . child ;
@@ -109,67 +103,78 @@ export const assertNative = (measurement: Measurement) => {
109103const updateOutlines = async ( fiber : Fiber , render : Render ) => {
110104 const hostFiber = getNearestHostFiber ( fiber ) ;
111105 if ( ! hostFiber ) {
106+ // console.log('nope');
112107 return null ;
113108 }
114109 const measurement = await measureFiber ( fiber ) ;
115110 if ( ! measurement ) {
111+ // console.log('nope1');
116112 return null ;
117113 }
118114
119115 if ( ! measurement . pageX ) {
116+ // console.log('nope 2');
120117 // weird case come back to this
121118 return null ;
122119 }
123120
124- const existingOutline = ReactScanInternals . activeOutlines . find (
125- ( { outline } ) => {
126- return (
127- getKey ( assertNative ( outline . cachedMeasurement ) . value ) ===
128- getKey ( measurement )
129- ) ;
130- } ,
131- ) ;
132-
133- // if an outline exists we just update the renders
134- if ( existingOutline ) {
135- existingOutline . outline . renders . push ( render ) ;
136- existingOutline . text = getLabelText (
137- existingOutline . outline . renders ,
138- 'native' ,
121+ // console.log('nice', measurement);
122+ try {
123+ const existingOutline = ReactScanInternals . activeOutlines . find (
124+ ( { outline } ) => {
125+ return (
126+ getKey ( assertNative ( outline . cachedMeasurement ) . value ) ===
127+ getKey ( measurement )
128+ ) ;
129+ } ,
139130 ) ;
140- existingOutline . updatedAt = Date . now ( ) ;
141- ReactScanInternals . activeOutlines = getCopiedActiveOutlines ( ) ;
142- } else {
143- // create the outline for the first time
144- const measuredFiber = await measureFiber ( fiber ) ;
145- if ( ! measuredFiber ) {
146- return ;
131+ // console.log('hi', existingOutline);
132+
133+ // if an outline exists we just update the renders
134+ if ( existingOutline ) {
135+ existingOutline . outline . renders . push ( render ) ;
136+ existingOutline . text = getLabelText (
137+ existingOutline . outline . renders ,
138+ 'native' ,
139+ ) ;
140+ existingOutline . updatedAt = Date . now ( ) ;
141+ ReactScanInternals . activeOutlines = getCopiedActiveOutlines ( ) ;
142+ // console.log('boo');
143+ } else {
144+ // create the outline for the first time
145+ const measuredFiber = await measureFiber ( fiber ) ;
146+ if ( ! measuredFiber ) {
147+ return ;
148+ }
149+ const newOutline : PendingOutline = {
150+ cachedMeasurement : {
151+ kind : 'native' ,
152+ value : measuredFiber ,
153+ } ,
154+ fiber,
155+ renders : [ render ] ,
156+ } ;
157+ ReactScanInternals . activeOutlines . push ( {
158+ outline : newOutline ,
159+ alpha : null ! ,
160+ frame : null ! ,
161+ totalFrames : null ! ,
162+ id : genId ( ) ,
163+ resolve : ( ) => {
164+ // resolve();
165+ // todo, update this,
166+ // options.onPaintFinish?.(outline);
167+ } ,
168+ text : getLabelText ( newOutline . renders , 'native' ) ,
169+ updatedAt : Date . now ( ) ,
170+ color : null ! , // not used for now
171+ } ) ;
172+ // tell useSes there's new data
173+ // console.log('pushing outline', ReactScanInternals.activeOutlines.length);
174+ ReactScanInternals . activeOutlines = getCopiedActiveOutlines ( ) ;
147175 }
148- const newOutline : PendingOutline = {
149- cachedMeasurement : {
150- kind : 'native' ,
151- value : measuredFiber ,
152- } ,
153- fiber : new WeakRef ( fiber ) ,
154- renders : [ render ] ,
155- } ;
156- ReactScanInternals . activeOutlines . push ( {
157- outline : newOutline ,
158- alpha : null ! ,
159- frame : null ! ,
160- totalFrames : null ! ,
161- id : genId ( ) ,
162- resolve : ( ) => {
163- // resolve();
164- // todo, update this,
165- // options.onPaintFinish?.(outline);
166- } ,
167- text : getLabelText ( newOutline . renders , 'native' ) ,
168- updatedAt : Date . now ( ) ,
169- color : null ! , // not used for now
170- } ) ;
171- // tell useSes there's new data
172- ReactScanInternals . activeOutlines = getCopiedActiveOutlines ( ) ;
176+ } catch ( e ) {
177+ console . log ( e ) ;
173178 }
174179} ;
175180
@@ -182,6 +187,7 @@ export const instrumentNative = () => {
182187 async onRender ( fiber , render ) {
183188 // console.log('render', render.name);
184189 // port over metadata stuff later
190+ // console.log('render', render.name);
185191 options . onRender ?.( fiber , render ) ;
186192 updateOutlines ( fiber , render ) ;
187193 } ,
@@ -194,35 +200,9 @@ export const instrumentNative = () => {
194200// dont run this here
195201instrumentNative ( ) ;
196202
197- const useCleanupActiveLines = ( ) => {
198- const isPaused = useSyncExternalStore (
199- ( listener ) => ReactScanInternals . subscribe ( 'isPaused' , listener ) ,
200- ( ) => ReactScanInternals . isPaused ,
201- ) ;
202- useEffect ( ( ) => {
203- const interval = setInterval ( ( ) => {
204- if ( isPaused ) return ;
205-
206- const newActive = ReactScanInternals . activeOutlines . filter (
207- ( x ) => Date . now ( ) - x . updatedAt < 300 ,
208- ) ;
209- if ( newActive . length !== ReactScanInternals . activeOutlines . length ) {
210- ReactScanInternals . set ( 'activeOutlines' , newActive ) ;
211- }
212- } , 200 ) ;
213- return ( ) => {
214- clearInterval ( interval ) ;
215- } ;
216- } , [ isPaused ] ) ;
217- } ;
218-
219203export const ReactNativeScanEntryPoint = ( ) => {
220- useCleanupActiveLines ( ) ;
221- const isPaused = useSyncExternalStore (
222- ( listener ) => ReactScanInternals . subscribe ( 'isPaused' , listener ) ,
223- ( ) => ReactScanInternals . isPaused ,
224- ) ;
225-
204+ console . log ( 'running' ) ;
205+ const [ isEnabled , setIsEnabled ] = useState ( true ) ;
226206 const pan = useRef ( new Animated . ValueXY ( ) ) . current ;
227207
228208 const panResponder = useRef (
@@ -245,11 +225,28 @@ export const ReactNativeScanEntryPoint = () => {
245225 } ) ,
246226 ) . current ;
247227
228+ useEffect ( ( ) => {
229+ const interval = setInterval ( ( ) => {
230+ if ( ! isEnabled ) return ;
231+
232+ const newActive = ReactScanInternals . activeOutlines . filter (
233+ ( x ) => Date . now ( ) - x . updatedAt < 300 ,
234+ ) ;
235+ if ( newActive . length !== ReactScanInternals . activeOutlines . length ) {
236+ ReactScanInternals . set ( 'activeOutlines' , newActive ) ;
237+ }
238+ } , 200 ) ;
239+ return ( ) => {
240+ clearInterval ( interval ) ;
241+ } ;
242+ } , [ isEnabled ] ) ;
243+
248244 return (
249245 < >
250- { ! isPaused && < ReactNativeScan id = "react-scan-no-traverse" /> }
246+ { isEnabled && < ReactNativeScan id = "react-scan-no-traverse" /> }
251247
252248 < Animated . View
249+ id = "react-scan-no-traverse"
253250 style = { {
254251 position : 'absolute' ,
255252 bottom : 20 ,
@@ -260,9 +257,9 @@ export const ReactNativeScanEntryPoint = () => {
260257 { ...panResponder . panHandlers }
261258 >
262259 < Pressable
263- onPress = { ( ) => ( ReactScanInternals . isPaused = ! isPaused ) }
260+ onPress = { ( ) => setIsEnabled ( ! isEnabled ) }
264261 style = { {
265- backgroundColor : ! isPaused
262+ backgroundColor : isEnabled
266263 ? 'rgba(88, 82, 185, 0.9)'
267264 : 'rgba(88, 82, 185, 0.5)' ,
268265 paddingHorizontal : 12 ,
@@ -278,7 +275,7 @@ export const ReactNativeScanEntryPoint = () => {
278275 width : 8 ,
279276 height : 8 ,
280277 borderRadius : 4 ,
281- backgroundColor : ! isPaused ? '#4ADE80' : '#666' ,
278+ backgroundColor : isEnabled ? '#4ADE80' : '#666' ,
282279 } }
283280 />
284281 < RNText
@@ -302,17 +299,25 @@ export const ReactNativeScanEntryPoint = () => {
302299
303300const ReactNativeScan = ( { id : _ } : { id : string } ) => {
304301 const { width, height } = Dimensions . get ( 'window' ) ;
305- const outlines = useSyncExternalStore (
306- ( listener ) =>
307- ReactScanInternals . subscribe ( 'activeOutlines' , ( value ) => {
308- opacity . value = 1 ;
309- opacity . value = withTiming ( 0 , {
310- duration : 300 ,
311- } ) ;
312- listener ( ) ;
313- } ) ,
314- ( ) => ReactScanInternals . activeOutlines ,
315- ) ;
302+ // const [outlines, setOutlines] = React.useState<ActiveOutline[]>([]);
303+ // const outlines = useSyncExternalStore(
304+ // (listener) => ReactScanInternals.subscribe('activeOutlines', (value) => {
305+ // opacity.value = 1;
306+ // opacity.value = withTiming(0, {
307+ // duration: 300
308+ // })
309+ // listener()
310+ // }),
311+ // () => ReactScanInternals.activeOutlines,
312+ // );
313+
314+ const [ outlines , setOutlines ] = useState < Array < ActiveOutline > > ( [ ] ) ;
315+
316+ useEffect ( ( ) => {
317+ setInterval ( ( ) => {
318+ setOutlines ( ReactScanInternals . activeOutlines ) ;
319+ } , 50 ) ;
320+ } , [ ] ) ;
316321 const opacity = useSharedValue ( 1 ) ;
317322 const animatedOpacity = useDerivedValue ( ( ) => opacity . value ) ;
318323 const font = matchFont ( {
@@ -321,10 +326,12 @@ const ReactNativeScan = ({ id: _ }: { id: string }) => {
321326 fontWeight : 'bold' ,
322327 } ) ;
323328
329+ // console.log('outlines', outlines.length);
330+
324331 const getTextWidth = ( text : string ) => {
325332 return ( text || 'unknown' ) . length * 7 ;
326333 } ;
327-
334+ console . log ( 'render' ) ;
328335 return (
329336 < Canvas
330337 style = { {
@@ -343,6 +350,7 @@ const ReactNativeScan = ({ id: _ }: { id: string }) => {
343350 const labelPadding = 4 ;
344351 const labelWidth = textWidth + labelPadding * 2 ;
345352 const labelHeight = 12 ;
353+ // console.log('bruh',render.id);
346354 return (
347355 < Group key = { render . id } >
348356 < Rect
0 commit comments