Skip to content

Commit c56a768

Browse files
committed
dont use weak ref, dont sync unconditionally
1 parent 4cd041b commit c56a768

File tree

3 files changed

+148
-140
lines changed

3 files changed

+148
-140
lines changed

src/core/native/index.tsx

Lines changed: 140 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,33 @@
11
import {
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';
99
import { Fiber } from 'react-reconciler';
10+
import { Measurement, MeasurementValue, ReactScanInternals } from '../..';
1011
import { instrument, Render } from '../instrumentation';
1112
import { getNearestHostFiber } from '../instrumentation/fiber';
12-
import { Measurement, MeasurementValue, ReactScanInternals } from '../..';
1313
import { getCopiedActiveOutlines, getLabelText } from '../utils';
1414

15-
import React, { useEffect, useRef, useSyncExternalStore } from 'react';
16-
import { Dimensions, Platform } from 'react-native';
1715
import {
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

4133
export 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) => {
109103
const 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
195201
instrumentNative();
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-
219203
export 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

303300
const 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

Comments
 (0)